<?php

namespace App\Classes\Jobs\Commands\V2;

use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Booking;
use App\Classes\Modules\Bookings\Services\UpdatesBookingStatus;
use Illuminate\Support\Facades\Log;


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


    public function handle()
    {
        Log::info(Carbon::now() . ': Start job - Expiring booking that do not have further action by user.');
        $start   = new Carbon();

         // 1. Cancel booking without payment & purchase order (1 month)
         $bookings = Booking::where('status', ApprovalStatus::APPROVED)
         ->where('created_at', '<', now()->subDays(30)->endOfDay())
         ->where('service_id', '!=', 4)
         ->where(function ($query) {
             $query->whereDoesntHave('transactions')
                 ->orWhereDoesntHave('transactions', function($transaction) {
                     return $transaction->where('type', TransactionType::PURCHASE_ORDER)->orWhere(function ($q) {
                         $q->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED, ApprovalStatus::REFUNDED]);
                     });
                 });
         })->get();

        foreach ($bookings as $booking) {
            (App()->make(UpdatesBookingStatus::class))->execute($booking, ApprovalStatus::EXPIRED);
            Log::info(Carbon::now() . " : Expired Booking without payment & purchase order, booking id: " . $booking->id);
            $transactions = $booking->transactions;

            foreach ($transactions as $transaction) {
                $prevStatus = $transaction->status;
                $transaction->status = ApprovalStatus::EXPIRED;
                $transaction->save();
                Log::info(Carbon::now() . " : Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}. Status before update: {$prevStatus}");
            }
        }

        // 2. Cancel booking without payment but with purchase order (2 month)
        $bookings = Booking::where('status', ApprovalStatus::APPROVED)
            ->where('created_at', '<', now()->subDays(60)->endOfDay())
            ->where(function ($query) {
                $query->whereDoesntHave('transactions', function($transaction) {
                        return $transaction->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED, ApprovalStatus::REFUNDED]);
                    })->whereHas('transactions', function($transaction) {
                        return $transaction->where('type', TransactionType::PURCHASE_ORDER);
                    });
            })->get();

        foreach ($bookings as $booking) {
            (App()->make(UpdatesBookingStatus::class))->execute($booking, ApprovalStatus::EXPIRED);
            Log::info(Carbon::now() . " : Expired Booking without payment but with purchase order, booking id: " . $booking->id);
            $transactions = $booking->transactions;

            foreach ($transactions as $transaction) {
                $prevStatus = $transaction->status;
                $transaction->status = ApprovalStatus::EXPIRED;
                $transaction->save();
                Log::info(Carbon::now() . " : Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}. Status before update: {$prevStatus}");
            }
        }

        $end = new Carbon();
        $elapsedTime = $start->diff($end)->format('%H:%I:%S');
        Log::info(Carbon::now() . ': End job - Expiring booking that do not have further action by user. ElapsedTime: ' . $elapsedTime . '.');
    }
}
