<?php

namespace App\Models;

use App\Services\TenantContext;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class GuestActivity extends Model
{
    use HasFactory, \App\Traits\HotelScopeTrait;

    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'guest_activities';

    /**
     * The attributes that are mass assignable.
     * UPDATED to match your exact database schema
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'hotel_id',
        'guest_id',
        'activity_type',
        'description',
        'metadata',
        'recorded_by',
        'activity_date',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'metadata' => 'array',
        'activity_date' => 'datetime',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    /**
     * Indicates if the model should be timestamped.
     *
     * @var bool
     */
    public $timestamps = true;

    /**
     * The attributes that should be mutated to dates.
     *
     * @var array<int, string>
     */
    protected $dates = [
        'activity_date',
        'created_at',
        'updated_at',
    ];

    /**
     * The accessors to append to the model's array form.
     *
     * @var array<int, string>
     */
    protected $appends = [
        'activity_type_badge',
        'activity_type_icon',
        'formatted_activity_date',
    ];

    /**
     * The "booted" method of the model.
     * This automatically sets hotel_id when creating.
     */
    protected static function booted()
    {
        static::creating(function ($activity) {
            // Auto-set recorded_by from authenticated user if not set
            if (empty($activity->recorded_by) && auth()->check()) {
                $activity->recorded_by = auth()->id();
            }

            // Auto-set activity_date if not set
            if (empty($activity->activity_date)) {
                $activity->activity_date = now();
            }
        });
    }

    /**
     * ============================================================
     * RELATIONSHIPS
     * ============================================================
     */

    /**
     * Get the guest that owns the activity.
     */
    public function guest(): BelongsTo
    {
        return $this->belongsTo(Guest::class);
    }

    /**
     * Get the hotel that owns the activity.
     */
    public function hotel(): BelongsTo
    {
        return $this->belongsTo(Hotel::class);
    }

    /**
     * Get the user who recorded the activity.
     */
    public function recordedBy(): BelongsTo
    {
        return $this->belongsTo(User::class, 'recorded_by');
    }

    /**
     * ============================================================
     * SCOPES
     * ============================================================
     */

    /**
     * Scope a query to only include activities for a specific hotel.
     */
    public function scopeForHotel($query, $hotelId = null)
    {
        $hotelId = $hotelId ?? app(TenantContext::class)->hotelId();
        if ($hotelId) {
            return $query->where('hotel_id', $hotelId);
        }
        return $query;
    }

    /**
     * Scope a query to only include activities for a specific guest.
     */
    public function scopeForGuest($query, $guestId)
    {
        return $query->where('guest_id', $guestId);
    }

    /**
     * Scope a query to only include activities of a specific type.
     */
    public function scopeOfType($query, $type)
    {
        return $query->where('activity_type', $type);
    }

    /**
     * Scope a query to only include activities within a date range.
     */
    public function scopeDateRange($query, $startDate, $endDate)
    {
        return $query->whereBetween('activity_date', [$startDate, $endDate]);
    }

    /**
     * Scope a query to only include today's activities.
     */
    public function scopeToday($query)
    {
        return $query->whereDate('activity_date', today());
    }

    /**
     * Scope a query to order by latest.
     */
    public function scopeLatest($query)
    {
        return $query->orderBy('activity_date', 'desc');
    }

    /**
     * ============================================================
     * ACCESSORS
     * ============================================================
     */

    /**
     * Get formatted activity date.
     */
    public function getFormattedActivityDateAttribute(): string
    {
        return $this->activity_date ? $this->activity_date->format('M j, Y g:i A') : 'N/A';
    }

    /**
     * Get activity type badge color.
     */
    public function getActivityTypeBadgeAttribute(): string
    {
        return match($this->activity_type) {
            'check_in', 'checkin' => 'bg-green-100 text-green-800',
            'check_out', 'checkout' => 'bg-blue-100 text-blue-800',
            'service_used', 'service_requested' => 'bg-indigo-100 text-indigo-800',
            'service_completed' => 'bg-green-100 text-green-800',
            'service_cancelled' => 'bg-red-100 text-red-800',
            'reservation_created' => 'bg-purple-100 text-purple-800',
            'reservation_updated' => 'bg-yellow-100 text-yellow-800',
            'reservation_cancelled' => 'bg-red-100 text-red-800',
            'payment_received' => 'bg-emerald-100 text-emerald-800',
            'payment' => 'bg-emerald-100 text-emerald-800',
            'blacklisted' => 'bg-red-100 text-red-800',
            'vip_marked' => 'bg-yellow-100 text-yellow-800',
            default => 'bg-gray-100 text-gray-800'
        };
    }

    /**
     * Get activity type icon.
     */
    public function getActivityTypeIconAttribute(): string
    {
        return match($this->activity_type) {
            'check_in', 'checkin' => 'fas fa-sign-in-alt',
            'check_out', 'checkout' => 'fas fa-sign-out-alt',
            'service_used', 'service_requested' => 'fas fa-concierge-bell',
            'service_completed' => 'fas fa-check-circle',
            'service_cancelled' => 'fas fa-times-circle',
            'reservation_created' => 'fas fa-bed',
            'reservation_updated' => 'fas fa-edit',
            'reservation_cancelled' => 'fas fa-ban',
            'payment_received' => 'fas fa-money-bill-wave',
            'payment' => 'fas fa-credit-card',
            'blacklisted' => 'fas fa-ban',
            'vip_marked' => 'fas fa-crown',
            default => 'fas fa-history'
        };
    }

    /**
     * Get activity type label.
     */
    public function getActivityTypeLabelAttribute(): string
    {
        return ucwords(str_replace('_', ' ', $this->activity_type));
    }

    /**
     * ============================================================
     * METHODS
     * ============================================================
     */

    /**
     * Log a new guest activity.
     */
    public static function logActivity(
        $guestId,
        $activityType,
        $description,
        $metadata = [],
        $recordedBy = null
    ) {
        $data = [
            'guest_id' => $guestId,
            'activity_type' => $activityType,
            'description' => $description,
            'metadata' => $metadata,
            'activity_date' => now(),
        ];

        // Add recorded_by if provided or from auth
        if ($recordedBy) {
            $data['recorded_by'] = $recordedBy;
        } elseif (auth()->check()) {
            $data['recorded_by'] = auth()->id();
        }

        $hotelId = app(TenantContext::class)->hotelId();
        if ($hotelId) {
            $data['hotel_id'] = $hotelId;
        }

        return self::create($data);
    }

    /**
     * Log a reservation-related activity.
     */
    public static function logReservationActivity(
        $guestId,
        $reservationId,
        $reservationNumber,
        $action,
        $metadata = []
    ) {
        $actionMap = [
            'created' => 'reservation_created',
            'updated' => 'reservation_updated',
            'cancelled' => 'reservation_cancelled',
            'checked_in' => 'check_in',
            'checked_out' => 'check_out',
        ];

        $activityType = $actionMap[$action] ?? 'reservation_updated';
        $description = 'Reservation ' . $action . ': ' . $reservationNumber;

        $metadata = array_merge([
            'reservation_id' => $reservationId,
            'reservation_number' => $reservationNumber,
        ], $metadata);

        return self::logActivity($guestId, $activityType, $description, $metadata);
    }

    /**
     * Log a service-related activity.
     */
    public static function logServiceActivity(
        $guestId,
        $serviceRequestId,
        $serviceName,
        $action,
        $metadata = []
    ) {
        $actionMap = [
            'requested' => 'service_requested',
            'started' => 'service_started',
            'completed' => 'service_completed',
            'cancelled' => 'service_cancelled',
        ];

        $activityType = $actionMap[$action] ?? 'service_used';
        $description = ucfirst($action) . ' service: ' . $serviceName;

        $metadata = array_merge([
            'service_request_id' => $serviceRequestId,
            'service_name' => $serviceName,
        ], $metadata);

        return self::logActivity($guestId, $activityType, $description, $metadata);
    }

    /**
     * Get activities grouped by date for a guest.
     */
    public static function getGroupedByDate($guestId = null, $limit = 50)
    {
        $query = self::query()->forHotel();
        
        if ($guestId) {
            $query->forGuest($guestId);
        }
        
        return $query->latest()
            ->limit($limit)
            ->get()
            ->groupBy(function($activity) {
                return $activity->activity_date->format('Y-m-d');
            });
    }
}