<?php

namespace App\Models\PensionCase;

use App\Interface\DocumentOwner;
use App\Interface\HistoryOwner;
use App\Interface\NoteOwner;
use App\Models\Client\Client;
use App\Trait\HasDocuments;
use App\Trait\HasHistory;
use App\Trait\HasNotes;
use App\Trait\HasSlug;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Database\Factories\PensionCase\PensionCaseFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

class PensionCase extends Model implements DocumentOwner, NoteOwner, HistoryOwner {
    use HasFactory, HasSlug, HasNotes, HasDocuments, HasHistory;

    protected static function newFactory(): PensionCaseFactory {
        return PensionCaseFactory::new();
    }

    protected $table = 'pension_cases';

    protected $fillable = [
        'client_id',
        'sf_case_id',
        'case_number',
        'case_owner',
        'created_by',
        'case_last_modified_by',
        'claims_writer',
        'file_investigator',
        'opened_at',
        'case_last_modified_at',
        'closed_at',
        'is_open',
        'is_closed',
        'claim_subject',
        'claim_basis',
        'priority',
        'settlement_status',
        'bank_claim_status',
        'fos_claim_status',
        'fscs_claim_status',
        'client_settlement_instruction',
        'reasons_for_not_proceeding',
        'additional_claims_info',
        'detail_of_outstanding_evidence',
        'underlying_investment',
        'investment_library',
        'pcp_subject',
        'fscs_contact_name',
        'fscs_contact_reference',
        'fscs_reference',
        'national_insurance',
        'cmc_client_reference',
        'car_reg',
        'atc',
        'tob_issued_by',
        'sar_to',
        'lead_source_cpf',
        'fee_structure',
        'vulnerable_client_flag',
        'vulnerable_client_details',
        'special_contact_requirements_flag',
        'special_contact_requirements_details',
        'sms_opt_out',
        'do_not_contact',
        'ifa_referred',
        'ifa_refer_opted_out',
        'client_in_dispute',
        'sar_sent',
        'sar_received',
        'fee_capping_flag',
        'atc_received',
        'settlement_to_date_raw',
        'settlement_to_date_new',
        'projected_future_settlement',
        'quantum',
        'cpfc_fee_percentage',
        'cpfc_fee_total_nett',
        'our_fees_percentage_raw',
        'issued_tob_date',
        'tob_in_date',
        'ifa_referred_date',
        'application_submitted_date',
        'date_requested_evidence',
        'fos_allocated_date',
        'fos_app_submitted_date',
        'fos_app_written_sent_to_client_date',
        'fos_complaint_letter_sent_to_client_date',
        'fos_initial_complaint_sent_date',
        'fos_under_review_with_investigator_date',
        'fscs_allocated_date',
        'sar_received_date',
        'sar_reviewed_scanned_date',
        'application_out_for_signature_date',
        'allocated_to_investigator_date',
    ];

    protected $casts = [
        'is_open' => 'boolean',
        'is_closed' => 'boolean',
        'vulnerable_client_flag' => 'boolean',
        'special_contact_requirements_flag' => 'boolean',
        'sms_opt_out' => 'boolean',
        'do_not_contact' => 'boolean',
        'ifa_referred' => 'boolean',
        'ifa_refer_opted_out' => 'boolean',
        'client_in_dispute' => 'boolean',
        'sar_sent' => 'boolean',
        'sar_received' => 'boolean',
        'fee_capping_flag' => 'boolean',
        'atc_received' => 'boolean',
        'opened_at' => 'datetime',
        'closed_at' => 'datetime',
        'case_last_modified_at' => 'datetime',
        'issued_tob_date' => 'date',
        'tob_in_date' => 'date',
        'ifa_referred_date' => 'date',
        'application_submitted_date' => 'date',
        'date_requested_evidence' => 'date',
        'fos_allocated_date' => 'date',
        'fos_app_submitted_date' => 'date',
        'fos_app_written_sent_to_client_date' => 'date',
        'fos_complaint_letter_sent_to_client_date' => 'date',
        'fos_initial_complaint_sent_date' => 'date',
        'fos_under_review_with_investigator_date' => 'date',
        'fscs_allocated_date' => 'date',
        'sar_received_date' => 'date',
        'sar_reviewed_scanned_date' => 'date',
        'application_out_for_signature_date' => 'date',
        'allocated_to_investigator_date' => 'date',
        'settlement_to_date_raw' => 'decimal:2',
        'settlement_to_date_new' => 'decimal:2',
        'projected_future_settlement' => 'decimal:2',
        'quantum' => 'decimal:2',
        'cpfc_fee_percentage' => 'decimal:4',
        'cpfc_fee_total_nett' => 'decimal:2',
        'our_fees_percentage_raw' => 'decimal:4',
    ];

    // -----------------------------------------------------------------------
    // Relationships
    // -----------------------------------------------------------------------

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

    public function comments(): HasMany {
        return $this->hasMany(PensionCaseComment::class)->orderByDesc('created_at');
    }

    public function interims(): HasMany {
        return $this->hasMany(PensionCaseInterim::class)->orderBy('interim_number');
    }

    // -----------------------------------------------------------------------
    // Query scopes
    // -----------------------------------------------------------------------

    public function scopeOpen($query) {
        return $query->where('is_open', true);
    }

    public function scopeClosed($query) {
        return $query->where('is_closed', true);
    }

    public function scopeVulnerable($query) {
        return $query->where('vulnerable_client_flag', true);
    }

    public function scopeByOwner($query, string $owner) {
        return $query->where('case_owner', $owner);
    }

    public function scopeBySettlementStatus($query, string $status) {
        return $query->where('settlement_status', $status);
    }

    public function scopeByBankStatus($query, string $status) {
        return $query->where('bank_claim_status', $status);
    }

    public function scopeByFosStatus($query, string $status) {
        return $query->where('fos_claim_status', $status);
    }

    public function scopeByFscsStatus($query, string $status) {
        return $query->where('fscs_claim_status', $status);
    }

    // -----------------------------------------------------------------------
    // Computed attributes
    // -----------------------------------------------------------------------

    protected function displayId(): Attribute {
        return Attribute::make(
            get: fn() => 'PC' . str_pad($this->id, 6, '0', STR_PAD_LEFT),
        );
    }

    // -----------------------------------------------------------------------
    // DocumentOwner contract
    // -----------------------------------------------------------------------

    public function getDocumentStoragePath(): string {
        return 'clients/' . $this->client->slug . '/pension-cases/' . $this->id . '/';
    }
}
