<?php

namespace App\Services\Integrations;

use App\Models\ApiClient;
use App\Models\IntegrationLog;
use App\Models\Victim;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Http;

class UbosGbvPortalService
{
    private $logs;

    public function __construct(IntegrationLogService $logs)
    {
        $this->logs = $logs;
    }

    public function buildPayload(Victim $victim): array
    {
        $victim->load(['incidents', 'perpetrators', 'witnesses', 'actions', 'statuses']);

        $client = $this->resolveOutboundClient();
        $apiVersion = $client && $client->outbound_api_version ? $client->outbound_api_version : config('ngbvd_integrations.ubos.api_version', 'v2');

        return [
            'api_version' => $apiVersion,
            'source_system' => 'NGBVD',
            'case' => [
                'uuid' => $victim->uuid ?? null,
                'reference_id' => (string) $victim->id,
                'crb_number' => $victim->crb_number,
                'survivor_code' => $victim->survivor_code,
                'interview_date' => $victim->interview_date,
                'district_id' => $victim->districtid,
                'subcounty_id' => $victim->subcountyid,
                'parish_id' => $victim->parishid,
                'gender_id' => $victim->gender,
                'age_or_dob' => $victim->dob,
                'nationality_status_id' => $victim->nationality_status,
                'religion_id' => $victim->religion,
                'created_at' => optional($victim->created_at)->toDateTimeString(),
            ],
            'incidents' => $victim->incidents->map(function ($incident) {
                return [
                    'uuid' => $incident->uuid ?? null,
                    'incident_type_id' => $incident->incidentid,
                    'incident_date' => $incident->incident_date,
                    'district_id' => $incident->districtid,
                    'subcounty_id' => $incident->subcountyid,
                    'parish_id' => $incident->parishid,
                    'reported_by' => $incident->reported_by,
                ];
            })->values()->all(),
            'perpetrators' => $victim->perpetrators->values()->all(),
            'witnesses' => $victim->witnesses->values()->all(),
            'actions' => $victim->actions->values()->all(),
            'statuses' => $victim->statuses->values()->all(),
            'metadata' => [
                'data_as_of' => now()->toIso8601String(),
                'privacy_note' => 'Payload should be handled under approved MGLSD/UBOS data-sharing protocol.',
            ],
        ];
    }

    public function pushVictim(Victim $victim): IntegrationLog
    {
        $client = $this->resolveOutboundClient();
        $payload = $this->buildPayload($victim);

        $endpoint = $client
            ? $client->outboundEndpointUrl('/api/v2/incidents')
            : $this->legacyEndpoint();

        $log = $this->logs->start([
            'api_client_id' => $client ? $client->id : null,
            'integration_name' => 'UBOS_GBV_PORTAL',
            'system_name' => $client && $client->system_name ? $client->system_name : 'UBOS GBV Portal',
            'direction' => 'outbound',
            'endpoint' => $endpoint ?: '/api/v2/incidents',
            'http_method' => 'POST',
            'record_type' => 'victim',
            'record_id' => $victim->id,
            'record_uuid' => $victim->uuid ?? null,
            'case_reference' => $victim->crb_number ?: $victim->survivor_code,
            'request_payload_hash' => $this->logs->hashPayload($payload),
            'request_payload_preview' => $payload,
            'triggered_by' => Auth::id(),
        ]);

        if (!$client && (!config('ngbvd_integrations.ubos.enabled') || empty(config('ngbvd_integrations.ubos.base_url')))) {
            return $this->logs->failure($log, 'UBOS outbound client is not configured. Create or update an active API Client with integration code UBOS_GBV_PORTAL, outbound enabled, and a base URL.');
        }

        if ($client && !$client->hasOutboundConfiguration()) {
            return $this->logs->failure($log, 'UBOS outbound client exists but outbound sharing is disabled or base URL is missing.');
        }

        if (empty($endpoint)) {
            return $this->logs->failure($log, 'UBOS outbound endpoint could not be resolved.');
        }

        try {
            $timeout = $client && $client->outbound_timeout ? (int) $client->outbound_timeout : (int) config('ngbvd_integrations.ubos.timeout', 30);
            $verifySsl = $client ? (bool) $client->outbound_verify_ssl : (bool) config('ngbvd_integrations.ubos.verify_ssl', true);

            $response = Http::timeout($timeout)
                ->withOptions(['verify' => $verifySsl])
                ->acceptJson()
                ->post($endpoint, $payload);

            if ($response->successful()) {
                return $this->logs->success($log, $response->status(), $response->body());
            }

            return $this->logs->failure($log, 'UBOS portal returned a non-success response.', $response->status(), $response->body());
        } catch (\Throwable $e) {
            return $this->logs->failure($log, $e->getMessage());
        }
    }

    private function resolveOutboundClient(): ?ApiClient
    {
        $current = request()->attributes->get('api_client');

        if ($current instanceof ApiClient && $current->canUseScope('ubos.push') && $current->hasOutboundConfiguration()) {
            return $current;
        }

        return ApiClient::query()
            ->where('is_active', 1)
            ->where('outbound_enabled', 1)
            ->whereNotNull('outbound_base_url')
            ->where(function ($query) {
                $query->where('integration_code', 'UBOS_GBV_PORTAL')
                    ->orWhere('system_name', 'like', '%UBOS%')
                    ->orWhere('allowed_scopes', 'like', '%ubos.push%');
            })
            ->orderByRaw("CASE WHEN integration_code = 'UBOS_GBV_PORTAL' THEN 0 ELSE 1 END")
            ->orderByDesc('last_used_at')
            ->orderBy('id')
            ->first();
    }

    private function legacyEndpoint(): ?string
    {
        $baseUrl = config('ngbvd_integrations.ubos.base_url');

        if (!$baseUrl) {
            return null;
        }

        return rtrim((string) $baseUrl, '/') . '/' . ltrim((string) config('ngbvd_integrations.ubos.push_endpoint', '/api/v2/incidents'), '/');
    }
}
