<?php

namespace App\Http\Controllers;

use App\Models\ApiClient;
use App\Models\IntegrationLog;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;

class IntegrationController extends Controller
{
    public function index()
    {
        $totalClients = class_exists(ApiClient::class) ? ApiClient::count() : 0;
        $activeClients = class_exists(ApiClient::class) ? ApiClient::where('is_active', 1)->count() : 0;
        $logSummary = class_exists(IntegrationLog::class) ? [
            'success' => IntegrationLog::where('status', 'success')->count(),
            'failed' => IntegrationLog::where('status', 'failed')->count(),
            'pending' => IntegrationLog::where('status', 'pending')->count(),
        ] : ['success' => 0, 'failed' => 0, 'pending' => 0];

        return view('integrations.index', compact('totalClients', 'activeClients', 'logSummary'));
    }

    public function apiUrls()
    {
        $baseUrl = url('/');
        $endpoints = [
            ['method' => 'GET', 'url' => $baseUrl.'/api/v2/health', 'description' => 'API health check'],
            ['method' => 'GET', 'url' => $baseUrl.'/api/v2/reference-data', 'description' => 'Reference data for integrations'],
            ['method' => 'GET', 'url' => $baseUrl.'/api/v2/incidents/statistics', 'description' => 'Quality-corrected incident statistics'],
            ['method' => 'POST', 'url' => $baseUrl.'/api/v2/incidents/push/ubos', 'description' => 'Push NGBVD case payload to the configured UBOS GBV Portal client URL'],
        ];

        return view('integrations.api_urls', compact('endpoints'));
    }

    public function apiClients()
    {
        $clients = class_exists(ApiClient::class) ? ApiClient::orderBy('name')->get() : collect();

        $districts = Schema::hasTable('districts')
            ? DB::table('districts')->select('id', 'name')->orderBy('name')->get()
            : collect();

        $partners = Schema::hasTable('partners')
            ? DB::table('partners')->select('id', 'name')->orderBy('name')->get()
            : collect();

        return view('integrations.api_clients', compact('clients', 'districts', 'partners'));
    }

    public function storeApiClient(Request $request)
    {
        $data = $this->normalizeApiClientData($this->validateApiClient($request));

        $plainSecret = Str::random(48);

        $client = ApiClient::create([
            'name' => $data['name'],
            'system_name' => $data['system_name'],
            'integration_code' => $data['integration_code'] ?: ApiClient::guessIntegrationCode($data['system_name'], $data['allowed_scopes'] ?? ''),
            'client_key' => 'ngbvd_'.Str::random(40),
            'client_secret_hash' => Hash::make($plainSecret),
            'client_secret_encrypted' => Crypt::encryptString($plainSecret),
            'signing_secret_encrypted' => Crypt::encryptString($plainSecret),
            'encryption_key_encrypted' => Crypt::encryptString(base64_encode(random_bytes(32))),
            'allowed_scopes' => $data['allowed_scopes'] ?? null,
            'allowed_ips' => $data['allowed_ips'] ?? null,
            'allowed_district_ids' => $data['allowed_district_ids'] ?? null,
            'partner_id' => $data['partner_id'] ?? null,
            'is_active' => $request->boolean('is_active', true),
            'outbound_enabled' => $request->boolean('outbound_enabled'),
            'outbound_base_url' => $data['outbound_base_url'] ?? null,
            'outbound_push_endpoint' => $data['outbound_push_endpoint'] ?? null,
            'outbound_timeout' => $data['outbound_timeout'] ?? 30,
            'outbound_verify_ssl' => $request->boolean('outbound_verify_ssl', true),
            'outbound_api_version' => $data['outbound_api_version'] ?? 'v2',
            'outbound_notes' => $data['outbound_notes'] ?? null,
            'require_signed_requests' => $request->boolean('require_signed_requests'),
            'require_payload_encryption' => $request->boolean('require_payload_encryption'),
            'require_https' => $request->boolean('require_https', true),
            'rate_limit_per_minute' => $data['rate_limit_per_minute'] ?? 60,
            'signature_window_seconds' => $data['signature_window_seconds'] ?? 300,
            'created_by' => auth()->id(),
        ]);

        return back()
            ->with('message', 'API client created. Copy the secret now; it will not be shown again.')
            ->with('new_api_client_key', $client->client_key)
            ->with('new_api_client_secret', $plainSecret);
    }

