<?php

namespace App\Console\Commands;

use App\Models\Client\Client;
use App\ValueObjects\Postcode;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use League\Csv\Reader;

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

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

        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/m/Y', $cleaned['date_of_birth'])
                            ->format('Y-m-d');
                    } catch (\Exception $e) {
                        $dob = null;
                    }
                }

                $client = Client::create([
                    'solicitor_id' => 1,
                    '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' => 1,
                        'line_1' => $cleaned['line_1'],
                        'line_2' => $cleaned['line_2'] ?? null,
                        'line_3' => $cleaned['line_3'] ?? null,
                        'postcode' => Postcode::fromString($cleaned['postcode'])->format(),
                        'is_current' => true,
                    ]);
                }

                $claim = $client->claim()->create([
                    'solicitor_id' => 1,
                    'redress_type' => 'INDIVIDUAL',
                    'case_number' => $cleaned['case_number'],
                    'status_id' => 1
                ]);

                if (isset($cleaned['notes']) && strlen($cleaned['notes']) > 2) {
                    $client->notes()->create([
                        'solicitor_id' => 1,
                        '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()->create([
                            'solicitor_id' => 1,
                            'first_name' => $benFirst,
                            'middle_name' => $cleaned['beneficiary_middle_name'] ?? null,
                            'surname' => $benLast,
                            '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,
                        ]);
                    }
                }

                if (isset($cleaned['age']) || isset($cleaned['cs1']) || isset($cleaned['reason']) || isset($cleaned['police'])) {
                    $claim->careSettings()->create([
                        'claim_id' => $claim->id,
                        'institution_id' => 1,
                        'solicitor_id' => 1,
                        'statement' => $cleaned['age'] . " " . ($cleaned['cs1'] ?? '') . " " . $cleaned['reason'] . " " . $cleaned['police']
                    ]);
                }
            }

            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\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)));
    }
}
