<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Concerns\HasUlids;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Carbon;

/**
 * Class Person
 * @package App\Models
 *
 * @property string $id
 * @property string $inquiry_id
 * @property int $deductible_id
 * @property int $price_id
 * @property string $first_name
 * @property string $last_name
 * @property Carbon $born_at
 * @property int|null $age
 * @property bool $is_male
 * @property float|null $individual_premium
 * @property string|null $rate_category
 * @property bool $has_smoking_surcharge
 * @property bool $is_eligible
 * @property string|null $ineligibility_reason
 * @property bool $has_pre_existing_conditions
 * @property bool $is_smoker
 * @property int $deductible_amount
 * @property bool $questionnaire_completed
 * @property array|null $questionnaire_data
 * @property Carbon|null $questionnaire_completed_at
 *
 * @property Deductible $deductible
 * @property Inquiry $inquiry
 * @property Price $price
 */
class Person extends Model
{
    use HasUlids;

    /**
     * Rate categories for Manulife insurance
     */
    const RATE_CATEGORY_A = 'A';
    const RATE_CATEGORY_B = 'B';
    const RATE_CATEGORY_C = 'C';

    /**
     * Minimum age for questionnaire requirement
     */
    const QUESTIONNAIRE_MIN_AGE = 60;

    public $timestamps = false;
    protected $table = 'people';
    protected $fillable = [
        'id',
        'inquiry_id',
        'deductible_id',
        'price_id',
        'first_name',
        'last_name',
        'born_at',
        'age',
        'is_male',
        'individual_premium',
        'rate_category',
        'has_smoking_surcharge',
        'is_eligible',
        'ineligibility_reason',
        'has_pre_existing_conditions',
        'is_smoker',
        'deductible_amount',
        'questionnaire_completed',
        'questionnaire_data',
        'questionnaire_completed_at',
    ];

    /**
     * Boot the model and register model events.
     * @return void
     */
    protected static function boot(): void
    {
        parent::boot();

        // Calculate age before creating if not set
        static::creating(function (Person $person) {
            if (empty($person->age) && $person->born_at) {
                $person->age = $person->calculateAge();
            }

            // Set default values for boolean fields
            $booleanDefaults = [
                'has_smoking_surcharge' => false,
                'is_eligible' => true,
                'has_pre_existing_conditions' => false,
                'is_smoker' => false,
                'questionnaire_completed' => false,
            ];

            foreach ($booleanDefaults as $field => $default) {
                if (!isset($person->{$field})) {
                    $person->{$field} = $default;
                }
            }

            // Set default deductible amount
            if (!isset($person->deductible_amount)) {
                $person->deductible_amount = 0;
            }
        });

        // Update age before saving if born_at changed
        static::saving(function (Person $person) {
            if ($person->isDirty('born_at')) {
                $person->age = $person->calculateAge();
            }
        });
    }

    /**
     * Calculate age based on born_at date
     * @return int
     */
    public function calculateAge(): int
    {
        if (!$this->born_at) {
            return 0;
        }

        return now()->diffInYears($this->born_at);
    }

    /**
     * Get rate category options
     * @return array
     */
    public static function getRateCategoryOptions(): array
    {
        return [
            self::RATE_CATEGORY_A => 'Category A (Lowest Risk)',
            self::RATE_CATEGORY_B => 'Category B (Medium Risk)',
            self::RATE_CATEGORY_C => 'Category C (Highest Risk)',
        ];
    }

    /**
     * Get rate category label
     * @return string
     */
    public function getRateCategoryLabel(): string
    {
        $options = self::getRateCategoryOptions();
        return $options[$this->rate_category] ?? 'Not Set';
    }

    /**
     * Check if person requires questionnaire
     * @return bool
     */
    public function requiresQuestionnaire(): bool
    {
        return $this->age >= self::QUESTIONNAIRE_MIN_AGE;
    }

    /**
     * Mark questionnaire as completed
     * @param array $data
     * @return void
     */
    public function markQuestionnaireCompleted(array $data = []): void
    {
        $this->questionnaire_completed = true;
        $this->questionnaire_data = $data;
        $this->questionnaire_completed_at = now();
        $this->save();
    }

    /**
     * Get full name of person
     * @return string
     */
    public function getFullName(): string
    {
        return trim($this->first_name . ' ' . $this->last_name);
    }

    /**
     * Get gender label
     * @return string
     */
    public function getGenderLabel(): string
    {
        return $this->is_male ? 'Male' : 'Female';
    }

    /**
     * Get gender in Persian
     * @return string
     */
    public function getGenderFa(): string
    {
        return $this->is_male ? 'مرد' : 'زن';
    }

    /**
     * Get gender based on language code
     * @param string|null $languageCode
     * @return string
     */
    public function getTranslatedGender(?string $languageCode = null): string
    {
        if (!$languageCode) {
            $languageCode = request()->header('Accept-Language', 'en');
        }

        return match($languageCode) {
            'zh' => $this->is_male ? '男' : '女',
            'fa' => $this->getGenderFa(),
            default => $this->getGenderLabel(),
        };
    }

    /**
     * Get eligibility status label
     * @return string
     */
    public function getEligibilityLabel(): string
    {
        return $this->is_eligible ? 'Eligible' : 'Not Eligible';
    }

    /**
     * Get smoking status label
     * @return string
     */
    public function getSmokingStatusLabel(): string
    {
        return $this->is_smoker ? 'Smoker' : 'Non-Smoker';
    }

    /**
     * Get pre-existing conditions status label
     * @return string
     */
    public function getPreExistingConditionsLabel(): string
    {
        return $this->has_pre_existing_conditions ? 'Has Conditions' : 'No Conditions';
    }

