<?php

namespace App\Jobs;

use App\Components\Functions;
use App\Events\LogAction;
use App\Models\Contract;
use App\Models\Hostel;
use App\Models\MoneyDetail;
use App\Models\MoneyInfo;
use App\Models\Notification;
use App\Models\RenterRoom;
use App\Models\Room;
use App\User;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

class GenerateNextContractInvoice implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    protected $contractId;
    protected $date;
    protected $user;

    public function __construct($contractId, $date = null, $user = null)
    {
        //
        $this->contractId = $contractId;
        $this->date = $date;
        $this->user = $user;

    }

    public function onConnection($connection)
    {
        $this->connection = 'redis';
        return $this;
    }

    public function onQueue($connection)
    {
        $this->queue = 'low';
        return $this;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function getLatestInvoice($contractId)
    {
        $contract = Contract::find($contractId);
        if (!$contract) {
            return null;
        }

        $moneyInfo = MoneyInfo::query()->where('contract_id', $contractId)
            ->whereIn('type', [MoneyInfo::VOUCHER_CONTRACT, MoneyInfo::VOUCHER_ROOM_PRICE])
            ->orderBy('date_action', 'desc')
            ->first();

        if (!$moneyInfo) {
            return null;
        }

        $moneyDetail = MoneyDetail::query()->where('money_info_id', $moneyInfo->id)
            ->orderBy('id', 'desc')
            ->first();
        if (!$moneyDetail) {
            return null;
        }

        return $moneyDetail->end_date;
    }


    public function handle()
    {
        $excepts = config('constants.EXCEPT_MONEY_INFO_NOTI');
        $date = $this->date;
        $contractId = $this->contractId;
        $contract = Contract::find($contractId);
        if (!$contract) {
            return;
        }

        $room = $contract->room;
        if (!$room) {
            return;
        }

        $hostelId = null;
        $owner = null;
        $roomId = $room->id;

        if (!$room->hostel) {
            return;
        }
        $hostel = $room->hostel;

        if ($room->hostel) {
            $hostelId = $room->hostel->id;
        }

        $ownerId = $hostel->owner_id;
        $owners = User::query()->where('id', $ownerId)
            ->get();
        $users = $hostel->staffs;
        if (empty($users->count())) {
            $users = User::query()->where('staff_owner_id', $ownerId)->get();
        }

        $users = $users->merge($owners);

        $renters = RenterRoom::query()->where('room_id', $room->id)
            ->where('contract_id', $contractId)
            ->with('contract')
            ->get();

        foreach ($renters as $renter) {

            if (!$renter->contract) {
                continue;
            }

            if ($renter->contract->status == Contract::LIQUIDATED) {
                continue;
            }

            $isStart = false;
            $contract = $renter->contract;

            if (!$contract) {
                continue;
            }

            $period = Functions::getPeriodNumber($contract->period);

//            $lastInvoiceDate = $contract->last_invoice_at;
//
//            if (empty($lastInvoiceDate)) {
//                $lastInvoiceDate = $this->getLatestInvoice($contract->id);
//            }

            $lastInvoiceDate = $this->getLatestInvoice($contract->id);

            if (empty($lastInvoiceDate)) {
                $lastInvoiceDate = $contract->last_invoice_at;
            }

            if (empty($lastInvoiceDate)) {
                $lastInvoiceDate = $contract->start_date->subDay()->format('Y-m-d');
                $isStart = true;
            }
            if (!empty($lastInvoiceDate)) {

                $dayCollect = $contract->day_collect;

                $lastInvoice = Carbon::createFromFormat('Y-m-d', $lastInvoiceDate);
                //dump($lastInvoice->toDateString());p
//				if ( ! Carbon::now()->greaterThanOrEqualTo( $lastInvoice ) ) {
//					continue;
//				}
                $startNextInvoiceCarbon = $lastInvoice->copy()->addDay();

                $startNextInvoiceMonth = $startNextInvoiceCarbon->month;
                $startNextInvoiceYear = $startNextInvoiceCarbon->year;
                $startNextInvoiceDay = $dayCollect;
                if (!$isStart) {

                    $startNextInvoiceDay = $startNextInvoiceCarbon->day;

                }
                if (checkdate($startNextInvoiceMonth, $startNextInvoiceDay, $startNextInvoiceYear)) {
                    $startNextInvoice = Carbon::createFromFormat('d-m-Y', $startNextInvoiceDay . '-' . $startNextInvoiceMonth . '-' . $startNextInvoiceYear);
                } else {
                    $startNextInvoiceDay = Carbon::createFromFormat('d-m-Y', '01-' . $startNextInvoiceMonth . '-' . $startNextInvoiceYear)->day;
                    $startNextInvoice = Carbon::createFromFormat('d-m-Y', $startNextInvoiceDay . '-' . $startNextInvoiceMonth . '-' . $startNextInvoiceYear);
                }


                if ($period > 1) {
                    $month = $startNextInvoice->copy()->firstOfMonth()->addMonth($period - 1)->month;
                    $year = $startNextInvoice->copy()->firstOfMonth()->addMonth($period - 1)->year;
                    if ($dayCollect <= $startNextInvoice->copy()->day) {
                        $month = $startNextInvoice->copy()->firstOfMonth()->addMonth($period)->month;
                        $year = $startNextInvoice->copy()->firstOfMonth()->addMonth($period)->year;
                    }
                } else {
                    $month = $startNextInvoice->copy()->month;
                    $year = $startNextInvoice->copy()->year;
                    if ($dayCollect <= $startNextInvoice->copy()->day) {
                        $month = $startNextInvoice->copy()->firstOfMonth()->addMonth()->month;
                        $year = $startNextInvoice->copy()->firstOfMonth()->addMonth()->year;
                    }
                }
                if (checkdate($month, $dayCollect, $year)) {
                    $to = Carbon::createFromFormat('d-m-Y', $dayCollect . '-' . $month . '-' . $year);
                } else {
                    $tempDayCollect = Carbon::createFromFormat('d-m-Y', '01-' . $month . '-' . $year)->lastOfMonth()->day;
                    $to = Carbon::createFromFormat('d-m-Y', $tempDayCollect . '-' . $month . '-' . $year);
                }

                if (!empty($date)) {
                    $dateCheck = Carbon::createFromFormat('d/m/Y', '01/' . $date)->endOfMonth()->endOfDay();
                    if ($startNextInvoice->copy()->greaterThan($dateCheck)) {
                        continue;
                    }
                }


                $range = $period;
                $sumMoney = $contract->room_price * $range;
                $money = 0;
                $name = 'Thu tiền phòng từ ' . $startNextInvoice->copy()->format('d/m/Y') . ' đến ' . $to->copy()->format('d/m/Y');

                //dd($startNextInvoice->copy()->format( 'd/m/Y' ),  $to->copy()->format( 'd/m/Y' ) );
                $moneyInfo = MoneyInfo::create([
                    'hostel_id' => $hostelId,
                    'room_id' => $roomId,
                    'date_action' => $startNextInvoice->copy()->toDateString(),
                    'contract_id' => $contract->id,
                    'user_id' => $contract->renter_id,
                    'type' => MoneyInfo::VOUCHER_ROOM_PRICE,
                    'amount' => $sumMoney,
                    'pay' => $money,
                    'remain' => $sumMoney - $money,
                    'money_info_name' => $name,
                    'bed_id' => $contract->bed_id,
                ]);

                $moneyInfo->update([
                    'name' => 'HD' . $moneyInfo->id . Carbon::now()->format('dmY')
                ]);

                MoneyDetail::create([
                    'hostel_id' => $hostelId,
                    'room_id' => $roomId,
                    'name' => $name,
                    'value' => $contract->room_price,
                    'money_info_id' => $moneyInfo->id,
                    'amount' => $money,
                    'note' => $name,
                    'start_date' => $startNextInvoice->copy()->toDateString(),
                    'end_date' => $to->copy()->toDateString(),
                    'qty' => $range,
                    'renter_id' => $contract->renter_id,
                    'sum_amount' => $sumMoney
                ]);

                $contract->last_invoice_at = $to->copy()->toDateString();
                $contract->save();
                if (!in_array($ownerId, $excepts)) {
                    foreach ($users as $user) {
                        Notification::create([
                            'to_user' => $user->id,
                            'title' => 'Thông báo hóa đơn từ itro.vn',
                            'user_id' => $user->id,
                            'content' => 'Đã có hoá đơn tiền phòng ' . $room->name . ' của ' . $renter->contract->name . ' từ ' . $startNextInvoice->copy()->format('d/m/Y') . ' - ' . $to->copy()->format('d/m/Y'),
                            'payload' => json_encode([
                                'id' => $moneyInfo->id,
                                'type' => config('constants.TRANSACTION')
                            ])
                        ]);
                    }
                }


//				dump( 'Process contract: ' . $contract->id );
//				dump( 'Room: ' . $contract->room->name );
//				dump( $startNextInvoice->copy()->format( 'd/m/Y' ) );
//				dump( $to->copy()->format( 'd/m/Y' ) );
//				dump( $money );
//				dump( $sumMoney );
//				dump( '----' );
            }

        }

        $user = Functions::getCurrentUser();
        if(!empty($this->date))
        {
        } else {
            if ($contract->hostel->type_rent == Hostel::TYPE_RENT_EVERY) {
                $desc = '{' . optional($this->user)->name . '} đã sinh hóa đơn tiền nhà cho hợp đồng khách khách {' . $contract->name . '} giường {' . $contract->bed->name . '} phòng {' . $contract->room->name . '} nhà {' . $contract->hostel->name . '}';
            } else {
                $desc = '{' . optional($this->user)->name . '} đã sinh hóa đơn tiền nhà cho hợp đồng khách khách {' . $contract->name . '} phòng {' . $contract->room->name . '} nhà {' . $contract->hostel->name . '}';
            }
            event(new LogAction([
                'type' => 'gen-contract-money-info',
                'user_id' => optional($user)->id,
                'object_id' => $contract->id,
                'hostel_id' => $contract->hostel_id,
                'room_id' => $contract->room_id,
                'properties' => $contract->toArray(),
                'desc' => $desc
            ]));
        }
    }
}
