<?php

namespace App\Services;

use App\Core\Citizenship\CitizenshipManager;
use App\Models\CitizenshipCountrySetting;
use App\Models\Client;
use App\Models\ClientVerification;
use App\Models\Log as ActivityLog;
use App\Models\Setting;
use App\Services\NotificationService;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Str;

class CitizenshipService
{
    protected CitizenshipManager $manager;

    public function __construct()
    {
        $this->manager = new CitizenshipManager();
    }

    public function isEnabled(): bool
    {
        return (bool) Setting::getValue('citizenship_verification', false)
            || (bool) Setting::getValue('verification_enabled', false);
    }

    public function getMode(): string
    {
        return Setting::getValue('citizenship_verification_mode', 'disabled');
    }

    public function getCountrySettings(string $countryCode): ?CitizenshipCountrySetting
    {
        return CitizenshipCountrySetting::where('country_code', strtoupper($countryCode))->first();
    }

    public function getManager(): CitizenshipManager
    {
        return $this->manager;
    }

    public function getAvailableModules(): array
    {
        return $this->manager->listAvailableModules();
    }

    /**
     * Process verification — validates all enabled fields via module.
     */
    public function processVerification(Client $client, string $countryCode, array $data, ?UploadedFile $document = null): array
    {
        $countrySettings = $this->getCountrySettings($countryCode);
        if (! $countrySettings) {
            return ['success' => true, 'message' => 'No verification required.'];
        }

        $module = $this->manager->get($countryCode);
        if (! $module) {
            return ['success' => true, 'message' => 'No module for this country.'];
        }

        $fieldSettings = $countrySettings->field_settings ?? [];
        $verificationFields = $module->getVerificationFields();
        $verificationType = $data['verification_type'] ?? 'individual';
        $errors = [];
        $verifiedData = [];

        // PRC-1067: API doğrulayıcılar (ör. TR/NVI MERNIS TCKimlikNoDogrula)
        // client kimlik alanlarını (first_name/last_name) GEREKTİRİR; bunlar
        // doğrulama FORM alanı DEĞİL (getVerificationFields tanımlamaz) → Client'tan
        // enjekte et. Form input öncelikli (varsa), yoksa Client'ın kayıtlı adı.
        // Bu enjeksiyon olmadan NVI guard (ad boş) her doğrulamada fail ediyordu.
        $apiContext = array_merge([
            'first_name' => $client->first_name,
            'last_name' => $client->last_name,
        ], $data);

        foreach ($verificationFields as $fieldKey => $fieldDef) {
            $fieldConfig = $fieldSettings[$fieldKey] ?? [];
            if (empty($fieldConfig['enabled'])) {
                continue;
            }

            $group = $fieldDef['group'] ?? 'general';
            if ($group !== 'general' && $group !== $verificationType) {
                continue;
            }

            $value = trim($data[$fieldKey] ?? '');
            $isRequired = ! empty($fieldConfig['required']);

            if (empty($value)) {
                if ($isRequired) {
                    $errors[] = ($fieldDef['label'] ?? $fieldKey) . ' alanı zorunludur.';
                }

                continue;
            }

            $result = $module->validateField($fieldKey, $value, $apiContext);
            if (! $result['valid']) {
                $errors[] = $result['message'];

                continue;
            }

            $verifiedData[$fieldKey] = $value;
        }

        if (! empty($errors)) {
            return ['success' => false, 'errors' => $errors];
        }

        // verified_data is the single source of truth (encrypted at rest)
        $verification = $this->createVerification($client, [
            'type' => $verificationType,
            'verified_data' => $verifiedData,
            'method' => 'format',
            'status' => 'verified',
        ]);

        // If API verification is enabled and validation passed, the API has already
        // confirmed identity — document upload becomes supplementary, no admin review needed.
        $apiVerified = (bool) $countrySettings->api_verification_enabled;

        // Persist uploaded document (if any) to private disk with a UUID filename
        if ($document !== null) {
            $extension = $document->getClientOriginalExtension() ?: 'bin';
            $filename = (string) Str::uuid() . '.' . $extension;
            $path = $document->storeAs('verifications', $filename, 'private');

            $verification->document_path = $path;
            $verification->document_type = $document->getClientMimeType();
            $verification->verification_method = $apiVerified ? 'api' : 'document';
            $verification->status = $apiVerified ? 'verified' : 'pending';
            $verification->save();
        }

        $finalStatus = $verification->status; // 'verified' or 'pending'
        $client->update(['verification_status' => $finalStatus]);

        // Set expiry on any verified record (covers no-doc and API-verified-with-doc paths)
        if ($finalStatus === 'verified' && empty($verification->expires_at)) {
            $days = (int) (Setting::where('key', 'verification_expiry_days')->value('value') ?? 365);
            $verification->expires_at = now()->addDays($days);
            $verification->save();
        }

        ActivityLog::create([
            'type' => ActivityLog::TYPE_CLIENT,
            'observer' => 'CitizenshipService',
            'module' => 'Verification',
            'method' => 'submit',
            'client_id' => $client->id,
            'description' => "Citizenship verification submitted (status: {$finalStatus})",
            'ip_address' => request()->ip() ?? '0.0.0.0',
            'user_agent' => request()->userAgent(),
        ]);

        // Notify admins (with 'approve verifications' permission) when admin review is required
        if ($finalStatus === 'pending') {
            $this->notifyPendingVerification($client, $verification);
        }

        return ['success' => true, 'message' => 'Verification processed successfully.'];
    }