    /**
     * Check if person is primary applicant (first person in inquiry)
     * @return bool
     */
    public function isPrimaryApplicant(): bool
    {
        if (!$this->inquiry || !$this->inquiry->people) {
            return false;
        }

        return $this->id === $this->inquiry->people->first()->id;
    }

    /**
     * Get individual premium formatted
     * @return string
     */
    public function getIndividualPremiumFormatted(): string
    {
        if (is_null($this->individual_premium)) {
            return 'N/A';
        }

        $symbol = '$';
        return $symbol . number_format($this->individual_premium, 2);
    }

    /**
     * Get deductible amount formatted
     * @return string
     */
    public function getDeductibleAmountFormatted(): string
    {
        $symbol = '$';
        return $symbol . number_format($this->deductible_amount, 0);
    }

    /**
     * Get age group for rate calculation
     * @return string|null
     */
    public function getAgeGroup(): ?string
    {
        if (is_null($this->age)) {
            return null;
        }

        if ($this->age < 18) return '0-17';
        if ($this->age <= 30) return '18-30';
        if ($this->age <= 60) return '31-60';
        if ($this->age <= 64) return '60-64';
        if ($this->age <= 69) return '65-69';
        if ($this->age <= 74) return '70-74';
        if ($this->age <= 79) return '75-79';
        if ($this->age <= 84) return '80-84';
        return '85+';
    }

    /**
     * Determine rate category based on age and medical conditions
     * @param array $questionnaireAnswers
     * @return string
     */
    public function determineRateCategory(array $questionnaireAnswers = []): string
    {
        // Only applicable for age 60+
        if ($this->age < 60) {
            return self::RATE_CATEGORY_A;
        }

        // Default to Category A
        $category = self::RATE_CATEGORY_A;

        // Implement Manulife questionnaire logic here
        // This is a simplified version - actual logic would be more complex
        if (!empty($questionnaireAnswers)) {
            // Check for automatic C category triggers
            $cTriggers = [
                'has_heart_condition',
                'has_aortic_aneurysm',
                'has_cirrhosis',
                'has_parkinsons',
                'has_alzheimers',
                'high_blood_pressure_meds',
            ];

            foreach ($cTriggers as $trigger) {
                if (!empty($questionnaireAnswers[$trigger]) && $questionnaireAnswers[$trigger] === 'yes') {
                    return self::RATE_CATEGORY_C;
                }
            }

            // Check for B category triggers
            $bTriggers = [
                'gastrointestinal_bleeding',
                'chronic_bowel_disorder',
                'kidney_disorder',
                'liver_disorder',
                'pancreatitis',
                'gallbladder_disorder',
                'blood_disorder',
                'recent_falls',
                'frequent_er_visits',
            ];

            foreach ($bTriggers as $trigger) {
                if (!empty($questionnaireAnswers[$trigger]) && $questionnaireAnswers[$trigger] === 'yes') {
                    $category = self::RATE_CATEGORY_B;
                    break;
                }
            }
        }

        return $category;
    }

    /**
     * Calculate smoking surcharge percentage
     * @return float
     */
    public function getSmokingSurchargePercent(): float
    {
        // 10% surcharge for smokers age 60+
        return ($this->is_smoker && $this->age >= 60) ? 10.0 : 0.0;
    }

    /**
     * Check if person can purchase insurance
     * @return array
     */
    public function checkEligibility(): array
    {
        $eligible = true;
        $reasons = [];

        // Age restrictions
        if ($this->age > 120) {
            $eligible = false;
            $reasons[] = 'Age exceeds maximum limit (120 years)';
        }

        // Other eligibility checks can be added here

        return [
            'eligible' => $eligible,
            'reasons' => $reasons,
        ];
    }

    /**
     * Get questionnaire completion status
     * @return string
     */
    public function getQuestionnaireStatus(): string
    {
        if (!$this->requiresQuestionnaire()) {
            return 'Not Required';
        }

        return $this->questionnaire_completed ? 'Completed' : 'Pending';
    }

    /**
     * Scope: People who need questionnaire
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeNeedsQuestionnaire($query)
    {
        return $query->where('age', '>=', self::QUESTIONNAIRE_MIN_AGE)
                    ->where('questionnaire_completed', false);
    }

    /**
     * Scope: Eligible people
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeEligible($query)
    {
        return $query->where('is_eligible', true);
    }

    /**
     * Scope: Smokers
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeSmokers($query)
    {
        return $query->where('is_smoker', true);
    }

    /**
     * Scope: People with pre-existing conditions
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeWithPreExistingConditions($query)
    {
        return $query->where('has_pre_existing_conditions', true);
    }

    /**
     * Relationship: Person belongs to a Deductible
     * @return BelongsTo
     */
    public function deductible(): BelongsTo
    {
        return $this->belongsTo(Deductible::class, 'deductible_id');
    }

    /**
     * Relationship: Person belongs to an Inquiry
     * @return BelongsTo
     */
    public function inquiry(): BelongsTo
    {
        return $this->belongsTo(Inquiry::class, 'inquiry_id');
    }

    /**
     * Relationship: Person belongs to a Price
     * @return BelongsTo
     */
    public function price(): BelongsTo
    {
        return $this->belongsTo(Price::class, 'price_id');
    }

    /**
     * The attributes that should be cast.
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'born_at' => 'datetime',
            'questionnaire_completed_at' => 'datetime',
            'is_male' => 'boolean',
            'has_smoking_surcharge' => 'boolean',
            'is_eligible' => 'boolean',
            'has_pre_existing_conditions' => 'boolean',
            'is_smoker' => 'boolean',
            'questionnaire_completed' => 'boolean',
            'individual_premium' => 'decimal:2',
            'questionnaire_data' => 'array',
        ];
    }
}