<?php

namespace App\Services;

use App\Models\Contract;
use App\Models\ContractRequest;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Ramsey\Uuid\Uuid;
use Throwable;

class EsignService {
    protected string $endpoint;
    protected int $timeout;

    public function __construct() {
        $this->endpoint = config('services.esign.endpoint', 'https://sign.theclaimsystem.co.uk/api/send-request');
        $this->timeout = config('services.esign.timeout', 10);
    }

    /**
     * Send an eSign request.
     *
     * @param ContractRequest $request
     * @return array|null
     */
    public function send(ContractRequest $request): ?array {
        $externalId = $externalId ?? Uuid::uuid4()->toString();

        $client = $request->client;

        $documentType = Contract::whereIn('id', $request->contract_ids)->pluck('name')->map(function ($item) {
            return Str::slug($item);
        })->toArray();

        $user = auth()->user();

        $payload = [
            'email' => (string)$client->email_address,
            'phone' => (string)$client->phone_number,
            'document_type' => $documentType,
            'external_id' => $request->slug,
            'prefill_data' => $this->getPrefillData($request, new ApplicationService()),
            'sign_data' => [
                'client_name' => $client->fullName,
                'client_phone' => (string)$client->phone_number,
                'sender_name' => $user->name_first . " " . $user->name_last,
                'sender_ip' => request()->ip(),
            ]
        ];

        Log::info('eSign request initiated', [
            'external_id' => $externalId,
            'document_type' => $documentType,
        ]);

        try {
            $response = Http::timeout($this->timeout)
                ->retry(3, 500)
                ->acceptJson()
                ->asJson()
                ->post($this->endpoint, $payload);

            if ($response->failed()) {
                Log::error('eSign request failed', [
                    'external_id' => $externalId,
                    'status' => $response->status(),
                    'response' => $response->body(),
                ]);

                return null;
            }

            Log::info('eSign request successful', [
                'external_id' => $externalId,
                'status' => $response->status(),
            ]);

            return $response->json();
        } catch (Throwable $e) {
            Log::critical('eSign request exception', [
                'external_id' => $externalId,
                'message' => $e->getMessage(),
            ]);

            return null;
        }
    }

    public function getPrefillData(ContractRequest $request, ApplicationService $service): ?array {
        $data = [];
        $client = $request->client;
        $clientName = collect([$client->name_first, $client->name_middle, $client->name_last])->filter()->implode(' ');
        $user = auth()->user();

        foreach ($request->contract_ids as $contractId) {
            $name = Str::slug(Contract::find($contractId)->name);
            switch ($name) {
                case 'cfa':
                    $data[$name] = [
                        'fields' => [
                            'date' => date('d/m/Y'),
                            'date_2' => date('d/m/Y'),
                            'date_3' => date('d/m/Y'),
                            'client_full_name_2' => $clientName,
                            'client_full_name_3' => $clientName,
                            'client_full_name' => $clientName,
                            'client_full_nam' => $clientName,
                            'reference' => "MMA" . str_pad($client->id, 5, '0', STR_PAD_LEFT),
                        ],
                        'signature_positions' => [
                            ['page' => 6, 'x' => 100, 'y' => 110, 'w' => 100, 'h' => 40]
                        ]
                    ];
                    break;
                case 'loa':
                    $address = $client->currentAddress;

                    $data[$name] = [
                        'fields' => [
                            'date' => date('d/m/Y'),
                            'date_2' => date('d/m/Y'),
                            'date_3' => date('d/m/Y'),

                            'client_full_name' => $clientName,
                            'client_full_name_2' => $clientName,
                            'date_of_birth' => $client->date_of_birth?->format('d/m/Y'),

                            'current_address' => collect([$address->line_1, $address->line_2, $address->line_3, $address->postcode])->filter()->implode("\n"),

                            'prev_name' => $client->previousNames()->first()?->fullName,

                            'witness_name' => $user->name_first . ' ' . $user->name_last,
                            'witness_signature' => $user->name_first . ' ' . $user->name_last,
                            'witness_occupation' => "Case Handler",
                            'witness_address' => "STOK, 43-59 Princes St, Stockport, SK1 1RY",

                            'firm_name' => 'MMA Legal',
                            'firm_address' => "STOK, 43-59 Princes St, Stockport",
                            'firm_postcode' => 'SK1 1RY',
                            'firm_email' => 'casemanagement@mmalegal.co.uk',
                            'firm_tel' => '0161 532 3544',
                        ],
                        'signature_positions' => [
                            ['page' => 4, 'x' => 110, 'y' => 135, 'w' => 100, 'h' => 25]
                        ]
                    ];
                    break;
                case 'part-1':
                    $l = $service->getPreviewData($request->client);
                    $data[$name] = $l['part_1'];
                    if(isset($l['part_1_extra'])) {
                        $data['part-1-extra'] = $l['part_1_extra'];
                    }
                    break;
                case 'part-3':
                    $l = $service->getPreviewData($request->client);
                    $data[$name] = $l['part_3'];
                    if(isset($l['part_3_extra'])) {
                        $data['part-3-extra'] = $l['part_3_extra'];
                    }
                    break;
                case 'fee-clarity':
                    $data[$name] = [
                        'fields' => [
                            'date' => date('d/m/Y'),
                            'date_2' => date('d/m/Y'),
                            'client_full_name_2' => $clientName,
                            'client_full_nam' => $clientName,
                            'reference' => "MMA" . str_pad($client->id, 5, '0', STR_PAD_LEFT),
                        ],
                        'signature_positions' => [
                            ['page' => 2, 'x' => 100, 'y' => 160, 'w' => 100, 'h' => 40]
                        ]
                    ];
                    break;
                default:
                    break;
            }
        }

        return $data;
    }
}
