<?php

namespace App\Models;

use Filament\Models\Contracts\FilamentUser;
use Filament\Panel;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable implements FilamentUser
{
    use HasFactory, Notifiable, HasApiTokens, HasRoles;

    protected $fillable = [
        'company_id',
        'employee_id',
        'nip',
        'name',
        'email',
        'password',
        'phone',
        'role',
        'department',
        'position',
        'address',
        'home_latitude',
        'home_longitude',
        'is_active',
        'approval_status',
        'approved_by',
        'approved_at',
        'rejection_reason',
        'avatar',
        'fcm_token',
    ];

    protected $hidden = [
        'password',
        'remember_token',
        'fcm_token',
    ];

    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
            'home_latitude' => 'decimal:8',
            'home_longitude' => 'decimal:8',
            'is_active' => 'boolean',
        ];
    }

    public function company(): BelongsTo
    {
        return $this->belongsTo(Company::class);
    }

    public function attendances(): HasMany
    {
        return $this->hasMany(Attendance::class);
    }

    public function businessTrips(): HasMany
    {
        return $this->hasMany(BusinessTrip::class);
    }

    public function businessTripAttendances(): HasMany
    {
        return $this->hasMany(BusinessTripAttendance::class);
    }

    public function activities(): HasMany
    {
        return $this->hasMany(Activity::class);
    }

    public function overtimes(): HasMany
    {
        return $this->hasMany(Overtime::class);
    }

    public function devices(): HasMany
    {
        return $this->hasMany(UserDevice::class);
    }

    /**
     * Get all employee cards for this user
     */
    public function employeeCards(): HasMany
    {
        return $this->hasMany(EmployeeCard::class);
    }

    /**
     * Get active employee card
     */
    public function activeEmployeeCard()
    {
        return $this->hasOne(EmployeeCard::class)->where('card_status', 'active');
    }

    /**
     * Get QR attendance logs where this user was scanned
     */
    public function qrAttendanceLogsAsScanned(): HasMany
    {
        return $this->hasMany(QrAttendanceLog::class, 'scanned_user_id');
    }

    /**
     * Get QR attendance logs where this user performed the scan
     */
    public function qrAttendanceLogsAsScanner(): HasMany
    {
        return $this->hasMany(QrAttendanceLog::class, 'scanner_user_id');
    }

    public function approvedDevices(): HasMany
    {
        return $this->hasMany(UserDevice::class)->where('status', 'approved');
    }

    public function pendingDevices(): HasMany
    {
        return $this->hasMany(UserDevice::class)->where('status', 'pending');
    }

    public function primaryDevice()
    {
        return $this->hasOne(UserDevice::class)->where('is_primary', true)->where('status', 'approved');
    }

    public function approvedBusinessTrips(): HasMany
    {
        return $this->hasMany(BusinessTrip::class, 'approved_by');
    }

    /**
     * Get surat tugas assigned to this user
     */
    public function suratTugas(): BelongsToMany
    {
        return $this->belongsToMany(SuratTugas::class, 'surat_tugas_user')
            ->withTimestamps();
    }

    /**
     * Get active surat tugas assigned to this user
     */
    public function activeSuratTugas(): BelongsToMany
    {
        return $this->suratTugas()->where('is_active', true);
    }

    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    public function scopeEmployees($query)
    {
        return $query->where('role', 'employee');
    }

    public function scopeManagers($query)
    {
        return $query->where('role', 'manager');
    }

    public function scopeAdmins($query)
    {
        return $query->where('role', 'admin');
    }

    public function scopeSuperAdmins($query)
    {
        return $query->where('role', 'super_admin');
    }

    public function isSuperAdmin(): bool
    {
        return $this->role === 'super_admin';
    }

    public function isAdmin(): bool
    {
        return $this->role === 'admin';
    }

    public function isManager(): bool
    {
        return $this->role === 'manager';
    }

    public function isEmployee(): bool
    {
        return $this->role === 'employee';
    }

    public function hasHomeLocation(): bool
    {
        return $this->home_latitude !== null && $this->home_longitude !== null;
    }

    /**
     * Determine if user can access Filament panels
     */
    public function canAccessPanel(Panel $panel): bool
    {
        // Must be active and approved
        if (!$this->is_active || $this->approval_status !== 'approved') {
            return false;
        }

        // Admin panel - only super_admin and admin
        if ($panel->getId() === 'admin') {
            return $this->hasRole(['super_admin', 'admin']);
        }

        // Employee panel - all active users (employee, admin, super_admin)
        if ($panel->getId() === 'employee') {
            return true; // All active approved users can access
        }

        return false;
    }

    /**
     * Get the approver relationship
     */
    public function approvedBy(): BelongsTo
    {
        return $this->belongsTo(User::class, 'approved_by');
    }

    /**
     * Check if user is pending approval
     */
    public function isPendingApproval(): bool
    {
        return $this->approval_status === 'pending';
    }

    /**
     * Check if user is approved
     */
    public function isApproved(): bool
    {
        return $this->approval_status === 'approved';
    }

    /**
     * Check if user can approve other users
     */
    public function canApprove(): bool
    {
        return $this->hasPermissionTo('approve_users');
    }

    /**
     * Get user notifications
     */
    public function notifications(): HasMany
    {
        return $this->hasMany(Notification::class);
    }

    /**
     * Get user shifts (many to many through user_shifts)
     */
    public function shifts(): BelongsToMany
    {
        return $this->belongsToMany(Shift::class, 'user_shifts')
            ->withPivot(['effective_date', 'end_date'])
            ->withTimestamps();
    }

    /**
     * Get user shift assignments
     */
    public function userShifts(): HasMany
    {
        return $this->hasMany(UserShift::class);
    }

    /**
     * Get the current active shift for today
     */
    public function getCurrentShift($date = null)
    {
        $date = $date ?? now()->toDateString();

        $userShift = $this->userShifts()
            ->with('shift')
            ->where('effective_date', '<=', $date)
            ->where(function ($query) use ($date) {
                $query->whereNull('end_date')
                    ->orWhere('end_date', '>=', $date);
            })
            ->orderBy('effective_date', 'desc')
            ->first();

        if ($userShift) {
            return $userShift->shift;
        }

        // Fallback to company default shift
        if ($this->company) {
            return $this->company->defaultShift();
        }

        return null;
    }
}
