<?php

namespace App\Jobs;

use App\Components\Functions;
use App\Models\Action;
use App\Models\Hostel;
use App\Models\HostelFee;
use App\Models\Room;
use App\Models\RoomBed;
use App\Services\ContractService;
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 ImportContract implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    protected $filePath;
    protected $ownerId;
    protected $userId;
    protected $pusher;

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

    public function __construct($filePath, $ownerId, $userId)
    {
        //
        $this->filePath = $filePath;
        $this->ownerId = $ownerId;
        $this->pusher = \PusherService::getClient();
        $this->userId = $userId;
    }

    /**
     * Execute the job.
     *
     * @return void
     */

    public function pushErrorMessage($action, $message)
    {
        $errorMessages = cache()->get($action->id . '-error-messages');
        if (empty($errorMessages)) {
            $errorMessages = [];
        }
        $errorMessages[] = $message;
        cache()->put($action->id . '-error-messages', $errorMessages, 600);
    }

    public function triggerMessage()
    {
        $pusher = $this->pusher;
        $channelName = 'job-actions-' . $this->ownerId;
        $actions = Action::query()
            ->where('user_id', $this->ownerId)
            ->whereNull('finished_at')
            ->where('created_at', '>=', Carbon::now()->subDay(1)->startOfDay())
            ->get();
        $content = view('admin2.progress.actions', compact('actions'))->render();
        $pusher->trigger($channelName, 'action-content', $content);
    }

    public function handle()
    {
        //
        $cnt = 0;

        $pusher = $this->pusher;
        $filePath = $this->filePath;
        $ownerId = $this->ownerId;
        $channelName = 'job-actions-' . $this->ownerId;


        $action = Action::create([
            'file' => $this->filePath,
            'user_id' => $this->userId,
            'type' => 'import-contract',
        ]);
        cache()->forget($action->id . '-error-messages');
        cache()->forget($action->id . '-success-message');


        $items = \Excel::selectSheetsByIndex(0)->load($filePath, function ($reader) {
            $reader->noHeading()->takeRows(600);
        })->skip(1)
            ->get();


        $number = count($items);


        cache()->put($action->id . '-progress', [
            'processed' => $cnt,
            'total' => 0,
            'percent' => round($cnt * 100 / $number)
        ], 600);

        $this->triggerMessage();
        $indexArr = [];
        $headerArr = [];
        $headers = $items[0];
        foreach ($headers as $key => $header) {
            $name = str_replace('(Số đầu)', '', $header);
            $name = str_replace('(Số lượng)', '', $name);
            $name = str_replace('(ngày/tháng/năm)', '', $name);
            $name = trim($name);
            $headerArr[$key] = $name;
        }

      //  dd($items);
        $lastKey = array_key_last($headerArr);


        unset($items[0]);
        foreach ($items as $key => $item) {

            $hostelName = isset($item[0]) ? trim($item[0]) : null;
            $roomName = isset($item[1]) ? trim($item[1]) : null;

            if (empty($hostelName) || empty($roomName)) {
                $cnt++;

                $errorMessage = 'Không được bỏ tên nhà trọ hoặc phòng trọ';
                $this->pushErrorMessage($action, $errorMessage);
                cache()->put($action->id . '-progress', [
                    'processed' => $cnt,
                    'total' => count($items),
                    'percent' => round($cnt * 100 / (count($items)))
                ], 600);
                $this->triggerMessage();
                continue;
            }

            if ($item[3] instanceof Carbon) {
                $dateContract = $item[3]->format('d/m/Y');
            } else {
                $dateContract = trim($item[3]);
            }



            if ($item[4] instanceof Carbon) {
                $endDate = $item[4]->format('d/m/Y');
            } else {
                $endDate = trim($item[4]);
            }

            if ($item[9] instanceof Carbon) {
                $collectTo = $item[9]->format('d/m/Y');
            } else {
                $collectTo = trim($item[9]);
            }

            if ($item[13] instanceof Carbon) {
                $birthday = $item[13]->format('d/m/Y');
            } else {
                $birthday = trim($item[13]);
            }

            $bedName = trim($item[2]);
            $roomPrice = trim($item[5]);
            $deposit = trim($item[6]);
            $period = trim($item[7]);
            $dayCollect = trim($item[8]);
            $phone = trim($item[10]);
            if (empty($phone)) {

                $errorMessage = 'Không được bỏ trống SĐT khách lập HĐ, phòng: ' . $roomName;
                $this->pushErrorMessage($action, $errorMessage);

                $cnt++;
                cache()->put($action->id . '-progress', [
                    'processed' => $cnt,
                    'total' => count($items),
                    'percent' => round($cnt * 100 / (count($items)))
                ], 600);
                $this->triggerMessage();
                continue;
            }
            $name = trim($item[11]);
            $email = trim($item[12]);

            $idNumber = trim($item[14]);
            $idNumberDate = trim($item[15]);

            $idNumberLocation = trim($item[16]);

            if (empty($endDate)) {

                $errorMessage = 'Không được bỏ trống hạn HĐ, phòng: ' . $roomName;
                $this->pushErrorMessage($action, $errorMessage);
                $pusher->trigger($channelName, 'error', $errorMessage);
                $cnt++;
                cache()->put($action->id . '-progress', [
                    'processed' => $cnt,
                    'total' => count($items),
                    'percent' => round($cnt * 100 / (count($items)))
                ], 600);
                $this->triggerMessage();
                continue;
            }

            $hostel = Hostel::query()
                ->where('name', $hostelName)
                ->where('owner_id', $ownerId)
                ->first();
            if (!$hostel) {
                $errorMessage = 'Không tìm thấy nhà trọ ' . $hostelName . ' trên hệ thống';
                $this->pushErrorMessage($action, $errorMessage);
                $res = $pusher->trigger($channelName, 'error', $errorMessage);

                $cnt++;
                cache()->put($action->id . '-progress', [
                    'processed' => $cnt,
                    'total' => count($items),
                    'percent' => round($cnt * 100 / (count($items)))
                ], 600);
                $this->triggerMessage();
                continue;
            }


            $room = Room::query()
                ->where('name', $roomName)
                ->where('hostel_id', $hostel->id)
                ->first();

            if (!$room) {
                $errorMessage = 'Không tìm thấy phòng trọ ' . $roomName . ' thuộc nhà trọ ' . $hostelName . ' trên hệ thống';
                $this->pushErrorMessage($action, $errorMessage);


                $cnt++;
                cache()->put($action->id . '-progress', [
                    'processed' => $cnt,
                    'total' => count($items),
                    'percent' => round($cnt * 100 / (count($items)))
                ], 600);
                $this->triggerMessage();
                continue;
            }


            $bedId = null;

            if ($hostel->type_rent == Hostel::TYPE_RENT_EVERY) {
                if (empty($bedName)) {
                    $errorMessage = 'Không được bỏ trống tên giường, phòng: ' . $roomName;
                    $this->pushErrorMessage($action, $errorMessage);
                    $pusher->trigger($channelName, 'error', $errorMessage);
                    $cnt++;
                    cache()->put($action->id . '-progress', [
                        'processed' => $cnt,
                        'total' => count($items),
                        'percent' => round($cnt * 100 / (count($items)))
                    ], 600);
                    $this->triggerMessage();
                    continue;
                }

                $bed = RoomBed::query()->where('room_id', $room->id)
                    ->where('name', $bedName)
                    ->first();
                if (!$bed) {
                    $errorMessage = 'Không tìm thấy giường ' . $bedName . ' cho phòng ' . $roomName;
                    $this->pushErrorMessage($action, $errorMessage);
                    $cnt++;
                    cache()->put($action->id . '-progress', [
                        'processed' => $cnt,
                        'total' => count($items),
                        'percent' => round($cnt * 100 / (count($items)))
                    ], 600);
                    $this->triggerMessage();
                    continue;
                }

                $bedId = $bed->id;

            }



            $data = [
                'hostel' => $hostel,
                'hostel_id' => $hostel->id,
                'period' => empty($period) ? 1 : $period,
                'room' => $room,
                'room_id' => $room->id,
                'date_contract' => $dateContract,
                'end_date' => $endDate,
                'room_price' => Functions::filterInputNumber($roomPrice),
                'deposit' => Functions::filterInputNumber($deposit),
                'day_collect' => $dayCollect,
                'collect_to' => $collectTo,
                'is_collected' => !empty($collectTo) ? 'on' : 'off',
                'phone' => $phone,
                'name' => $name,
                'email' => $email,
                'birthday' => $birthday,
                'id_number' => $idNumber,
                'id_number_date' => $idNumberDate,
                'id_number_location' => $idNumberLocation,
                'bed_id' => $bedId,
                'residence_status' => false,
                'date_end_residence' => null,
                'type_rent' => Room::START_PERIOD
            ];


            if (!empty($data['end_date'])) {
                if ($data['end_date'] instanceof Carbon) {
                    $data['end_date'] = $data['end_date']->copy()->toDateString();

                } else if (is_numeric($data['end_date'])) {
                    $data['end_date'] = \PHPExcel_Shared_Date::ExcelToPHPObject($data['end_date']);
                    $data['end_date'] = Carbon::instance($data['end_date'])->toDateString();
                } else if (is_string($data['date_contract'])) {
                    $data['end_date'] = Carbon::createFromFormat('d/m/Y', $data['end_date'])->toDateString();
                }
            }
            if (!empty($data['collect_to'])) {
                if ($data['collect_to'] instanceof Carbon) {
                    $data['collect_to'] = $data['collect_to']->copy()->toDateString();

                } else if (is_numeric($data['collect_to'])) {
                    $data['collect_to'] = \PHPExcel_Shared_Date::ExcelToPHPObject($data['collect_to']);
                    $data['collect_to'] = Carbon::instance($data['collect_to'])->toDateString();
                } else if (is_string($data['collect_to'])) {
                    $data['collect_to'] = Carbon::createFromFormat('d/m/Y', $data['collect_to'])->toDateString();
                }
            }

            if (!empty($data['id_number_date'])) {
                if ($data['id_number_date'] instanceof Carbon) {
                    $data['id_number_date'] = $data['id_number_date']->copy()->toDateString();

                } else if (is_numeric($data['id_number_date'])) {
                    $data['id_number_date'] = \PHPExcel_Shared_Date::ExcelToPHPObject($data['id_number_date']);
                    $data['id_number_date'] = Carbon::instance($data['id_number_date'])->toDateString();
                } else if (is_string($data['id_number_date'])) {
                    try {
                        $data['id_number_date'] = Carbon::createFromFormat('d/m/Y', $data['id_number_date'])->toDateString();
                    } catch (\Exception $exception) {
                        $data['id_number_date'] = Carbon::parse($data['id_number_date'])->toDateString();
                    }
                }
            }


            if (!empty($data['date_contract'])) {

                if ($data['date_contract'] instanceof Carbon) {
                    $data['date_contract'] = $data['date_contract']->copy()->toDateString();

                } else if (is_numeric($data['date_contract'])) {
                    $data['date_contract'] = \PHPExcel_Shared_Date::ExcelToPHPObject($dateContract);
                    $data['date_contract'] = Carbon::instance($data['date_contract'])->toDateString();
                } else if (is_string($data['date_contract'])) {
                    $data['date_contract'] = Carbon::createFromFormat('d/m/Y', $data['date_contract'])->toDateString();
                }
                $data['date_enable'] = $data['date_contract'];
                $data['start_date'] = $data['date_contract'];
                $data['date_join'] = $data['date_contract'];
            }

            $data['fees'] = null;

            for ($i = 17; $i <= $lastKey; $i++) {
                if (!isset($headerArr[$i])) {
//                    $cnt++;
//                    cache()->put($action->id . '-progress', [
//                        'processed' => $cnt,
//                        'total' => count($items),
//                        'percent' => round($cnt * 100 / (count($items)))
//                    ], 600);
                    continue;
                }

                $feeName = $headerArr[$i];
                $fee = HostelFee::query()
                    ->where('name', $feeName)
                    ->where('hostel_id', $hostel->id)
                    ->first();
                if (!$fee) {
                    //$cnt++;
                    cache()->put($action->id . '-progress', [
                        'processed' => $cnt,
                        'total' => count($items),
                        'percent' => round($cnt * 100 / (count($items)))
                    ], 600);
                    $this->triggerMessage();
                    continue;
                }

                if (!is_numeric($item[$i])) {
                    //$cnt++;
                    cache()->put($action->id . '-progress', [
                        'processed' => $cnt,
                        'total' => count($items),
                        'percent' => round($cnt * 100 / (count($items)))
                    ], 600);
                    $this->triggerMessage();
                    continue;
                }

                $data['fees'][$fee->id] = ['qty' => intval($item[$i])];
            }

            $contractService = new ContractService($data);
            $res = $contractService->store();
            $cnt++;

            if ($res['status'] == 0) {
                $errorMessage = $res['message'];
                $this->pushErrorMessage($action, $errorMessage);
            }

            cache()->put($action->id . '-success-message', 'Đã import thành công: ' . $cnt . '/' . count($items) . ' hợp đồng', 600);
            cache()->put($action->id . '-progress', [
                'processed' => $cnt,
                'total' => count($items),
                'percent' => round($cnt * 100 / count($items))
            ], 600);
            $res = $pusher->trigger($channelName, 'success', 'Đã import thành công: ' . $cnt . '/' . count($items) . ' hợp đồng');
            $this->triggerMessage();

        }

        cache()->forget($action->id . '-error-messages');
        cache()->forget($action->id . '-success-message');
        $action->finished_at = Carbon::now();
        $action->save();
    }
}
