<?php

namespace App\Models;

use App\Components\Functions;
use App\Events\LogAction;
use App\User;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Spatie\Activitylog\Traits\LogsActivity;


class Contract extends Model
{
    //
    const VALIDATED = 0;
    const EXPIRE = 1;
    const LIQUIDATED = 2;

    const RETURNED_DEPOSIT = 1;
    const NOT_RETURNED_DEPOSIT = 2;
    const NEVER_RETURNED_DEPOSIT = 3;

    use SoftDeletes;
    use LogsActivity;

    protected static $logAttributes = ['*'];

    protected $fillable = [
        'code',
        'status',
        'room_id',
        'hostel_id',
        'user_id',
        'date_contract',
        'date_enable',
        'start_date',
        'end_date',
        'room_price',
        'period',
        'type_rent',
        'is_collected',
        'collect_to',
        'deposit',
        'phone',
        'name',
        'id_number',
        'email',
        'date_join',
        'customer_image',
        'created_at',
        'updated_at',
        'deleted_at',
        'renter_id',
        'contract_status',
        'date_end_contract',
        'id_number_front',
        'id_number_back',
        'is_return_deposit',
        'is_return_money_info',
        'reference',
        'reserve_id',
        'date_voucher',
        'day_collect',
        'last_invoice_at',
        'last_invoice_id',
        'bed_id',
        'renter_signature',
        'leave_day',
        'amount_return_deposit',
        'note',
        'contract_note'
    ];

    protected $dates = [
        //  'collect_to',
        'date_enable',
        'date_contract',
        'start_date',
        'end_date',
        'created_at',
        'updated_at',
        'deleted_at',
        'date_join',
        'leave_day',

    ];


