<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Carbon\Carbon;

class Reservasi extends Model
{
    use HasFactory;

    protected $table = 'reservasi';
    
    protected $fillable = [
        'user_id',
        'meja_id',
        'name',
        'phone',
        'date',
        'start_time',
        'status',
        'notes',
        'total_harga',
        'payment_method'
    ];

    protected $casts = [
        'date' => 'date',
        'start_time' => 'datetime:H:i',
    ];

    const STATUS_PENDING = 'pending';
    const STATUS_CONFIRMED = 'confirmed';
    const STATUS_COMPLETED = 'completed';
    const STATUS_CANCELLED = 'cancelled';

    /**
     * Get the user that owns the reservation.
     */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    /**
     * Get the table that is reserved.
     */
    public function meja(): BelongsTo
    {
        return $this->belongsTo(Meja::class, 'meja_id');
    }

    /**
     * Get the transaction associated with the reservation.
     */
    public function transaksi(): HasOne
    {
        return $this->hasOne(Transaksi::class);
    }

    /**
     * Get the transaction items through the transaction.
     */
    public function detailPesanan(): HasManyThrough
    {
        return $this->hasManyThrough(
            TransaksiItem::class,
            Transaksi::class,
            'reservasi_id', // Foreign key on transaksi table...
            'transaksi_id', // Foreign key on transaksi_items table...
            'id', // Local key on reservasi table...
            'id'  // Local key on transaksi table...
        );
    }

    /**
     * Check if a time slot is available for a specific table.
     */
    public static function isTimeSlotAvailable($mejaId, $date, $startTime): bool
    {
        // Convert times to Carbon instances for comparison
        $start = Carbon::parse($startTime);
        $requestedDate = Carbon::parse($date);

        // Check if the requested date and time is in the past
        if ($requestedDate->isPast() && $requestedDate->isToday() && $start->isPast()) {
            return false;
        }

        // Check for existing reservations at the same time slot
        $conflictingReservations = self::where('meja_id', $mejaId)
            ->whereDate('date', $date)
            ->whereNotIn('status', [self::STATUS_CANCELLED])
            ->where('start_time', $startTime)
            ->exists();

        return !$conflictingReservations;
    }

    /**
     * Get all available time slots for a specific table and date
     */
    public static function getAvailableTimeSlots($mejaId, $date)
    {
        // Get all reservations for this table on this date
        $reservations = self::where('meja_id', $mejaId)
            ->whereDate('date', $date)
            ->whereNotIn('status', [self::STATUS_CANCELLED])
            ->get(['start_time']);

        $timeSlots = [];
        $startHour = 10; // 10:00
        $endHour = 22;   // 22:00
        $interval = 30;  // 30 minutes interval

        for ($hour = $startHour; $hour < $endHour; $hour++) {
            for ($minute = 0; $minute < 60; $minute += $interval) {
                $currentTime = sprintf('%02d:%02d', $hour, $minute);

                // Check if this time slot is available
                if (self::isTimeSlotAvailable($mejaId, $date, $currentTime)) {
                    $timeSlots[] = [
                        'start_time' => $currentTime,
                        'is_available' => true
                    ];
                }
            }
        }

        // If date is today, remove past time slots
        if ($date == Carbon::today()->format('Y-m-d')) {
            $currentTime = Carbon::now();
            $timeSlots = array_filter($timeSlots, function($slot) use ($currentTime) {
                return Carbon::parse($slot['start_time'])->gt($currentTime);
            });
        }

        return array_values($timeSlots);
    }

    /**
     * Update table status based on reservation status
     */
    public function updateTableStatus()
    {
        if ($this->date == now()->format('Y-m-d')) {
            $status = match($this->status) {
                self::STATUS_CONFIRMED => 'dipesan',
                self::STATUS_COMPLETED, self::STATUS_CANCELLED => 'tersedia',
                default => null
            };

            if ($status) {
                $this->meja()->update(['status' => $status]);
            }
        }
    }

    /**
     * Get payment method display name
     */
    public function getPaymentMethodDisplayAttribute()
    {
        $methods = [
            'credit_card' => 'Kartu Kredit',
            'mandiri_clickpay' => 'Mandiri Clickpay',
            'cimb_clicks' => 'CIMB Clicks',
            'bca_klikbca' => 'BCA KlikBCA',
            'bca_klikpay' => 'BCA KlikPay',
            'bri_epay' => 'BRI e-Pay',
            'echannel' => 'Mandiri Bill Payment',
            'permata_va' => 'Permata Virtual Account',
            'bca_va' => 'BCA Virtual Account',
            'bni_va' => 'BNI Virtual Account',
            'bri_va' => 'BRI Virtual Account',
            'other_va' => 'Virtual Account Bank Lain',
            'gopay' => 'GoPay',
            'shopeepay' => 'ShopeePay',
            'qris' => 'QRIS',
            'indomaret' => 'Indomaret',
            'alfamart' => 'Alfamart',
            'danamon_online' => 'Danamon Online Banking',
            'akulaku' => 'Akulaku'
        ];

        return $methods[$this->payment_method] ?? $this->payment_method;
    }
} 