<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Concerns\HasUlids;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOne;

/**
 * Class QuestionnaireAnswer
 * @package App\Models
 *
 * @property string $id
 * @property string $person_id
 * @property string $inquiry_id
 * @property int|null $questionnaire_config_id
 * @property array|null $step1_answers
 * @property bool|null $step1_passed
 * @property string|null $step1_rejection_reason
 * @property array|null $step2_answers
 * @property bool|null $step2_triggered_c_rate
 * @property array|null $step3_answers
 * @property bool|null $step3_triggered_b_rate
 * @property array|null $step4_answers
 * @property bool $is_smoker
 * @property int|null $years_smoking
 * @property bool $uses_vaping
 * @property string $status
 * @property string|null $rate_category
 * @property float $rate_adjustment_factor
 * @property string|null $rejection_reason
 * @property string|null $review_notes
 * @property \Carbon\Carbon|null $started_at
 * @property \Carbon\Carbon|null $completed_at
 * @property \Carbon\Carbon|null $reviewed_at
 * @property \Carbon\Carbon $created_at
 * @property \Carbon\Carbon $updated_at
 *
 * @property Person $person
 * @property Inquiry $inquiry
 * @property QuestionnaireConfig|null $config
 */
class QuestionnaireAnswer extends Model
{
    use HasUlids;

    /**
     * The table associated with the model.
     * @var string
     */
    protected $table = 'questionnaire_answers';

    /**
     * The attributes that are mass assignable.
     * @var array<int, string>
     */
    protected $fillable = [
        'person_id',
        'inquiry_id',
        'questionnaire_config_id',
        'step1_answers',
        'step1_passed',
        'step1_rejection_reason',
        'step2_answers',
        'step2_triggered_c_rate',
        'step3_answers',
        'step3_triggered_b_rate',
        'step4_answers',
        'is_smoker',
        'years_smoking',
        'uses_vaping',
        'status',
        'rate_category',
        'rate_adjustment_factor',
        'rejection_reason',
        'review_notes',
        'started_at',
        'completed_at',
        'reviewed_at',
    ];

    /**
     * The attributes that should be cast.
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'step1_answers' => 'array',
            'step1_passed' => 'boolean',
            'step2_answers' => 'array',
            'step2_triggered_c_rate' => 'boolean',
            'step3_answers' => 'array',
            'step3_triggered_b_rate' => 'boolean',
            'step4_answers' => 'array',
            'is_smoker' => 'boolean',
            'uses_vaping' => 'boolean',
            'rate_adjustment_factor' => 'decimal:2',
            'started_at' => 'datetime',
            'completed_at' => 'datetime',
            'reviewed_at' => 'datetime',
        ];
    }

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

        // Set started_at when questionnaire is first created
        static::creating(function (QuestionnaireAnswer $questionnaire) {
            if (empty($questionnaire->started_at)) {
                $questionnaire->started_at = now();
            }
            
            // Initialize status if not set
            if (empty($questionnaire->status)) {
                $questionnaire->status = 'pending';
            }
            
            // Initialize rate adjustment factor
            if (empty($questionnaire->rate_adjustment_factor)) {
                $questionnaire->rate_adjustment_factor = 1.00;
            }
        });

        // When questionnaire is completed, set completed_at and evaluate answers
        static::updating(function (QuestionnaireAnswer $questionnaire) {
            if ($questionnaire->isDirty('status') && $questionnaire->status === 'completed') {
                if (empty($questionnaire->completed_at)) {
                    $questionnaire->completed_at = now();
                }
                
                // Auto-evaluate the questionnaire
                $questionnaire->evaluate();
            }
        });
    }

    /**
     * Relationship: Questionnaire belongs to a Person.
     * @return BelongsTo
     */
    public function person(): BelongsTo
    {
        return $this->belongsTo(Person::class, 'person_id');
    }

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

    /**
     * Relationship: Questionnaire uses a specific configuration.
     * @return BelongsTo
     */
    public function config(): BelongsTo
    {
        return $this->belongsTo(QuestionnaireConfig::class, 'questionnaire_config_id');
    }

