<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Laravel\Sanctum\HasApiTokens;

class Client extends Model
{
    use HasFactory, HasApiTokens;


    protected $fillable = [
        'name',
        'phone',
        'landline',
        'account_type_id',
        'auth_count',
        'authorized_count',
        'address',
        'city',
        'state',
        'country',
        'safebox_count',
        'safebox', 
        'payment_terms',
        'registration_number',
        'contract_start_date',
        'contract_end_date',
        'is_appointment',
        'status_id',
        'tenant_id',
    ];

    protected $casts = [
        'name' => 'string',
        'email' => 'string',
        'phone' => 'string',
        'address' => 'string',
        'city' => 'string',
        'state' => 'string',
        'country' => 'string',
        'payment_terms' => 'string',
        'registration_number' => 'string',
        'contract_start_date' => 'date',
        'contract_end_date' => 'date',
        'auth_count' => 'integer',
        'authorized_count' => 'integer',
        'safebox' => 'array',
        'is_appointment' => 'boolean',
    ];

    // Relationships
    public function status(): \Illuminate\Database\Eloquent\Relations\BelongsTo
    {
        return $this->belongsTo(Status::class);
    }

    public function accountType(): \Illuminate\Database\Eloquent\Relations\BelongsTo
    {
        return $this->belongsTo(AccountType::class);
    }

    public function contacts(): HasMany
    {
        return $this->hasMany(ClientContact::class);
    }

    public function contracts(): HasMany
    {
        return $this->hasMany(ClientContract::class);
    }

    public function locations(): HasMany
    {
        return $this->hasMany(ClientLocation::class);
    }

    public function geofences(): HasMany
    {
        return $this->hasMany(Geofence::class);
    }

    public function patrolSchedules(): HasMany
    {
        return $this->hasMany(PatrolSchedule::class);
    }

    public function services(): HasMany
    {
        return $this->hasMany(ClientService::class);
    }

    public function employeeAssignments(): HasMany
    {
        return $this->hasMany(EmployeeAssignment::class);
    }

    public function patrolReports(): HasMany
    {
        return $this->hasMany(PatrolReport::class);
    }

    public function customerMembers(): HasMany
    {
        return $this->hasMany(CustomerMember::class);
    }

    public function lockerRegistrations(): HasMany
    {
        return $this->hasMany(LockerRegistration::class);
    }

    public function membershipPlan(): BelongsTo
    {
        return $this->belongsTo(MembershipPlan::class, 'payment_terms');
    }

    // Scopes
    public function scopeByTenant($query, $tenantId = null)
    {
        $tenantId = $tenantId ?? config('app.default_tenant_id', 1);
        return $query->where('tenant_id', $tenantId);
    }

    public function scopeActive($query)
    {
        return $query->whereHas('status', function ($q) {
            $q->where('name', 'active');
        });
    }

    public function scopeByIndustry($query, string $industry)
    {
        return $query->where('industry', $industry);
    }

    // Accessors
    public function getFullAddressAttribute(): string
    {
        $parts = array_filter([
            $this->address,
            $this->city,
            $this->country,
            $this->postal_code
        ]);

        return implode(', ', $parts);
    }

    public function getPrimaryContactAttribute(): ?ClientContact
    {
        return $this->contacts()->where('is_primary', true)->first();
    }

    public function getActiveContractsCountAttribute(): int
    {
        return $this->contracts()->whereHas('status', function ($q) {
            $q->where('name', 'active');
        })->count();
    }

    public function getTotalLocationsCountAttribute(): int
    {
        return $this->locations()->count();
    }

    public function getActiveLocationsCountAttribute(): int
    {
        return $this->locations()->where('is_active', true)->count();
    }

    // Methods
    public function addContact(array $data): ClientContact
    {
        // If this is marked as primary, unmark other primary contacts
        if ($data['is_primary'] ?? false) {
            $this->contacts()->where('is_primary', true)->update(['is_primary' => false]);
        }

        return $this->contacts()->create(array_merge($data, [
            'tenant_id' => $this->tenant_id
        ]));
    }

    public function addLocation(array $data): ClientLocation
    {
        return $this->locations()->create(array_merge($data, [
            'tenant_id' => $this->tenant_id
        ]));
    }

    public function addContract(array $data): ClientContract
    {
        return $this->contracts()->create(array_merge($data, [
            'tenant_id' => $this->tenant_id
        ]));
    }

    public function createGeofence(array $data): Geofence
    {
        return $this->geofences()->create(array_merge($data, [
            'tenant_id' => $this->tenant_id
        ]));
    }

    public function schedulePatrol(array $data): PatrolSchedule
    {
        return $this->patrolSchedules()->create(array_merge($data, [
            'tenant_id' => $this->tenant_id
        ]));
    }

    public function addService(array $data): ClientService
    {
        return $this->services()->create(array_merge($data, [
            'tenant_id' => $this->tenant_id
        ]));
    }

    public function assignEmployee(array $data): EmployeeAssignment
    {
        return $this->employeeAssignments()->create(array_merge($data, [
            'tenant_id' => $this->tenant_id
        ]));
    }

    public function createPatrolReport(array $data): PatrolReport
    {
        return $this->patrolReports()->create(array_merge($data, [
            'tenant_id' => $this->tenant_id
        ]));
    }

    // Contract Validation Methods
    public function hasActiveContract(): bool
    {
        return $this->contracts()
            ->where('status_id', Status::getActiveId())
            ->where('start_date', '<=', now())
            ->where(function ($query) {
                $query->whereNull('end_date')
                    ->orWhere('end_date', '>=', now());
            })
            ->exists();
    }

    public function isValidForPatrol(): bool
    {
        return $this->hasActiveContract() && $this->status_id === Status::getActiveId();
    }

    public function getActiveContract(): ?ClientContract
    {
        return $this->contracts()
            ->where('status_id', Status::getActiveId())
            ->where('start_date', '<=', now())
            ->where(function ($query) {
                $query->whereNull('end_date')
                    ->orWhere('end_date', '>=', now());
            })
            ->first();
    }
}
