<?php

namespace App\Console\Commands;

use App\Models\Client\Client;
use App\Models\Dsar\DsarType;
use App\Models\Institution\Institution;
use App\Models\Institution\InstitutionType;
use Carbon\Carbon;
use Exception;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use League\Csv\Reader;
use Throwable;

class ImportClients extends Command {
    protected $signature = 'clients:import {path} {solicitorId=1}';
    protected $description = 'Import clients from a CSV file';

    public $primaryOptions = [
        'passport' => 'Passport',
        'drivers_license' => 'Full or provisional driving licence (with a photo)',
        'national_id' => 'European Economic Area (EEA) national identity card',
        'brp' => 'Biometric Residence Permit (BRP)',
        'na' => 'Not Available',
    ];

    public $list1Options = [
        'utility_bill' => 'full version of your birth certificate',
        'marriage_cert' => 'marriage or civil partnership certificate',
        'drivers_license_paper' => 'UK driving licence without a photo (paper version)',
        'entitlement_card' => 'National Entitlement Card (Scotland only)',
        'identity_card' => 'identity photo card with PASS logo (this includes a Young Scot card)',
        'forces_card' => 'HM Forces ID card',
    ];

    public $list2Options = [
        'medical_letter' => 'official letter from a medical professional (for example the NHS or your doctor)',
        'utility_bill' => 'utility bill from the last 3 months',
        'financial_letter' => 'official letter from a financial institution (for example your bank)',
        'tenancy_agmt' => 'tenancy agreement (UK only)',
        'mortgage_stmt' => 'mortgage statement (UK only)',
        'tax_letter' => 'letter from HMRC or DWP (UK only)',
        'tax_stmt' => 'council tax statement (UK only)',
        'dwp_letter' => 'P45 or P60 (UK only)',
        'homeless_letter' => 'homeless registration letter from a local authority (UK only)',
    ];

    public $supportingDocsProvided = [
        'NA' => 'Not applicable',
        'Help' => 'The client needs help to find them',
        'Yes' => 'The client has provided them with the form'
    ];

    public $statuses = [
        '01 New Campaign Lead' => 21,
        '02 First Communication' => 20,
        '05 DSARS' => 24,
        '08 Awaiting Panel Decision' => 17,
        '23 TBC' => 32
    ];