    /**
     * Evaluate the questionnaire answers and determine rate category.
     * @return bool True if evaluation was successful
     */
    public function evaluate(): bool
    {
        // Step 1: Check eligibility
        if (!$this->evaluateStep1()) {
            $this->status = 'rejected';
            $this->save();
            return false;
        }

        // Step 2: Check for C Rate triggers
        if ($this->evaluateStep2()) {
            $this->rate_category = 'C';
        }
        // Step 3: Check for B Rate triggers (only if not C)
        elseif ($this->evaluateStep3()) {
            $this->rate_category = 'B';
        }
        // Default to A Rate
        else {
            $this->rate_category = 'A';
        }

        // Step 4: Apply smoking adjustment
        $this->applySmokingAdjustment();

        // Mark as completed
        $this->status = 'completed';
        $this->save();

        return true;
    }

    /**
     * Evaluate Step 1 (Eligibility Check).
     * @return bool True if eligible, false otherwise
     */
    private function evaluateStep1(): bool
    {
        if (!$this->step1_answers) {
            $this->step1_passed = false;
            $this->step1_rejection_reason = 'No answers provided for Step 1';
            return false;
        }

        // Check each answer in Step 1
        foreach ($this->step1_answers as $questionId => $answer) {
            // For Manulife questionnaire: If any answer is "yes" in Step 1, applicant is not eligible
            if ($answer === 'yes' || $answer === true) {
                $this->step1_passed = false;
                $this->step1_rejection_reason = 'Failed eligibility check in Step 1';
                return false;
            }
        }

        $this->step1_passed = true;
        return true;
    }

    /**
     * Evaluate Step 2 (C Rate Triggers).
     * @return bool True if C rate is triggered
     */
    private function evaluateStep2(): bool
    {
        if (!$this->step2_answers) {
            $this->step2_triggered_c_rate = false;
            return false;
        }

        // Check if any answer in Step 2 triggers C rate
        foreach ($this->step2_answers as $questionId => $answer) {
            if ($answer === 'yes' || $answer === true) {
                $this->step2_triggered_c_rate = true;
                return true;
            }
        }

        $this->step2_triggered_c_rate = false;
        return false;
    }

    /**
     * Evaluate Step 3 (B Rate Triggers).
     * @return bool True if B rate is triggered
     */
    private function evaluateStep3(): bool
    {
        if (!$this->step3_answers) {
            $this->step3_triggered_b_rate = false;
            return false;
        }

        // Check if any answer in Step 3 triggers B rate
        foreach ($this->step3_answers as $questionId => $answer) {
            if ($answer === 'yes' || $answer === true) {
                $this->step3_triggered_b_rate = true;
                return true;
            }
        }

        $this->step3_triggered_b_rate = false;
        return false;
    }

    /**
     * Apply smoking adjustment to rate factor.
     * @return void
     */
    private function applySmokingAdjustment(): void
    {
        if ($this->is_smoker || $this->uses_vaping) {
            // Apply 10% surcharge for smokers/vapers
            $this->rate_adjustment_factor = 1.10;
        } else {
            $this->rate_adjustment_factor = 1.00;
        }
    }

    /**
     * Check if questionnaire is completed.
     * @return bool
     */
    public function isCompleted(): bool
    {
        return $this->status === 'completed';
    }

    /**
     * Check if questionnaire is pending.
     * @return bool
     */
    public function isPending(): bool
    {
        return $this->status === 'pending';
    }

    /**
     * Check if questionnaire is rejected.
     * @return bool
     */
    public function isRejected(): bool
    {
        return $this->status === 'rejected';
    }

    /**
     * Check if questionnaire requires review.
     * @return bool
     */
    public function requiresReview(): bool
    {
        return $this->status === 'requires_review';
    }

    /**
     * Get the rate category with description.
     * @return string
     */
    public function getRateCategoryDescription(): string
    {
        return match($this->rate_category) {
            'A' => 'Standard Rate (Lowest Risk)',
            'B' => 'Medium Rate (Moderate Risk)',
            'C' => 'High Rate (Higher Risk)',
            default => 'Not Determined',
        };
    }

    /**
     * Get the status in a user-friendly format.
     * @return string
     */
    public function getStatusFormatted(): string
    {
        return ucfirst(str_replace('_', ' ', $this->status));
    }

