<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use JeroenNoten\LaravelAdminLte\Menu\Filters\FilterInterface;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use App\Models\CaseRecord;
use App\Models\PoliceStation;

class User extends Authenticatable
{
    /** @use HasFactory<\Database\Factories\UserFactory> */
    use HasFactory, Notifiable, HasApiTokens;

    /**
     * The attributes that are mass assignable.
     *
     * @var list<string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
        'profile_picture',
        'is_officer',
        'rank',
        'badge_number',
        'station_id',
        'refresh_token',
        'refresh_token_expiry',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var list<string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * Get the attributes that should be cast.
     *
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
            'is_officer' => 'boolean',
        ];
    }
    
    /**
     * Get the police station this user is assigned to.
     */
    public function station(): BelongsTo
    {
        return $this->belongsTo(PoliceStation::class, 'station_id');
    }
    
    /**
     * Get the URL to the user's profile photo.
     *
     * @return string
     */
    public function adminlte_image()
    {
        if ($this->profile_picture) {
            return asset('storage/profile_pictures/' . $this->profile_picture);
        }
        return asset('img/user-profile.png');
    }

    /**
     * Get the URL to the user's profile page.
     *
     * @return string
     */
    public function adminlte_profile_url()
    {
        return route('profile.edit');
    }

    /**
     * Get the user's profile description.
     *
     * @return string
     */
    public function adminlte_desc()
    {
        return 'Police Officer';
    }
    
    /**
     * Get the cases where the user is the lead investigator.
     */
    public function leadInvestigatorCases(): HasMany
    {
        return $this->hasMany(CaseRecord::class, 'lead_investigator_id');
    }
    
    /**
     * Get the cases where the user is the reporting officer.
     */
    public function reportingOfficerCases(): HasMany
    {
        return $this->hasMany(CaseRecord::class, 'reporting_officer_id');
    }

    /**
     * Check if user has a specific permission based on their rank
     */
    public function hasRankPermission(string $permission): bool
    {
        // Admin users (non-officers) have full access
        if (!$this->is_officer) {
            return true;
        }

        $rank = strtolower($this->rank ?? '');
        
        // Define rank hierarchy (higher number = higher authority)
        $rankHierarchy = [
            'constable' => 1,
            'corporal' => 2,
            'sergeant' => 3,
            'inspector' => 4,
            'chief inspector' => 5,
            'superintendent' => 6,
            'deputy superintendent' => 7,
            'assistant superintendent' => 8,
            'assistant commissioner' => 9,
            'deputy commissioner' => 10,
            'commissioner' => 11,
        ];

        // Define permissions and required minimum rank levels
        $permissions = [
            // Station Management
            'manage-stations' => 4,
            'create-stations' => 6,
            
            // Officer Management
            'manage-officers' => 4,
            'create-officers' => 5,
            'batch-assign-officers' => 6,
            
            // Case Management
            'view-cases' => 1,
            'create-cases' => 2,
            'edit-cases' => 3,
            'delete-cases' => 5,
            'close-cases' => 4,
            
            // Evidence Management
            'manage-evidence' => 3,
            'transfer-evidence' => 4,
            'delete-evidence' => 5,
            
            // Statements
            'create-statements' => 2,
            'verify-statements' => 3,
            'edit-statements' => 4,
            
            // Suspects and Victims
            'manage-suspects' => 2,
            'manage-victims' => 2,
            'update-arrest-status' => 3,
            'update-charges' => 4,
            
            // Bail Management
            'manage-bail' => 4,
            'approve-bail' => 5,
            'bail-checkins' => 2,
            
            // Reports and Analytics
            'view-reports' => 3,
            'advanced-reports' => 4,
            'performance-reports' => 5,
            
            // Case Updates
            'edit-all-updates' => 4,
            'delete-all-updates' => 5,
            
            // System Settings
            'manage-settings' => 6,
            'manage-users' => 7,
            'system-backup' => 8,
        ];

        $userRankLevel = $rankHierarchy[$rank] ?? 0;
        $requiredLevel = $permissions[$permission] ?? 99;

        return $userRankLevel >= $requiredLevel;
    }

    /**
     * Get user's rank level for comparison
     */
    public function getRankLevel(): int
    {
        $rank = strtolower($this->rank ?? '');
        
        $rankHierarchy = [
            'constable' => 1,
            'corporal' => 2,
            'sergeant' => 3,
            'inspector' => 4,
            'chief inspector' => 5,
            'superintendent' => 6,
            'deputy superintendent' => 7,
            'assistant superintendent' => 8,
            'assistant commissioner' => 9,
            'deputy commissioner' => 10,
            'commissioner' => 11,
        ];

        return $rankHierarchy[$rank] ?? 0;
    }

    /**
     * Check if user can perform any case management actions
     */
    public function canManageCases(): bool
    {
        return $this->hasRankPermission('create-cases');
    }

