<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Notifications\Notifiable;
use Tymon\JWTAuth\Contracts\JWTSubject;

class User extends Authenticatable implements JWTSubject
{
    use HasFactory, Notifiable;

    protected $fillable = [
        'name',
        'email',
        'phone',
        'password',
        'password_hash',
        'first_name',
        'last_name',
        'avatar_url',
        'role',
        'tenant_id',
        'corporate_account_id',
        'tenant',
        'company',
        'department',
        'grade',
        'address',
        'status',
        'email_verified',
        'email_verified_at',
        'phone_verified',
        'last_login',
        'last_login_at',
    ];

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

    protected $casts = [
        'email_verified' => 'boolean',
        'email_verified_at' => 'datetime',
        'phone_verified' => 'boolean',
        'last_login' => 'datetime',
        'last_login_at' => 'datetime',
        'password' => 'hashed',
    ];

    // JWT Subject Implementation
    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

    public function getJWTCustomClaims()
    {
        return [
            'email' => $this->email,
            'role' => $this->role,
            'tenant_id' => $this->tenant_id,
            'tenant' => $this->tenant,
        ];
    }

    // Helper Methods
    public function hasRole($role)
    {
        return $this->role === $role;
    }

    public function isAdmin()
    {
        return in_array($this->role, ['Platform Admin', 'Tenant Admin', 'Operator Admin']);
    }

    public function isOperatorAdmin()
    {
        return $this->role === 'Operator Admin';
    }

    public function isTenantAdmin()
    {
        return $this->role === 'Tenant Admin';
    }

    public function isPlatformAdmin()
    {
        return $this->role === 'Platform Admin';
    }

    public function isDriver()
    {
        return $this->role === 'Driver';
    }

    public function isCustomer()
    {
        return $this->role === 'Customer';
    }

    public function isCorporateTraveler()
    {
        return $this->role === 'Corporate Traveler';
    }

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

    public function updateLastLogin()
    {
        $this->update([
            'last_login_at' => now(),
        ]);
    }

    // One-to-One Relationships
    public function profile(): HasOne
    {
        return $this->hasOne(UserProfile::class);
    }

    public function tenantModel(): BelongsTo
    {
        return $this->belongsTo(Tenant::class, 'tenant_id');
    }

    // One-to-Many Relationships
    public function apiKeys(): HasMany
    {
        return $this->hasMany(ApiKey::class);
    }

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

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

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

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

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

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

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

    public function roles(): BelongsToMany
    {
        return $this->belongsToMany(Role::class, 'user_roles')
            ->withPivot('tenant_id', 'assigned_at', 'assigned_by')
            ->withTimestamps();
    }

    public function createdApiKeys(): HasMany
    {
        return $this->hasMany(ApiKey::class, 'created_by');
    }

    public function assignedRoles(): HasMany
    {
        return $this->hasMany(UserRole::class, 'assigned_by');
    }

    public function reportedDisputes(): HasMany
    {
        return $this->hasMany(Dispute::class, 'reported_by_id');
    }

    public function defendedDisputes(): HasMany
    {
        return $this->hasMany(Dispute::class, 'reported_against_id');
    }

    public function crmLeads(): HasMany
    {
        return $this->hasMany(CrmLead::class, 'assigned_to');
    }

    public function crmQuotes(): HasMany
    {
        return $this->hasMany(CrmQuote::class, 'generated_by');
    }

    public function signedContracts(): HasMany
    {
        return $this->hasMany(CrmContract::class, 'signed_by');
    }

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

    public function uploadedDocuments(): HasMany
    {
        return $this->hasMany(Document::class, 'uploaded_by');
    }

    public function verifiedDocuments(): HasMany
    {
        return $this->hasMany(Document::class, 'verified_by');
    }

    public function reviewedBids(): HasMany
    {
        return $this->hasMany(Bid::class, 'reviewed_by');
    }

    public function approverBookingApprovals(): HasMany
    {
        return $this->hasMany(BookingApproval::class, 'approver_id');
    }

    public function managedCorporateAccounts(): HasMany
    {
        return $this->hasMany(CorporateAccount::class, 'account_manager_id');
    }

    public function managedCorporateTravelers(): HasMany
    {
        return $this->hasMany(CorporateTraveler::class, 'manager_id');
    }

    public function dispatcherShifts(): HasMany
    {
        return $this->hasMany(DispatcherShift::class, 'dispatcher_id');
    }
}
