<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;
use Wildside\Userstamps\Userstamps;
use Illuminate\Database\Eloquent\SoftDeletes;

class Booking extends Model
{
    use HasFactory, Userstamps, SoftDeletes;

    protected $fillable = [
        'guest_id',
        'check_in_date',
        'check_out_date',
        'status',
        'booking_type',
        'duration_hours',
        'guest_count'
    ];

    protected $casts = [
        'check_in_date' => 'date',
        'check_out_date' => 'date',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
        'duration_hours' => 'integer',
        'guest_count' => 'integer',
    ];

    // Status constants
    const STATUS_BOOKED = 'booked';
    const STATUS_CHECKED_IN = 'checked_in';
    const STATUS_CHECKED_OUT = 'checked_out';
    const STATUS_CANCELLED = 'cancelled';

    // Booking type constants
    const TYPE_DAILY = 'daily';
    const TYPE_HOURLY = 'hourly';
    const TYPE_PER_PERSON = 'per_person';

    // Relationships
    public function guest()
    {
        return $this->belongsTo(Guest::class);
    }

    public function bookingDetails()
    {
        return $this->hasMany(BookingDetail::class);
    }

    public function rooms()
    {
        return $this->hasManyThrough(MsRooms::class, BookingDetail::class, 'booking_id', 'id', 'id', 'room_id');
    }

    public function room()
    {
        return $this->belongsTo(MsRooms::class, 'room_id', 'id');
    }

    // Relationship dengan CheckIn
    public function checkIn()
    {
        return $this->hasOne(CheckIn::class, 'booking_id', 'id');
    }

    // Relationship dengan CheckOut
    public function checkOut()
    {
        return $this->hasOne(CheckOut::class);
    }

    // Method untuk cek apakah sudah check-in
    public function isCheckedIn()
    {
        return $this->checkIn !== null && $this->status === 'checked_in';
    }

    // Method untuk cek apakah sudah check-out
    public function isCheckedOut()
    {
        return $this->checkOut !== null && $this->status === 'checked_out';
    }

    // Method untuk cek apakah bisa check-in
    public function canCheckIn()
    {
        return $this->status === 'booked' && 
            $this->check_in_date <= today() &&
            $this->checkIn === null;
    }

    // Method untuk cek apakah bisa check-out
    public function canCheckOut()
    {
        return $this->status === 'checked_in' && 
            $this->checkIn !== null &&
            $this->checkOut === null;
    }

    // NEW: Booking type methods
    public function isDailyBooking()
    {
        return $this->booking_type === self::TYPE_DAILY;
    }

    public function isHourlyBooking()
    {
        return $this->booking_type === self::TYPE_HOURLY;
    }

    public function isPerPersonBooking()
    {
        return $this->booking_type === self::TYPE_PER_PERSON;
    }

    // NEW: Get booking type display name
    public function getBookingTypeDisplayAttribute()
    {
        $types = [
            'daily' => 'Harian',
            'hourly' => 'Per Jam',
            'per_person' => 'Per Orang'
        ];

        return $types[$this->booking_type] ?? 'Unknown';
    }

    // NEW: Get duration display based on booking type
    public function getDurationDisplayAttribute()
    {
        switch ($this->booking_type) {
            case 'daily':
                return $this->nights . ' malam';
            case 'hourly':
                return $this->duration_hours . ' jam';
            case 'per_person':
                return $this->guest_count . ' orang x ' . $this->nights . ' malam';
            default:
                return 'Unknown';
        }
    }

    // Accessors - Updated
    public function getNightsAttribute()
    {
        if ($this->booking_type === 'hourly') {
            return 0; // Untuk booking hourly tidak ada konsep malam
        }
        
        return Carbon::parse($this->check_in_date)->diffInDays(Carbon::parse($this->check_out_date));
    }

    public function getTotalAmountAttribute()
    {
        return $this->bookingDetails->sum('grand_total');
    }

    public function getStatusBadgeAttribute()
    {
        $badges = [
            'booked' => '<span class="badge badge-primary">Booked</span>',
            'checked_in' => '<span class="badge badge-success">Checked In</span>',
            'checked_out' => '<span class="badge badge-info">Checked Out</span>',
            'cancelled' => '<span class="badge badge-danger">Cancelled</span>',
        ];

        return $badges[$this->status] ?? '<span class="badge badge-secondary">Unknown</span>';
    }

    // NEW: Get booking type badge
    public function getBookingTypeBadgeAttribute()
    {
        $badges = [
            'daily' => '<span class="badge badge-success">Harian</span>',
            'hourly' => '<span class="badge badge-warning">Per Jam</span>',
            'per_person' => '<span class="badge badge-info">Per Orang</span>',
        ];

        return $badges[$this->booking_type] ?? '<span class="badge badge-secondary">Unknown</span>';
    }

    public function getCheckInDateFormattedAttribute()
    {
        return $this->check_in_date ? $this->check_in_date->format('d/m/Y') : null;
    }