    public function updateApiClient(Request $request, $uuid)
    {
        $client = ApiClient::where('uuid', $uuid)->firstOrFail();
        $data = $this->normalizeApiClientData($this->validateApiClient($request, true));

        $client->fill([
            'name' => $data['name'],
            'system_name' => $data['system_name'],
            'integration_code' => $data['integration_code'] ?: ApiClient::guessIntegrationCode($data['system_name'], $data['allowed_scopes'] ?? ''),
            'allowed_scopes' => $data['allowed_scopes'] ?? null,
            'allowed_ips' => $data['allowed_ips'] ?? null,
            'allowed_district_ids' => $data['allowed_district_ids'] ?? null,
            'partner_id' => $data['partner_id'] ?? null,
            'is_active' => $request->boolean('is_active'),
            'outbound_enabled' => $request->boolean('outbound_enabled'),
            'outbound_base_url' => $data['outbound_base_url'] ?? null,
            'outbound_push_endpoint' => $data['outbound_push_endpoint'] ?? null,
            'outbound_timeout' => $data['outbound_timeout'] ?? 30,
            'outbound_verify_ssl' => $request->boolean('outbound_verify_ssl'),
            'outbound_api_version' => $data['outbound_api_version'] ?? 'v2',
            'outbound_notes' => $data['outbound_notes'] ?? null,
            'require_signed_requests' => $request->boolean('require_signed_requests'),
            'require_payload_encryption' => $request->boolean('require_payload_encryption'),
            'require_https' => $request->boolean('require_https', true),
            'rate_limit_per_minute' => $data['rate_limit_per_minute'] ?? 60,
            'signature_window_seconds' => $data['signature_window_seconds'] ?? 300,
            'updated_by' => auth()->id(),
        ])->save();

        return back()->with('message', 'API client configuration updated. Client Key and Client Secret were not changed.');
    }

    private function validateApiClient(Request $request, bool $updating = false): array
    {
        return $request->validate([
            'name' => 'required|string|max:150',
            'system_name' => 'required|string|max:150',
            'integration_code' => 'nullable|string|max:60',
            'allowed_scopes' => 'nullable|string|max:1000',
            'allowed_ips' => 'nullable|string|max:1000',
            'allowed_district_ids' => 'nullable',
            'allowed_district_ids.*' => 'nullable|integer',
            'partner_id' => 'nullable|integer',
            'is_active' => 'nullable|boolean',
            'outbound_enabled' => 'nullable|boolean',
            'outbound_base_url' => 'nullable|url|max:500',
            'outbound_push_endpoint' => 'nullable|string|max:255',
            'outbound_timeout' => 'nullable|integer|min:5|max:300',
            'outbound_verify_ssl' => 'nullable|boolean',
            'outbound_api_version' => 'nullable|string|max:20',
            'outbound_notes' => 'nullable|string|max:1000',
            'require_signed_requests' => 'nullable|boolean',
            'require_payload_encryption' => 'nullable|boolean',
            'require_https' => 'nullable|boolean',
            'rate_limit_per_minute' => 'nullable|integer|min:1|max:10000',
            'signature_window_seconds' => 'nullable|integer|min:60|max:3600',
        ]);
    }


    private function normalizeApiClientData(array $data): array
    {
        if (array_key_exists('allowed_district_ids', $data)) {
            $districts = $data['allowed_district_ids'];

            if (is_array($districts)) {
                $districts = array_values(array_unique(array_filter(array_map(function ($value) {
                    return trim((string) $value);
                }, $districts), function ($value) {
                    return $value !== '';
                })));

                $data['allowed_district_ids'] = empty($districts) ? null : implode(',', $districts);
            } elseif (is_string($districts)) {
                $districts = array_values(array_unique(array_filter(array_map(function ($value) {
                    return trim((string) $value);
                }, preg_split('/[,\s]+/', $districts)), function ($value) {
                    return $value !== '';
                })));

                $data['allowed_district_ids'] = empty($districts) ? null : implode(',', $districts);
            }
        }

        if (empty($data['partner_id'])) {
            $data['partner_id'] = null;
        }

        return $data;
    }

    public function logs(Request $request)
    {
        $query = IntegrationLog::query()
            ->with('apiClient')
            ->orderByDesc('created_at');

        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }

        if ($request->filled('direction')) {
            $query->where('direction', $request->direction);
        }

        if ($request->filled('http_method')) {
            $query->where('http_method', $request->http_method);
        }

        if ($request->filled('integration_name')) {
            $query->where(function ($q) use ($request) {
                $q->where('integration_name', 'like', '%'.$request->integration_name.'%')
                  ->orWhere('system_name', 'like', '%'.$request->integration_name.'%');
            });
        }

        if ($request->filled('client')) {
            $query->whereHas('apiClient', function ($q) use ($request) {
                $q->where('name', 'like', '%'.$request->client.'%')
                  ->orWhere('client_key', 'like', '%'.$request->client.'%')
                  ->orWhere('system_name', 'like', '%'.$request->client.'%');
            });
        }

        if ($request->filled('ip_address')) {
            $query->where('ip_address', 'like', '%'.$request->ip_address.'%');
        }

        if ($request->filled('endpoint')) {
            $query->where('endpoint', 'like', '%'.$request->endpoint.'%');
        }

        if ($request->filled('case_reference')) {
            $query->where('case_reference', 'like', '%'.$request->case_reference.'%');
        }

        if ($request->filled('date_from')) {
            $query->whereDate('created_at', '>=', $request->date_from);
        }

        if ($request->filled('date_to')) {
            $query->whereDate('created_at', '<=', $request->date_to);
        }

        $logs = $query->paginate(25);
        $clients = ApiClient::orderBy('name')->get();

        return view('integrations.logs', compact('logs', 'clients'));
    }

    public function logDetail($uuid)
    {
        $log = IntegrationLog::with('apiClient')->where('uuid', $uuid)->firstOrFail();

        return view('integrations.log_detail', compact('log'));
    }
}