    public static function boot()
    {
        parent::boot();
        static::saved(function ($contract) {
            self::updateEmptyRooms($contract);
        });
        static::updated(function ($contract) {
            self::updateEmptyRooms($contract);
            if ($contract->status == Contract::LIQUIDATED) {
                Deposit::query()->where('contract_id', $contract->id)->delete();
            }

            $deposit = $contract->deposit;

            if ($deposit == 0) {

            }

            $name = 'Thu tiền đặt cọc Hợp đồng ' . $contract->code;

            if ($deposit == 0) {
                CollectSpend::query()
                    ->where('note', $name)
                    ->delete();

                Transaction::query()
                    ->where('note', $name)
                    ->delete();
            } else {

                Transaction::query()
                    ->where('note', $name)
                    ->update([
                        'amount' => $deposit,
                        'payer' => $contract->name
                    ]);

                CollectSpend::query()
                    ->where('note', $name)
                    ->update([
                        'amount' => $deposit,
                        'payer' => $contract->name
                    ]);


            }
            if ($contract && $contract->hostel && $contract->room) {
                Deposit::query()
                    ->updateOrCreate([
                        'contract_id' => $contract->id
                    ], [
                        'contract_id' => $contract->id,
                        'hostel_id' => $contract->hostel->id,
                        'room_id' => $contract->room->id,
                        'date_action' => Carbon::now(),
                        'amount' => $deposit
                    ]);
            }


            // đổi HĐ sang phòng khác
            if ($contract->isDirty('room_id') || $contract->isDirty('bed_id') || $contract->isDirty('hostel_id')) {
                MoneyInfo::query()
                    ->where('contract_id', $contract->id)
                    ->update([
                        'hostel_id' => $contract->hostel_id,
                        'room_id' => $contract->room_id,
                        'bed_id' => $contract->bed_id
                    ]);

                MoneyDetail::query()
                    ->whereHas('moneyInfo.contract', function ($q) use ($contract) {
                        $q->where('contracts.id', $contract->id);
                    })
                    ->update([
                        'hostel_id' => $contract->hostel_id,
                        'room_id' => $contract->room_id
                    ]);

                CollectSpend::query()
                    ->where('contract_id', $contract->id)
                    ->update([
                        'hostel_id' => $contract->hostel_id,
                        'room_id' => $contract->room_id
                    ]);

                Transaction::query()
                    ->whereHas('moneyInfo.contract', function ($q) use ($contract) {
                        $q->where('contracts.id', $contract->id);
                    })
                    ->update([
                        'hostel_id' => $contract->hostel_id,
                        'room_id' => $contract->room_id,
                        'bed_id' => $contract->bed_id
                    ]);

                RenterRoom::query()
                    ->where(function ($q) use ($contract) {
                        $q->orWhere('contract_id', $contract->id);
                        $q->orWhere('room_contract_id', $contract->id);
                    })
                    ->update([
                        'hostel_id' => $contract->hostel_id,
                        'room_id' => $contract->room_id,
                        'bed_id' => $contract->bed_id
                    ]);
                $user = User::query()->where('phone', $contract->phone)->where('type', User::RENTER)->first();
                if ($user) {
                    RenterBike::query()
                        ->where('renter_id', $user->id)
                        ->update([
                            'room_id' => $contract->room_id
                        ]);
                }

                Renter::query()
                    ->whereHas('contractItem', function ($q) use ($contract) {
                        $q->where('contracts.id', $contract->id);
                    })
                    ->update([
                        'hostel_id' => $contract->hostel_id,
                        'room_id' => $contract->room_id
                    ]);

                StatisticLog::query()
                    ->where('contract_id', $contract->id)
                    ->update([
                        'hostel_id' => $contract->hostel_id,
                        'room_id' => $contract->room_id
                    ]);

                StatisticMonth::query()
                    ->where('contract_id', $contract->id)
                    ->update([
                        'hostel_id' => $contract->hostel_id,
                        'room_id' => $contract->room_id
                    ]);

                if ($contract->isDirty('bed_id')) {
                    $roomBedBefore = $contract->getOriginal('bed_id');
                    RoomBed::query()
                        ->where('id', $roomBedBefore)
                        ->update([
                            'status' => RoomBed::AVAILABLE
                        ]);
                    RoomBed::query()
                        ->where('id', $contract->bed_id)
                        ->update([
                            'status' => RoomBed::UNAVAILABLE
                        ]);
                }

            }
            $user = Functions::getCurrentUser();
            if (!$user) {
                return;
            }
            if (!$contract->isDirty('status')) {

//                if ($contract->status != Contract::LIQUIDATED) {
//
//                    $desc = '{' . optional($user)->name . '}' . ' đã cập nhật hợp đồng khách {' . $contract->name . '}, phòng {' . $contract->room->name . '}, nhà {' . $contract->hostel->name . '}';
//                    if ($contract->hostel->type_rent == Hostel::TYPE_RENT_EVERY) {
//                        $desc = '{' . optional($user)->name . '} đã cập nhật hợp đồng khách {' . $contract->name . '}, giường {' . optional($contract->bed)->name .
//                            '} phòng {' . optional($contract->room)->name . '}, nhà {' . optional($contract->hostel)->name . '}';
//                    }
//                    event(new LogAction([
//                        'type' => 'update-contract',
//                        'user_id' => optional($user)->id,
//                        'object_id' => $contract->id,
//                        'hostel_id' => $contract->hostel->id,
//                        'room_id' => $contract->room->id,
//                        'properties' => $contract->toArray(),
//                        'desc' => $desc
//                    ]));
//                }
            } else if ($contract->status == Contract::LIQUIDATED) {
                $desc = '{' . optional($user)->name . '}' . ' đã thanh lý hợp đồng khách {' . $contract->name . '}, phòng {' . $contract->room->name . '}, nhà {' . $contract->hostel->name . '}';
                if ($contract->hostel->type_rent == Hostel::TYPE_RENT_EVERY) {
                    $desc = '{' . optional($user)->name . '} đã thanh lý hợp đồng khách {' . $contract->name . '}, giường {' . optional($contract->bed)->name .
                        '} phòng {' . optional($contract->room)->name . '}, nhà {' . optional($contract->hostel)->name . '}';
                }
                event(new LogAction([
                    'type' => 'end-contract',
                    'user_id' => optional($user)->id,
                    'object_id' => $contract->id,
                    'hostel_id' => $contract->hostel->id,
                    'room_id' => $contract->room->id,
                    'desc' => $desc
                ]));
            }
        });
        static::created(function ($contract) {
            self::updateEmptyRooms($contract);

            if ($contract->deposit > 0) {
                Deposit::create([
                    'contract_id' => $contract->id,
                    'amount' => $contract->deposit,
                    'date_action' => $contract->created_at,
                    'room_id' => $contract->room_id,
                    'hostel_id' => $contract->hostel_id,
                ]);
            }

            $user = Functions::getCurrentUser();
            if ($user) {
                $desc = '{' . $user->name . '} đã tạo hợp đồng khách {' . $contract->name . '}, phòng {' . $contract->room->name . '}, nhà {' . $contract->hostel->name . '}';
                if ($contract->hostel->type_rent == Hostel::TYPE_RENT_EVERY) {
                    $desc = '{' . $user->name . '} đã tạo hợp đồng khách {' . $contract->name . '}, giường {' . optional($contract->bed)->name .
                        '} phòng {' . optional($contract->room)->name . '}, nhà {' . optional($contract->hostel)->name . '}';
                }
                event(new LogAction([
                    'type' => 'create-contract',
                    'user_id' => optional($user)->id,
                    'object_id' => $contract->id,
                    'hostel_id' => $contract->hostel->id,
                    'room_id' => $contract->room->id,
                    'properties' => $contract->toArray(),
                    'desc' => $desc
                ]));
            }

        });
        static::deleted(function ($item) {
            Deposit::query()->where('contract_id', $item->id)->delete();

            ElectricWater::query()
                ->where('contract_id', $item->id)
                ->delete();

            $renter = Renter::query()
                ->where('user_id', $item->renter_id)
                ->where('room_id', $item->room_id)
                ->first();
            if ($renter) {
                $renter->delete();
            }
            self::updateEmptyRooms($item);

            $user = Functions::getCurrentUser();
            if ($user) {
                $desc = '{' . $user->name . '} đã xóa hợp đồng khách {' . $item->name . '}, {phòng ' . $item->room->name . '}, nhà {' . $item->hostel->name . '}';
                if ($item->hostel->type_rent == Hostel::TYPE_RENT_EVERY) {
                    $desc = '{' . $user->name . '} đã xóa hợp đồng khách {' . $item->name . '}, giường {' . optional($item->bed)->name .
                        '} phòng {' . optional($item->room)->name . '}, nhà {' . optional($item->hostel)->name . '}';
                }
                event(new LogAction([
                    'type' => 'delete-contract',
                    'user_id' => optional($user)->id,
                    'object_id' => $item->id,
                    'hostel_id' => $item->hostel->id,
                    'room_id' => $item->room->id,
                    'properties' => $item->toArray(),
                    'desc' => $desc
                ]));
            }

        });

    }