    public function createVerification(Client $client, array $data): ClientVerification
    {
        return ClientVerification::create([
            'client_id' => $client->id,
            'type' => $data['type'] ?? 'individual',
            'verified_data' => $data['verified_data'] ?? null,
            'verification_method' => $data['method'] ?? 'format',
            'status' => $data['status'] ?? 'pending',
            'document_path' => $data['document_path'] ?? null,
            'document_type' => $data['document_type'] ?? null,
            'api_response' => $data['api_response'] ?? null,
        ]);
    }

    private function notifyPendingVerification(Client $client, ClientVerification $verification): void
    {
        try {
            $clientName = trim(($client->first_name ?? '') . ' ' . ($client->last_name ?? '')) ?: $client->email;
            app(NotificationService::class)->notifyAdmins(
                'verification_pending',
                'Doğrulama Onayı Bekliyor: #' . $verification->id,
                "Yeni kimlik doğrulama gönderimi admin onayı bekliyor.\nClient: {$clientName}\nType: {$verification->type}",
                [
                    // SendEmailJob only supports a fixed set of entity types; use 'client' so
                    // email merge fields resolve correctly, while verification_id travels in extra.
                    'entity_type' => 'client',
                    'entity_id' => $client->id,
                    'verification_id' => $verification->id,
                    'url' => route('admin.verifications.show', $verification),
                    'emoji' => '🆔',
                ]
            );
        } catch (\Throwable $e) {
            \Illuminate\Support\Facades\Log::warning('Verification pending notification failed: ' . $e->getMessage());
        }
    }

    public function approveVerification(ClientVerification $verification, int $adminId): void
    {
        $days = (int) (Setting::where('key', 'verification_expiry_days')->value('value') ?? 365);

        $verification->update([
            'status' => 'verified',
            'verified_at' => now(),
            'verified_by' => $adminId,
            'expires_at' => now()->addDays($days),
        ]);

        $verification->client->update(['verification_status' => 'verified']);

        ActivityLog::create([
            'type' => ActivityLog::TYPE_CLIENT,
            'observer' => 'CitizenshipService',
            'module' => 'Verification',
            'method' => 'approve',
            'client_id' => $verification->client_id,
            'admin_id' => $adminId,
            'description' => "Citizenship verification approved (id: {$verification->id})",
            'ip_address' => request()->ip() ?? '0.0.0.0',
            'user_agent' => request()->userAgent(),
        ]);

        \App\Jobs\SendEmailJob::dispatch(
            'Verification Approved',
            'client',
            $verification->client_id,
            ['VERIFICATION_TYPE' => $verification->type]
        );
    }

    public function rejectVerification(ClientVerification $verification, int $adminId, string $reason): void
    {
        $verification->update([
            'status' => 'rejected',
            'verified_by' => $adminId,
            'rejected_reason' => $reason,
        ]);

        $verification->client->update(['verification_status' => 'unverified']);

        ActivityLog::create([
            'type' => ActivityLog::TYPE_CLIENT,
            'observer' => 'CitizenshipService',
            'module' => 'Verification',
            'method' => 'reject',
            'client_id' => $verification->client_id,
            'admin_id' => $adminId,
            'description' => "Citizenship verification rejected: {$reason} (id: {$verification->id})",
            'ip_address' => request()->ip() ?? '0.0.0.0',
            'user_agent' => request()->userAgent(),
        ]);

        \App\Jobs\SendEmailJob::dispatch(
            'Verification Rejected',
            'client',
            $verification->client_id,
            ['REASON' => $reason, 'VERIFICATION_TYPE' => $verification->type]
        );
    }
}