    public function handle(): int {
        $path = $this->argument('path');
        $solicitorId = $this->argument('solicitorId');

        if (!file_exists($path)) {
            $this->error("File not found.");
            return self::FAILURE;
        }

        $this->info("Starting import...");

        DB::beginTransaction();

        try {

            $csv = Reader::createFromPath($path, 'r');
            $csv->setHeaderOffset(0);

            foreach ($csv->getRecords() as $row) {

                $cleaned = $this->cleanRow($row);

                $dob = null;

                if (!empty($cleaned['date_of_birth'])) {
                    try {
                        $dob = Carbon::createFromFormat('d/n/Y', $cleaned['date_of_birth'])
                            ->format('Y-m-d');
                    } catch (Exception $e) {
                        $dob = null;
                    }
                }

                $client = Client::create([
                    'solicitor_id' => $solicitorId,
                    'name_first' => $cleaned['name_first'],
                    'name_middle' => $cleaned['name_middle'],
                    'name_last' => $cleaned['name_last'],
                    'name_preferred' => $cleaned['name_preferred'] ?? null,
                    'date_of_birth' => $dob,
                    'email_address' => $cleaned['email_address'],
                    'phone_number' => $cleaned['phone_number'],
                ]);

                if ($cleaned['postcode']) {
                    $client->addresses()->updateOrCreate([
                        'solicitor_id' => $solicitorId,
                        'line_1' => $cleaned['line_1'],
                        'line_2' => $cleaned['line_2'] ?? null,
                        'line_3' => $cleaned['line_3'] ?? null,
                        'postcode' => $cleaned['postcode'],
                        'is_current' => true,
                    ]);
                }

                $claim = $client->claim()->updateOrCreate([
                    'client_id' => $client->id
                ], [
                    'solicitor_id' => $solicitorId,
                    'redress_type' => 'INDIVIDUAL',
                    'case_number' => $cleaned['case_number'],
                    'redress_case_worker' => $cleaned['case_worker'],
                    'status_id' => $this->statuses[$cleaned['status']],
                ]);

                $client->confirmIdentity()->updateOrCreate([
                    'client_id' => $client->id
                ], [
                    'solicitor_id' => $solicitorId,
                    'provides_docs' => true,
                    'primary_doc_type' => array_search($cleaned['primary_doc_type'], $this->primaryOptions) ?: null,
                    'list1_doc_type' => array_search($cleaned['list_1_doc_type'], $this->list1Options) ?: null,
                    'list2_doc_type' => array_search($cleaned['list2_doc_type'], $this->list2Options) ?: null,
                ]);

                if ($cleaned['opt_in_email'] == 'YES') {
                    $client->optIns()->syncWithoutDetaching(1);
                }

                if ($cleaned['opt_in_phone'] == 'YES') {
                    $client->optIns()->syncWithoutDetaching(3);
                }

                $claim->furtherInformation()->updateOrCreate([
                    'claim_id' => $claim->id,
                ], [
                    'apply_aps' => $cleaned['7a_apply'] == 'YES',
                    'confirm_care_setting' => $cleaned['7a_apply_permission'] == 'YES',
                    'name_in_care' => $cleaned['7a_name'],
                    'legal_name_change' => $cleaned['7a_legal_name'],
                    'supporting_docs_provision' => array_search($cleaned['7a_supporting_docs'], $this->supportingDocsProvided),
                ]);

                $claim->impactDetail()->updateOrCreate(
                    ['claim_id' => $claim->id],
                    [
                        'has_received_relevant_payment' => false,
                        'has_criminal_conviction' => $cleaned['8_cc'] == 'YES',
                        'payment_date' => null,
                        'paying_organisation' => null,
                        'payment_amount' => null,
                    ]
                );

                for ($i = 1; $i <= 7; $i++) {

                    $name = $cleaned["care_setting_{$i}_name"] ?? null;

                    if ($name) {
                        $institution = Institution::create([
                            'solicitor_id' => $solicitorId,
                            'display_name' => $name,
                            'institution_type_id' => InstitutionType::first()->id,
                            'dsar_type_id' => DsarType::first()->id ?? null,
                        ]);

                        $claim->careSettings()->create([
                            'solicitor_id' => $solicitorId,
                            'institution_id' => $institution->id,
                            'people_involved' => $cleaned["care_setting_{$i}_people"] ?? null,
                            'dates' => $cleaned["care_setting_{$i}_dates"] ?? null,
                        ]);
                    }
                }

                if ($cleaned['bank_name']) {
                    $claim->bankDetail()->updateOrCreate(
                        ['claim_id' => $claim->id],
                        [
                            'name_on_account' => $cleaned['bank_name'],
                            'sort_code' => $cleaned['bank_sort_code'],
                            'account_number' => $cleaned['bank_account_number'],
                            'clearing_code' => $cleaned['bank_cc'],
                        ]
                    );
                }

                if (isset($cleaned['notes']) && strlen($cleaned['notes']) > 2) {
                    $client->notes()->create([
                        'solicitor_id' => $solicitorId,
                        'user_id' => 1,
                        'client_id' => $client->id,
                        'note' => $cleaned['notes'],
                    ]);
                }

                $benNameFull = $cleaned['beneficiary_name_first'] ?? '';

                if (!empty($benNameFull)) {
                    if (empty($benFirst) && !empty($benNameFull)) {
                        $parts = explode(' ', trim($benNameFull));
                        $benFirst = array_shift($parts); // First part
                        $benLast = implode(' ', $parts); // Rest is last name


                        $claim->beneficiary()->updateOrCreate([
                            'claim_id' => $claim->id,
                        ], [
                            'solicitor_id' => $solicitorId,
                            'first_name' => $benFirst,
                            'middle_name' => $cleaned['beneficiary_middle_name'] ?? null,
                            'surname' => $benLast,
                            'date_of_birth' => $cleaned['beneficiary_dob'],
                            'address_line_1' => $cleaned['beneficiary_address_line_1'] ?? null,
                            'address_line_2' => $cleaned['beneficiary_address_line_2'] ?? null,
                            'address_line_3' => $cleaned['beneficiary_address_line_3'] ?? null,
                            'address_line_4' => $cleaned['beneficiary_address_line_4'] ?? null,
                            'postcode' => $cleaned['beneficiary_postcode'] ?? null,
                            'email' => $cleaned['beneficiary_email'] ?? null,
                            'telephone' => $cleaned['beneficiary_telephone'] ?? null,
                        ]);
                    }
                }

                foreach ([
                             'lead_generated' => 1,
                             'intro_email' => 33,
                             'initial_call' => 34,
                             'app_submitted' => 13,
                             'pre_dsar' => 32,
                             'statement_production' => 35,
                             'info_resubmitted' => 17,
                             'panel_meets' => 15
                         ] as $keyDate => $valueDate) {
                    if ($cleaned[$keyDate]) {
                        try {
                            $date = Carbon::createFromFormat('d/n/Y', $cleaned[$keyDate])
                                ->format('Y-m-d');
                        } catch (Exception $e) {
                            $date = null;
                        }

                        if ($date) {
                            $claim->keyDates()->syncWithoutDetaching([
                                $valueDate => ['date' => $date]
                            ]);
                        }
                    }
                }
            }

            DB::commit();
            $this->info("Import complete!");

        } catch
        (Throwable $e) {

            DB::rollBack();
            $this->error("Import failed: " . $e->getMessage());

            return self::FAILURE;
        }

        return self::SUCCESS;
    }