    public function getLastInvoiceAtTextAttribute()
    {
        $lastInvoiceAt = $this->attributes['last_invoice_at'];
        $date = null;
        if (!empty($lastInvoiceAt)) {
            $date = Carbon::parse($lastInvoiceAt);
        }

        $lastInvoiceAt = Functions::getLatestInvoice2($this->attributes['id']);

        if (!empty($lastInvoiceAt)) {
            $date = Carbon::parse($lastInvoiceAt);

        }


        if (!empty($date)) {
            if (isset($this->attributes['day_collect'])) {

                if ($date->copy()->day != $this->attributes['day_collect']) {
                    $month = $date->copy()->month;
                    if ($date->copy()->isLastOfMonth()) {
                        return $date->copy()->format('d/m/Y');
                    }

                    if (checkdate($month, $this->attributes['day_collect'], $date->copy()->year)) {
                        if ($date->copy()->isLastOfMonth()) {
                            return $date->copy()->format('d/m/Y');
                        }
                        return $this->attributes['day_collect'] . '/' . $date->copy()->format('m/Y');
                    }

                    return $date->copy()->lastOfMonth()->format('d/m/Y');
                }
            }

            return $date->copy()->format('d/m/Y');
        }

        return null;
    }

    public static function updateEmptyRooms($contract)
    {
        Functions::updateHostelEmptyRooms($contract->hostel_id);
    }

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function renter()
    {
        return $this->belongsTo(Renter::class, 'renter_id', 'user_id');
    }