    /**
     * Calculate completion percentage.
     * @return int Percentage (0-100)
     */
    public function getCompletionPercentage(): int
    {
        $stepsCompleted = 0;
        $totalSteps = 4;

        if ($this->step1_answers) $stepsCompleted++;
        if ($this->step2_answers) $stepsCompleted++;
        if ($this->step3_answers) $stepsCompleted++;
        if ($this->step4_answers) $stepsCompleted++;

        return (int) (($stepsCompleted / $totalSteps) * 100);
    }

    /**
     * Get the time taken to complete questionnaire.
     * @return string|null Formatted duration or null if not completed
     */
    public function getCompletionTime(): ?string
    {
        if (!$this->started_at || !$this->completed_at) {
            return null;
        }

        $duration = $this->started_at->diff($this->completed_at);
        
        if ($duration->d > 0) {
            return $duration->format('%d days %h hours');
        } elseif ($duration->h > 0) {
            return $duration->format('%h hours %i minutes');
        } else {
            return $duration->format('%i minutes %s seconds');
        }
    }

    /**
     * Check if person is eligible for insurance based on questionnaire.
     * @return bool
     */
    public function isEligible(): bool
    {
        return $this->step1_passed === true && !$this->isRejected();
    }

    /**
     * Get smoking status description.
     * @return string
     */
    public function getSmokingStatus(): string
    {
        if ($this->is_smoker && $this->uses_vaping) {
            return 'Smoker & Vaper';
        } elseif ($this->is_smoker) {
            return 'Smoker';
        } elseif ($this->uses_vaping) {
            return 'Vaper';
        } else {
            return 'Non-Smoker';
        }
    }

    /**
     * Scope: Only completed questionnaires.
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeCompleted($query)
    {
        return $query->where('status', 'completed');
    }

    /**
     * Scope: Only pending questionnaires.
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopePending($query)
    {
        return $query->where('status', 'pending');
    }

    /**
     * Scope: Only rejected questionnaires.
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeRejected($query)
    {
        return $query->where('status', 'rejected');
    }

    /**
     * Scope: Questionnaires for a specific rate category.
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param string $category Rate category (A, B, C)
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeForRateCategory($query, string $category)
    {
        return $query->where('rate_category', $category);
    }

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

    /**
     * Scope: Questionnaires completed within a date range.
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param \Carbon\Carbon $startDate
     * @param \Carbon\Carbon $endDate
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeCompletedBetween($query, \Carbon\Carbon $startDate, \Carbon\Carbon $endDate)
    {
        return $query->whereBetween('completed_at', [$startDate, $endDate]);
    }

    /**
     * Get all answers as a flat array for display.
     * @return array
     */
    public function getAllAnswers(): array
    {
        $answers = [];
        
        // Merge answers from all steps
        if ($this->step1_answers) {
            foreach ($this->step1_answers as $key => $value) {
                $answers['step1_' . $key] = $value;
            }
        }
        
        if ($this->step2_answers) {
            foreach ($this->step2_answers as $key => $value) {
                $answers['step2_' . $key] = $value;
            }
        }
        
        if ($this->step3_answers) {
            foreach ($this->step3_answers as $key => $value) {
                $answers['step3_' . $key] = $value;
            }
        }
        
        if ($this->step4_answers) {
            foreach ($this->step4_answers as $key => $value) {
                $answers['step4_' . $key] = $value;
            }
        }
        
        // Add smoking information
        $answers['is_smoker'] = $this->is_smoker;
        $answers['years_smoking'] = $this->years_smoking;
        $answers['uses_vaping'] = $this->uses_vaping;
        
        return $answers;
    }

    /**
     * Reset questionnaire to initial state.
     * @return void
     */
    public function reset(): void
    {
        $this->update([
            'step1_answers' => null,
            'step1_passed' => null,
            'step1_rejection_reason' => null,
            'step2_answers' => null,
            'step2_triggered_c_rate' => null,
            'step3_answers' => null,
            'step3_triggered_b_rate' => null,
            'step4_answers' => null,
            'status' => 'pending',
            'rate_category' => null,
            'rate_adjustment_factor' => 1.00,
            'rejection_reason' => null,
            'completed_at' => null,
            'reviewed_at' => null,
        ]);
    }
}