    /**
     * Master row cleaner
     */
    protected function cleanRow(array $row): array {
        return collect($row)->mapWithKeys(function ($value, $key) {
            return [
                $this->cleanHeader($key) => $this->cleanValue($value)
            ];
        })->toArray();
    }

    /**
     * Header normalisation
     */
    protected function cleanHeader(string $header): string {
        return strtolower(trim(str_replace([' ', '-'], '_', $header)));
    }

    /**
     * Universal value cleaner
     */
    protected function cleanValue($value) {
        if (is_null($value)) {
            return null;
        }

        $value = trim($value);

        if ($value === '') {
            return null;
        }

        return $value;
    }

    /**
     * Email normaliser
     */
    protected function cleanEmail(?string $email): ?string {
        if (!$email) {
            return null;
        }

        $email = strtolower(trim($email));

        return filter_var($email, FILTER_VALIDATE_EMAIL) ? $email : null;
    }

    /**
     * Phone normaliser (UK friendly)
     */
    protected function cleanPhone(?string $phone): ?string {
        if (!$phone) {
            return null;
        }

        return preg_replace('/[^0-9+]/', '', $phone);
    }

    /**
     * Boolean normaliser
     */
    protected function cleanBoolean($value): ?bool {
        $value = strtolower(trim($value));

        return match ($value) {
            'yes', '1', 'true' => true,
            'no', '0', 'false' => false,
            default => null,
        };
    }

    /**
     * Date normaliser
     */
    protected function cleanDate(?string $date): ?string {
        if (!$date) {
            return null;
        }

        try {
            return Carbon::parse($date)->format('Y-m-d');
        } catch (Exception) {
            return null;
        }
    }

    /**
     * Name cleaner
     */
    protected function cleanName(?string $name): ?string {
        if (!$name) {
            return null;
        }

        return ucwords(strtolower(trim($name)));
    }

    public function getPrimaryDocType($type) {
        switch ($type) {
            case 'Passport':
                return 'passport';
            case 'Full or provisional license (with a photo)':
                return 'drivers_license';
            default:
                return null;
        }
    }

    public function getList1DocType($type) {}
}