    /**
     * Check if user can manage evidence
     */
    public function canManageEvidence(): bool
    {
        return $this->hasRankPermission('manage-evidence');
    }

    /**
     * Check if user can manage officers
     */
    public function canManageOfficers(): bool
    {
        return $this->hasRankPermission('manage-officers');
    }

    /**
     * Check if user can access reports
     */
    public function canViewReports(): bool
    {
        return $this->hasRankPermission('view-reports');
    }

    /**
     * Check if user can access data from a specific station
     */
    public function canAccessStationData(int $stationId): bool
    {
        // Admin users can access all station data
        if (!$this->is_officer) {
            return true;
        }

        // High-ranking officers can access data from multiple stations
        $rank = strtolower($this->rank ?? '');
        $highRankingOfficers = [
            'superintendent',
            'assistant superintendent',
            'deputy superintendent',
            'assistant commissioner', 
            'deputy commissioner',
            'commissioner'
        ];

        if (in_array($rank, $highRankingOfficers)) {
            return true;
        }

        // Regular officers can only access their own station's data
        return $this->station_id == $stationId;
    }

    /**
     * Get cases that the user can access based on their station and rank
     */
    public function getAccessibleCases()
    {
        // Admin users can see all cases
        if (!$this->is_officer) {
            return \App\Models\CaseRecord::query();
        }

        $rank = strtolower($this->rank ?? '');
        $highRankingOfficers = [
            'superintendent',
            'assistant superintendent',
            'deputy superintendent',
            'assistant commissioner', 
            'deputy commissioner',
            'commissioner'
        ];

        // High-ranking officers can see cases from all stations
        if (in_array($rank, $highRankingOfficers)) {
            return \App\Models\CaseRecord::query();
        }

        // Regular officers can only see cases from their station
        return \App\Models\CaseRecord::where('station_id', $this->station_id);
    }

    /**
     * Get officers that the user can access based on their station and rank
     */
    public function getAccessibleOfficers()
    {
        // Admin users can see all officers
        if (!$this->is_officer || $this->hasMultiStationAccess()) {
            return User::where('is_officer', true);
        }

        // Regular officers can only see officers from their station
        return User::where('is_officer', true)
                  ->where('station_id', $this->station_id);
    }

    /**
     * Get evidence that the user can access based on their station and rank
     */
    public function getAccessibleEvidence()
    {
        // Admin users can see all evidence
        if (!$this->is_officer) {
            return \App\Models\Evidence::query();
        }

        $rank = strtolower($this->rank ?? '');
        $highRankingOfficers = [
            'superintendent',
            'assistant superintendent',
            'deputy superintendent',
            'assistant commissioner', 
            'deputy commissioner',
            'commissioner'
        ];

        // High-ranking officers can see evidence from all stations
        if (in_array($rank, $highRankingOfficers)) {
            return \App\Models\Evidence::query();
        }

        // Regular officers can only see evidence from cases in their station
        return \App\Models\Evidence::whereHas('case', function($query) {
            $query->where('station_id', $this->station_id);
        });
    }

    /**
     * Get bail applications that the user can access based on their station and rank
     */
    public function getAccessibleBailApplications()
    {
        // Admin users can see all bail applications
        if (!$this->is_officer) {
            return \App\Models\BailApplication::query();
        }

        $rank = strtolower($this->rank ?? '');
        $highRankingOfficers = [
            'superintendent',
            'assistant superintendent',
            'deputy superintendent',
            'assistant commissioner', 
            'deputy commissioner',
            'commissioner'
        ];

        // High-ranking officers can see bail applications from all stations
        if (in_array($rank, $highRankingOfficers)) {
            return \App\Models\BailApplication::query();
        }

        // Regular officers can only see bail applications from their station
        return \App\Models\BailApplication::whereHas('case', function($query) {
            $query->where('station_id', $this->station_id);
        });
    }

    /**
     * Check if user is a high-ranking officer with multi-station access
     */
    public function hasMultiStationAccess(): bool
    {
        // Admin users have multi-station access
        if (!$this->is_officer) {
            return true;
        }

        $rank = strtolower($this->rank ?? '');
        $highRankingOfficers = [
            'superintendent',
            'assistant superintendent',
            'deputy superintendent',
            'assistant commissioner', 
            'deputy commissioner',
            'commissioner'
        ];

        return in_array($rank, $highRankingOfficers);
    }

    /**
     * Get the station name for display purposes
     */
    public function getStationNameAttribute(): string
    {
        return $this->station ? $this->station->name : 'No Station Assigned';
    }

    /**
     * Scope to filter users by accessible stations
     */
    public function scopeAccessibleToUser($query, User $user)
    {
        if (!$user->is_officer || $user->hasMultiStationAccess()) {
            return $query;
        }

        return $query->where('station_id', $user->station_id);
    }
}