    public function renterWithTrashed()
    {
        return $this->belongsTo(Renter::class, 'renter_id', 'user_id')->withTrashed();
    }


    public function getPeriodTextAttribute()
    {
        $period = $this->attributes['period'];
        $message = '';

        switch ($period) {
            case Room::ONE_MONTH_PERIOD:
                $message = '1 tháng';
                break;

            case Room::TWO_MONTH_PERIOD:
                $message = '2 tháng';
                break;

            case Room::THREE_MONTH_PERIOD:
                $message = '3 tháng';
                break;
            case Room::FOUR_MONTH_PERIOD:
                $message = '4 tháng';
                break;
            case 6:
                $message = '6 tháng';
                break;

            case 12:
                $message = '1 năm';
                break;

            case Room::FIVE_MONTH_PERIOD:
                $message = '5 tháng';
                break;

            case Room::SIX_MONTH_PERIOD:
                $message = '6 tháng';
                break;


            default:
                $message = 'Chưa rõ';
                break;
        }

        return $message;
    }

    public function getTypeRentTextAttribute()
    {
        $period = $this->attributes['type_rent'];
        $message = '';

        switch ($period) {
            case Room::START_PERIOD:
                $message = 'Đầu kỳ';
                break;

            case Room::LAST_PERIOD:
                $message = 'Cuối kỳ';
                break;

            default:
                $message = 'Chưa rõ';
                break;
        }

        return $message;
    }

    public function getStatusTextAttribute()
    {
        $status = $this->attributes['status'];
        $now = Carbon::now();
        $endDate = Carbon::parse($this->end_date);
        $left = $now->diffInDays($endDate, false);

        if ($status == self::VALIDATED) {
            if ($left < 0) {
                return '<label class="label label-warning">Quá hạn (' . $left * -1 . ' ngày)</label>';
            }
            return '<label class="label label-success">Còn hạn (' . $left . ' ngày)</label>';
        } else if ($status == self::LIQUIDATED) {
            return '<label class="label label-danger">Đã thanh lý ' . ' </label>';
        } else if ($status == self::EXPIRE) {
            return '<label class="label label-warning">Đã hết hạn (' . $left . ' ngày)</label>';
        }
    }

    public function room()
    {
        return $this->belongsTo(Room::class, 'room_id', 'id')->withTrashed();
    }

    public function bed()
    {
        return $this->belongsTo(RoomBed::class, 'bed_id', 'id');
    }

    public function hostel()
    {
        return $this->belongsTo(Hostel::class);
    }

    public function fees()
    {
        return $this->belongsToMany(HostelFee::class, 'contract_fees', 'contract_id', 'fee_id')->withPivot('qty');
    }

    public function collectSpends(Carbon $startDate = null, Carbon $endDate = null)
    {
        if (!empty($startDate) && !empty($endDate)) {
            return $this->hasMany(CollectSpend::class)->whereBetween('date_action', [
                $startDate->copy()->startOfMonth(),
                $endDate->copy()->endOfMonth()
            ]);
        }

        return $this->hasMany(CollectSpend::class);
    }

    public function moneyInfos()
    {
        return $this->hasMany(MoneyInfo::class);
    }

    public function moneyInfoServices()
    {
        return $this->hasMany(MoneyInfo::class)->where('money_infos.type', MoneyInfo::VOUCHER_SERVICE);
    }

    public function moneyInfoRooms()
    {
        return $this->hasMany(MoneyInfo::class)->whereIn('money_infos.type', [MoneyInfo::VOUCHER_ROOM_PRICE, MoneyInfo::VOUCHER_CONTRACT]);
    }
}
