<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Illuminate\Database\Eloquent\Model;

class Patient extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    protected $fillable = [
        'name',
        'email',
        'phone',
        'email_verified_at',
        'phone_verified_at',
        'password', // Optional for phone-only users
        'preferred_language',
        'date_of_birth',
        'address',
        'emergency_contact_name',
        'emergency_contact_phone',
        'notes',
        'is_active',
    ];

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

    protected $casts = [
        'email_verified_at' => 'datetime',
        'phone_verified_at' => 'datetime',
        'date_of_birth' => 'date',
        'is_active' => 'boolean',
    ];

    /**
     * Get the queue entries for this patient via customer records
     * This returns a query builder, not a relationship
     */
    public function queueEntries()
    {
        // Get customer IDs that match this patient's phone number
        $customerIds = \App\Models\Customer::withoutGlobalScope(\App\Models\Scopes\TenantScope::class)
            ->where('phone', $this->phone)
            ->pluck('id')
            ->toArray();

        return WaitingQueue::withoutGlobalScope(\App\Models\Scopes\TenantScope::class)
            ->whereIn('customer_id', $customerIds);
    }

    /**
     * Get the current active queue entry
     */
    public function currentQueue()
    {
        return $this->hasOne(WaitingQueue::class, 'customer_id')
            ->whereIn('status', ['waiting', 'serving'])
            ->latest();
    }

    /**
     * Get patient's appointments
     */
    public function appointments()
    {
        return $this->hasMany(Appointment::class, 'customer_id');
    }

    /**
     * Get patient's favorite tenants
     */
    public function favoriteTenants()
    {
        return $this->belongsToMany(Tenant::class, 'patient_favorite_tenants')
            ->withTimestamps();
    }

    /**
     * Get patient's visits history across all tenants
     */
    public function visits()
    {
        // Get customer IDs that match this patient's phone number
        $customerIds = \App\Models\Customer::withoutGlobalScope(\App\Models\Scopes\TenantScope::class)
            ->where('phone', $this->phone)
            ->pluck('id')
            ->toArray();

        return WaitingQueue::withoutGlobalScope(\App\Models\Scopes\TenantScope::class)
            ->whereIn('customer_id', $customerIds)
            ->whereNotNull('completed_at')
            ->orderBy('completed_at', 'desc');
    }

    /**
     * Get patient's queue position at a specific tenant
     * For walk-in patients: show position among walk-ins only
     * For appointment patients: show appointment details instead of position
     */
    public function getQueuePositionAt($tenantId,$queid=0)
    {
        $currentQueue = $this->queueEntries()
            ->withoutGlobalScope(\App\Models\Scopes\TenantScope::class)
            ->where('tenant_id', $tenantId)
            ->where('id', $queid)
            ->whereIn('status', ['waiting', 'serving'])
            ->first();

        if (!$currentQueue) {
            return null;
        }

        $result = [
            'queue_entry' => $currentQueue,
            'type' => $currentQueue->type,
        ];

        if ($currentQueue->type === 'walk-in') {
            // For walk-in patients, count only other walk-in patients ahead
            $position = WaitingQueue::withoutGlobalScope(\App\Models\Scopes\TenantScope::class)
                ->where('tenant_id', $tenantId)
                ->where('type', 'walk-in')
                ->where('status', 'waiting')
                ->where('position', '<', $currentQueue->position)
                ->count() + 1;

            $result['position'] = $position;
            $result['total_walkins_waiting'] = WaitingQueue::withoutGlobalScope(\App\Models\Scopes\TenantScope::class)
                ->where('tenant_id', $tenantId)
                ->where('type', 'walk-in')
                ->where('status', 'waiting')
                ->count();
        } if ($currentQueue->type === 'appointment') {
            // For appointment patients, provide appointment details
            $result['appointment_time'] = $currentQueue->appointment_time;
            $result['is_appointment_due'] = $currentQueue->isAppointmentDue();
        }

        return $result;
    }

    /**
     * Calculate estimated wait time based on position and tenant's average service time
     */
    private function calculateEstimatedWaitTime($tenantId, $position)
    {
        // Get tenant's average service time from recent completed queues (bypass tenant scope)
        $avgServiceTime = WaitingQueue::withoutGlobalScope(\App\Models\Scopes\TenantScope::class)
            ->where('tenant_id', $tenantId)
            ->whereNotNull('completed_at')
            ->whereNotNull('served_at')
            ->where('completed_at', '>=', now()->subDays(7)) // Last 7 days
            ->selectRaw('AVG(TIMESTAMPDIFF(MINUTE, served_at, completed_at)) as avg_minutes')
            ->first();

        $averageMinutesPerCustomer = $avgServiceTime->avg_minutes ?? 15; // Default 15 minutes
        return ($position - 1) * $averageMinutesPerCustomer;
    }

    /**
     * Check if patient has verified contact method
     */
    public function hasVerifiedContact()
    {
        return $this->email_verified_at || $this->phone_verified_at;
    }

    /**
     * Get primary contact method
     */
    public function getPrimaryContactAttribute()
    {
        if ($this->phone_verified_at) {
            return $this->phone;
        }
        if ($this->email_verified_at) {
            return $this->email;
        }
        return $this->phone ?: $this->email;
    }

    /**
     * Join queue at specific tenant
     */
    public function joinQueueAt($tenantId, $visitType = null)
    {
        // Check if already in queue at this tenant (bypass tenant scope)
        $existingQueue = $this->queueEntries()
            ->withoutGlobalScope(\App\Models\Scopes\TenantScope::class)
            ->where('tenant_id', $tenantId)
            ->whereIn('status', ['waiting', 'serving'])
            ->first();

            $getposition = $this->queueEntries()
            ->withoutGlobalScope(\App\Models\Scopes\TenantScope::class)
            ->where('tenant_id', $tenantId)
            ->whereIn('status', ['waiting', 'serving'])
            ->count();

        if ($existingQueue) {
            return $existingQueue;
        }

        // Find or create a corresponding customer record for this patient and tenant
        $customer = \App\Models\Customer::withoutGlobalScope(\App\Models\Scopes\TenantScope::class)
            ->where('phone', $this->phone)
            ->where('tenant_id', $tenantId)
            ->first();

        if (!$customer) {
            $customer = \App\Models\Customer::withoutGlobalScope(\App\Models\Scopes\TenantScope::class)
                ->create([
                    'name' => $this->name,
                    'phone' => $this->phone,
                    'email' => $this->email,
                    'address' => $this->address,
                    'tenant_id' => $tenantId,
                    'notes' => 'Auto-created from patient record'
                ]);
        }

        // Create new queue entry (bypass tenant scope)
        $queueEntry = WaitingQueue::withoutGlobalScope(\App\Models\Scopes\TenantScope::class)
            ->create([
                'customer_id' => $customer->id,
                'tenant_id' => $tenantId,
                'type' => 'walk-in',
                'status' => 'waiting',
                'arrival_time' => now(),
                'visit_type' => $visitType,
                'position' => $getposition +1,
                'notes' => 'Joined via patient portal'
            ]);

        return $queueEntry;
    }

    /**
     * Add tenant to favorites
     */
    public function addFavoriteTenant($tenantId)
    {
        return $this->favoriteTenants()->syncWithoutDetaching([$tenantId]);
    }

    /**
     * Remove tenant from favorites
     */
    public function removeFavoriteTenant($tenantId)
    {
        return $this->favoriteTenants()->detach($tenantId);
    }

    /**
     * Check if tenant is in favorites
     */
    public function hasFavoriteTenant($tenantId)
    {
        return $this->favoriteTenants()->where('tenant_id', $tenantId)->exists();
    }

    /**
     * Check if patient is admin (always false for patients)
     * This method prevents errors when shared code calls isAdmin() on patient models
     */
    public function isAdmin()
    {
        return false;
    }
}
