<?php

namespace App\Console\Commands;

use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Booking;
use Illuminate\Console\Command;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use App\Classes\Modules\Bookings\Services\UpdatesBookingStatus;
use App\Models\Transaction;

class ExpiredBookingCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'booking:expired';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Expiring booking that do not have further action by user';

    /** @var UpdatesBookingStatus */
    private $updatesBookingStatus;

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct(UpdatesBookingStatus $updatesBookingStatus)
    {
        parent::__construct();
        $this->updatesBookingStatus = $updatesBookingStatus;
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        // 1. Cancel booking without payment & purchase order (1 month)
        $bookings = Booking::where('status', ApprovalStatus::APPROVED)
            ->where('created_at', '<', now()->subDays(30)->endOfDay())
            ->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]);
                        });
                    });
            })->get();

        foreach ($bookings as $booking) {
            $this->updatesBookingStatus->execute($booking, ApprovalStatus::EXPIRED);
            $this->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();
                $this->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]);
                    })->whereHas('transactions', function($transaction) {
                        return $transaction->where('type', TransactionType::PURCHASE_ORDER);
                    });
            })->get();

        foreach ($bookings as $booking) {
            $this->updatesBookingStatus->execute($booking, ApprovalStatus::EXPIRED);
            $this->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();
                $this->info(Carbon::now() . " : Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}. Status before update: {$prevStatus}");
            }
        }
    }
}