    public function getCheckOutDateFormattedAttribute()
    {
        return $this->check_out_date ? $this->check_out_date->format('d/m/Y') : null;
    }

    // NEW: Get check-in datetime formatted (for hourly bookings)
    public function getCheckInDateTimeFormattedAttribute()
    {
        if ($this->booking_type === 'hourly') {
            return $this->check_in_date ? $this->check_in_date->format('d/m/Y H:i') : null;
        }
        return $this->getCheckInDateFormattedAttribute();
    }

    // Scopes
    public function scopeActive($query)
    {
        return $query->whereIn('status', ['booked', 'checked_in']);
    }

    public function scopeToday($query)
    {
        return $query->whereDate('check_in_date', today());
    }

    public function scopeThisMonth($query)
    {
        return $query->whereMonth('created_at', now()->month)
                    ->whereYear('created_at', now()->year);
    }

    public function scopeByStatus($query, $status)
    {
        return $query->where('status', $status);
    }

    // NEW: Scopes for booking types
    public function scopeDaily($query)
    {
        return $query->where('booking_type', 'daily');
    }

    public function scopeHourly($query)
    {
        return $query->where('booking_type', 'hourly');
    }

    public function scopePerPerson($query)
    {
        return $query->where('booking_type', 'per_person');
    }

    // Methods
    public function canBeCancelled()
    {
        return $this->status === 'booked';
    }

    public function canBeCheckedIn()
    {
        return $this->status === 'booked' && 
               $this->check_in_date <= today();
    }

    public function bookingServices()
    {
        return $this->hasMany(BookingService::class);
    }

    /**
     * Get total amount dari booking services
     */
    public function getTotalServicesAmountAttribute()
    {
        return $this->bookingServices()->sum('total_amount');
    }

    /**
     * Get formatted total services amount
     */
    public function getFormattedTotalServicesAmountAttribute()
    {
        return 'Rp ' . number_format($this->total_services_amount, 0, ',', '.');
    }

    /**
     * Check if booking has services
     */
    public function hasServices()
    {
        return $this->bookingServices()->count() > 0;
    }

    /**
     * Get services count
     */
    public function getServicesCountAttribute()
    {
        return $this->bookingServices()->count();
    }

    /**
     * Get grand total (booking + services)
     */
    public function getGrandTotalAmountAttribute()
    {
        return $this->total_amount + $this->total_services_amount;
    }

    /**
     * Get formatted grand total
     */
    public function getFormattedGrandTotalAmountAttribute()
    {
        return 'Rp ' . number_format($this->grand_total_amount, 0, ',', '.');
    }

    public function invoice()
    {
        return $this->hasOne(Invoice::class);
    }

    /**
     * Check if booking has invoice
     */
    public function hasInvoice()
    {
        return $this->invoice()->exists();
    }

    /**
     * Get invoice status
     */
    public function getInvoiceStatusAttribute()
    {
        return $this->invoice ? $this->invoice->status : null;
    }

    /**
     * Check if invoice is paid
     */
    public function isInvoicePaid()
    {
        return $this->invoice && $this->invoice->status === 'paid';
    }

    /**
     * Generate invoice for this booking
     */
    public function generateInvoice($data = [])
    {
        if ($this->hasInvoice()) {
            return $this->invoice;
        }

        $roomTotal = $this->bookingDetails->sum('total_price');
        $servicesTotal = $this->bookingServices->sum('total_amount');
        $subtotal = $roomTotal + $servicesTotal;
        
        $discountAmount = $data['discount_amount'] ?? 0;
        $taxRate = $data['tax_rate'] ?? 11;
        $taxAmount = (($subtotal - $discountAmount) * $taxRate) / 100;
        $grandTotal = $subtotal - $discountAmount + $taxAmount;

        // Generate invoice number
        $date = \Carbon\Carbon::now();
        $prefix = 'INV-' . $date->format('Ymd') . '-';
        
        $lastInvoice = Invoice::where('invoice_number', 'like', $prefix . '%')
                            ->orderBy('invoice_number', 'desc')
                            ->first();

        if ($lastInvoice) {
            $lastNumber = intval(substr($lastInvoice->invoice_number, -4));
            $newNumber = $lastNumber + 1;
        } else {
            $newNumber = 1;
        }

        $invoiceNumber = $prefix . str_pad($newNumber, 4, '0', STR_PAD_LEFT);

        return $this->invoice()->create([
            'invoice_number' => $invoiceNumber,
            'invoice_date' => $data['invoice_date'] ?? now()->toDateString(),
            'due_date' => $data['due_date'] ?? now()->addDays(3)->toDateString(),
            'room_total' => $roomTotal,
            'services_total' => $servicesTotal,
            'subtotal' => $subtotal,
            'discount_amount' => $discountAmount,
            'tax_rate' => $taxRate,
            'tax_amount' => $taxAmount,
            'grand_total' => $grandTotal,
            'status' => 'pending',
            'notes' => $data['notes'] ?? null
        ]);
    }
}