<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Http\Requests\RejectIndividualRegistrationRequest;
use App\Http\Requests\SendInvitationRequest;
use App\Http\Requests\UpdateIndividualRegistrationRequest;
use App\Models\AuditLog;
use App\Models\IndividualRegistration;
use App\Services\AmlScreeningService;
use App\Services\AuditService;
use App\Services\IndividualRegistrationService;
use App\Services\RegistrationFileUploadService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException;

class IndividualRegistrationController extends Controller
{
    public function __construct(
        private readonly IndividualRegistrationService $registrationService,
        private readonly RegistrationFileUploadService $fileUploadService,
        private readonly AuditService $auditService,
        private readonly AmlScreeningService $amlScreeningService,
    ) {}

    /**
     * Get all pending individual registrations.
     */
    public function pending(Request $request): JsonResponse
    {
        try {
            $perPage = min(max((int) $request->input('per_page', 15), 1), 100);
            $submissions = $this->registrationService->getPendingSubmissions($perPage);

            return response()->json([
                'success' => true,
                'data' => collect($submissions->items())->map(fn ($s) => $this->summaryData($s)),
                'pagination' => $this->paginationMeta($submissions),
            ]);
        } catch (\Exception $e) {
            Log::error('Error fetching pending individual registrations: ' . $e->getMessage(), ['exception' => $e]);

            return response()->json([
                'success' => false,
                'message' => 'An error occurred while fetching pending submissions.',
                'error' => config('app.debug') ? $e->getMessage() : 'Internal server error',
            ], 500);
        }
    }

    /**
     * Get all individual registrations with optional filters.
     */
    public function index(Request $request): JsonResponse
    {
        try {
            $perPage = min(max((int) $request->input('per_page', 15), 1), 100);

            $filters = array_filter([
                'status'          => $request->input('status'),
                'submission_type' => $request->input('submission_type'),
                'account_status'  => $request->input('account_status'),
                'from_date'       => $request->input('from_date'),
                'to_date'         => $request->input('to_date'),
            ]);

            $submissions = $this->registrationService->getAllSubmissions($filters, $perPage);

            return response()->json([
                'success' => true,
                'data' => collect($submissions->items())->map(fn ($s) => array_merge(
                    $this->summaryData($s),
                    [
                        'approved_at' => $s->approved_at?->toIso8601String(),
                        'rejected_at' => $s->rejected_at?->toIso8601String(),
                    ]
                )),
                'pagination' => $this->paginationMeta($submissions),
            ]);
        } catch (\Exception $e) {
            Log::error('Error fetching individual registrations: ' . $e->getMessage(), ['exception' => $e]);

            return response()->json([
                'success' => false,
                'message' => 'An error occurred while fetching submissions.',
                'error' => config('app.debug') ? $e->getMessage() : 'Internal server error',
            ], 500);
        }
    }

    /**
     * Get a specific individual registration.
     */
    public function show(IndividualRegistration $registration, Request $request): JsonResponse
    {
        try {
            $registration = $this->registrationService->getSubmission($registration);

            $this->auditService->success(
                AuditLog::ACTION_INDIVIDUAL_REGISTRATION_VIEWED,
                AuditLog::ACTOR_ADMIN,
                $request->user()->id,
                $request->user()->email,
                'IndividualRegistration', $registration->id,
                ['name' => $registration->first_name . ' ' . $registration->last_name],
                $request->ip(),
            );

            return response()->json([
                'success' => true,
                'data' => [
                    'id' => $registration->id,
                    'submission_type' => $registration->submission_type,
                    'status' => $registration->status,
                    'account_status' => $registration->account_status,
                    'verification_status' => $registration->verification_status,
                    'rejection_reason' => $registration->rejection_reason,
                    // BIO-DATA INFORMATION
                    'title' => $registration->title,
                    'first_name' => $registration->first_name,
                    'last_name' => $registration->last_name,
                    'middle_name' => $registration->middle_name,
                    'gender' => $registration->gender,
                    'date_of_birth' => $registration->date_of_birth?->toDateString(),
                    'nationality' => $registration->nationality,
                    'phone_number' => $registration->phone_number,
                    'foreign_number' => $registration->foreign_number,
                    'email_address' => $registration->email_address,
                    'country' => $registration->country,
                    'state' => $registration->state,
                    'city' => $registration->city,
                    'chn' => $registration->chn,
                    'house_address' => $registration->house_address,
                    'previous_address' => $registration->previous_address,
                    // BANK INFORMATION
                    'bank_name' => $registration->bank_name,
                    'bank_account_number' => $registration->bank_account_number,
                    'tin_or_pin' => $registration->tin_or_pin,
                    'bank_details_consent' => $registration->bank_details_consent,
                    // IDENTITY INFORMATION
                    'identity_card_type' => $registration->identity_card_type,
                    'identity_card_number' => $registration->identity_card_number,
                    // Document URLs
                    'documents' => [
                        'identity_card' => $this->fileUploadService->getDocumentUrl($registration->identity_card_path),
                        'scanned_signature' => $this->fileUploadService->getDocumentUrl($registration->scanned_signature_path),
                        'passport_photograph' => $this->fileUploadService->getDocumentUrl($registration->passport_photograph_path),
                        'nin_document' => $this->fileUploadService->getDocumentUrl($registration->nin_document_path),
                    ],
                    // Tracking
                    'consent_given' => $registration->consent_given,
                    'submitted_at' => $registration->created_at?->toIso8601String(),
                    'approved_at' => $registration->approved_at?->toIso8601String(),
                    'rejected_at' => $registration->rejected_at?->toIso8601String(),
                    'approved_by' => $registration->approvedBy ? [
                        'id' => $registration->approvedBy->id,
                        'name' => $registration->approvedBy->name,
                    ] : null,
                    'rejected_by' => $registration->rejectedBy ? [
                        'id' => $registration->rejectedBy->id,
                        'name' => $registration->rejectedBy->name,
                    ] : null,
                ],
            ]);
        } catch (\Exception $e) {
            Log::error('Error fetching individual registration: ' . $e->getMessage(), [
                'registration_id' => $registration->id,
                'exception' => $e,
            ]);

            return response()->json([
                'success' => false,
                'message' => 'An error occurred while fetching the submission.',
                'error' => config('app.debug') ? $e->getMessage() : 'Internal server error',
            ], 500);
        }
    }

    /**
     * Update an individual registration.
     */
    public function update(UpdateIndividualRegistrationRequest $request, IndividualRegistration $registration): JsonResponse
    {
        try {
            if ($registration->isRejected()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Cannot update a rejected submission.',
                ], 422);
            }

            $validated = $request->validated();

            foreach (['identity_card', 'scanned_signature', 'passport_photograph', 'nin_document'] as $field) {
                if ($request->hasFile($field)) {
                    $validated[$field . '_path'] = $this->fileUploadService->uploadDocument(
                        $request->file($field),
                        $field
                    );
                    unset($validated[$field]);
                }
            }

            $updated = $this->registrationService->updateSubmission($registration, $validated);

            $this->auditService->success(
                AuditLog::ACTION_INDIVIDUAL_REGISTRATION_UPDATED,
                AuditLog::ACTOR_ADMIN,
                $request->user()->id,
                $request->user()->email,
                'IndividualRegistration', $updated->id,
                ['name' => $updated->first_name . ' ' . $updated->last_name, 'fields_updated' => array_keys($validated)],
                $request->ip(),
            );

            return response()->json([
                'success' => true,
                'message' => 'Individual registration updated successfully.',
                'data' => [
                    'id' => $updated->id,
                    'first_name' => $updated->first_name,
                    'last_name' => $updated->last_name,
                    'email_address' => $updated->email_address,
                    'phone_number' => $updated->phone_number,
                    'status' => $updated->status,
                ],
            ]);
        } catch (ValidationException $e) {
            throw $e;
        } catch (\Exception $e) {
            Log::error('Error updating individual registration: ' . $e->getMessage(), [
                'registration_id' => $registration->id,
                'exception' => $e,
            ]);

            return response()->json([
                'success' => false,
                'message' => 'An error occurred while updating the submission.',
                'error' => config('app.debug') ? $e->getMessage() : 'Internal server error',
            ], 500);
        }
    }

    /**
     * Approve an individual registration.
     */
    public function approve(IndividualRegistration $registration, Request $request): JsonResponse
    {
        try {
            if ($registration->isApproved() || $registration->isStatusVerified()) {
                return response()->json([
                    'success' => false,
                    'message' => 'This submission has already been approved.',
                ], 422);
            }

            if ($registration->isRejected()) {
                return response()->json([
                    'success' => false,
                    'message' => 'This submission has been rejected and cannot be approved.',
                ], 422);
            }

            $updated = $this->registrationService->approveSubmission($registration, $request->user()->id);

            $this->auditService->success(
                AuditLog::ACTION_INDIVIDUAL_REGISTRATION_APPROVED,
                AuditLog::ACTOR_ADMIN,
                $request->user()->id,
                $request->user()->email,
                'IndividualRegistration', $updated->id,
                ['name' => $updated->first_name . ' ' . $updated->last_name],
                $request->ip(),
            );

            return response()->json([
                'success' => true,
                'message' => 'Individual registration approved successfully.',
                'data' => [
                    'id' => $updated->id,
                    'first_name' => $updated->first_name,
                    'last_name' => $updated->last_name,
                    'email_address' => $updated->email_address,
                    'status' => $updated->status,
                    'account_status' => $updated->account_status,
                    'approved_at' => $updated->approved_at->toIso8601String(),
                ],
            ]);
        } catch (ValidationException $e) {
            throw $e;
        } catch (\Exception $e) {
            Log::error('Error approving individual registration: ' . $e->getMessage(), [
                'registration_id' => $registration->id,
                'exception' => $e,
            ]);

            return response()->json([
                'success' => false,
                'message' => 'An error occurred while approving the submission.',
                'error' => config('app.debug') ? $e->getMessage() : 'Internal server error',
            ], 500);
        }
    }

    /**
     * Verify an individual registration (mark as verified).
     */
    public function verify(IndividualRegistration $registration, Request $request): JsonResponse
    {
        try {
            if ($registration->isStatusVerified()) {
                return response()->json([
                    'success' => false,
                    'message' => 'This registration has already been verified.',
                ], 422);
            }

            if (! $registration->isApproved()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Only approved registrations can be verified.',
                ], 422);
            }

            $updated = $this->registrationService->verifyRegistration($registration, $request->user()->id);

            $this->auditService->success(
                AuditLog::ACTION_INDIVIDUAL_REGISTRATION_VERIFIED,
                AuditLog::ACTOR_ADMIN,
                $request->user()->id,
                $request->user()->email,
                'IndividualRegistration', $updated->id,
                ['name' => $updated->first_name . ' ' . $updated->last_name],
                $request->ip(),
            );

            return response()->json([
                'success' => true,
                'message' => 'Individual registration verified successfully.',
                'data' => [
                    'id' => $updated->id,
                    'first_name' => $updated->first_name,
                    'last_name' => $updated->last_name,
                    'email_address' => $updated->email_address,
                    'status' => $updated->status,
                ],
            ]);
        } catch (ValidationException $e) {
            throw $e;
        } catch (\Exception $e) {
            Log::error('Error verifying individual registration: ' . $e->getMessage(), [
                'registration_id' => $registration->id,
                'exception' => $e,
            ]);

            return response()->json([
                'success' => false,
                'message' => 'An error occurred while verifying the registration.',
                'error' => config('app.debug') ? $e->getMessage() : 'Internal server error',
            ], 500);
        }
    }

    /**
     * Send invitation to individual registration.
     * Approves (if pending), creates PortalUser with role=individual, sends invitation email.
     */
    public function sendInvitation(IndividualRegistration $registration, SendInvitationRequest $request): JsonResponse
    {
        try {
            if ($registration->isRejected()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Cannot send invitation to a rejected registration.',
                ], 422);
            }

            if ($registration->isAccountActive()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Account is already active.',
                ], 422);
            }

            $email = $request->validated()['email'] ?? null;
            $portalUser = $this->registrationService->sendInvitation($registration, $email, $request->user()->id);
            $registration->refresh();

            $this->auditService->success(
                AuditLog::ACTION_INDIVIDUAL_INVITATION_SENT,
                AuditLog::ACTOR_ADMIN,
                $request->user()->id,
                $request->user()->email,
                'IndividualRegistration', $registration->id,
                ['individual_name' => $portalUser->name, 'invited_email' => $portalUser->email],
                $request->ip(),
            );

            return response()->json([
                'success' => true,
                'message' => 'Registration approved and invitation sent successfully.',
                'data' => [
                    'submission_id' => $registration->id,
                    'portal_user_id' => $portalUser->id,
                    'individual_name' => $portalUser->name,
                    'individual_email' => $portalUser->email,
                    'status' => $registration->status,
                    'account_status' => $registration->account_status,
                ],
            ]);
        } catch (ValidationException $e) {
            throw $e;
        } catch (\Exception $e) {
            Log::error('Error sending individual registration invitation: ' . $e->getMessage(), [
                'registration_id' => $registration->id,
                'exception' => $e,
            ]);

            return response()->json([
                'success' => false,
                'message' => 'An error occurred while sending the invitation.',
                'error' => config('app.debug') ? $e->getMessage() : 'Internal server error',
            ], 500);
        }
    }

    /**
     * Reject an individual registration.
     */
    public function reject(IndividualRegistration $registration, RejectIndividualRegistrationRequest $request): JsonResponse
    {
        try {
            if ($registration->isApproved() || $registration->isStatusVerified()) {
                return response()->json([
                    'success' => false,
                    'message' => 'This submission has already been approved and cannot be rejected.',
                ], 422);
            }

            if ($registration->isRejected()) {
                return response()->json([
                    'success' => false,
                    'message' => 'This submission has already been rejected.',
                ], 422);
            }

            $updated = $this->registrationService->rejectSubmission(
                $registration,
                $request->user()->id,
                $request->validated()['rejection_reason']
            );

            $this->auditService->success(
                AuditLog::ACTION_INDIVIDUAL_REGISTRATION_REJECTED,
                AuditLog::ACTOR_ADMIN,
                $request->user()->id,
                $request->user()->email,
                'IndividualRegistration', $updated->id,
                ['name' => $updated->first_name . ' ' . $updated->last_name, 'reason' => $updated->rejection_reason],
                $request->ip(),
            );

            return response()->json([
                'success' => true,
                'message' => 'Individual registration rejected successfully. Rejection email sent.',
                'data' => [
                    'submission_id' => $updated->id,
                    'individual_name' => $updated->first_name . ' ' . $updated->last_name,
                    'rejection_reason' => $updated->rejection_reason,
                    'rejected_at' => $updated->rejected_at->toIso8601String(),
                ],
            ]);
        } catch (ValidationException $e) {
            throw $e;
        } catch (\Exception $e) {
            Log::error('Error rejecting individual registration: ' . $e->getMessage(), [
                'registration_id' => $registration->id,
                'exception' => $e,
            ]);

            return response()->json([
                'success' => false,
                'message' => 'An error occurred while rejecting the submission.',
                'error' => config('app.debug') ? $e->getMessage() : 'Internal server error',
            ], 500);
        }
    }

    /**
     * Export Individual registrations to CSV.
     */
    public function exportCsv(Request $request)
    {
        $filters = array_filter([
            'status'          => $request->input('status'),
            'submission_type' => $request->input('submission_type'),
            'account_status'  => $request->input('account_status'),
            'from_date'       => $request->input('from_date'),
            'to_date'         => $request->input('to_date'),
        ]);

        $submissions = $this->registrationService->getSubmissionsForExport($filters);

        $filename = 'individual-registrations-' . now()->format('Y-m-d') . '.csv';

        $headers = [
            'Content-Type'        => 'text/csv',
            'Content-Disposition' => "attachment; filename=\"{$filename}\"",
        ];

        $columns = ['ID', 'First Name', 'Last Name', 'Email', 'Phone', 'Country', 'State', 'City', 'Submission Type', 'Status', 'Account Status', 'Verification Status', 'Submitted At', 'Approved At', 'Rejected At'];

        return response()->streamDownload(function () use ($submissions, $columns) {
            $handle = fopen('php://output', 'w');
            fputcsv($handle, $columns);

            foreach ($submissions as $row) {
                fputcsv($handle, [
                    $row->id,
                    $row->first_name,
                    $row->last_name,
                    $row->email_address,
                    $row->phone_number,
                    $row->country,
                    $row->state,
                    $row->city,
                    $row->submission_type,
                    $row->status,
                    $row->account_status,
                    $row->verification_status,
                    $row->created_at?->toIso8601String(),
                    $row->approved_at?->toIso8601String(),
                    $row->rejected_at?->toIso8601String(),
                ]);
            }

            fclose($handle);
        }, $filename, $headers);
    }

    private function summaryData(IndividualRegistration $s): array
    {
        return [
            'id' => $s->id,
            'first_name' => $s->first_name,
            'last_name' => $s->last_name,
            'email_address' => $s->email_address,
            'phone_number' => $s->phone_number,
            'country' => $s->country,
            'state' => $s->state,
            'city' => $s->city,
            'submission_type' => $s->submission_type,
            'status' => $s->status,
            'account_status' => $s->account_status,
            'verification_status' => $s->verification_status,
            'submitted_at' => $s->created_at->toIso8601String(),
        ];
    }

    private function paginationMeta($paginator): array
    {
        return [
            'current_page' => $paginator->currentPage(),
            'last_page' => $paginator->lastPage(),
            'per_page' => $paginator->perPage(),
            'total' => $paginator->total(),
            'from' => $paginator->firstItem() ?? 0,
            'to' => $paginator->lastItem() ?? 0,
        ];
    }

    /**
     * Run AML/PEP screening for an individual registration.
     */
    public function amlScreen(IndividualRegistration $registration, Request $request): JsonResponse
    {
        try {
            $screening = $this->amlScreeningService->screenIndividualRegistration(
                $registration,
                $request->user()->id
            );

            return response()->json([
                'success' => true,
                'message' => 'AML screening completed.',
                'data'    => [
                    'id'             => $screening->id,
                    'risk_level'     => $screening->risk_level,
                    'match_status'   => $screening->match_status,
                    'total_results'  => $screening->total_results,
                    'total_articles' => $screening->total_articles,
                    'results'        => $screening->results,
                    'screened_at'    => $screening->screened_at->toIso8601String(),
                ],
            ]);
        } catch (\RuntimeException $e) {
            $serviceDown = $e->serviceUnavailable ?? false;
            return response()->json(array_filter([
                'success'      => false,
                'service_down' => $serviceDown ?: null,
                'message'      => $e->getMessage(),
            ]), $serviceDown ? 503 : 422);
        } catch (\Exception $e) {
            Log::error('Error running AML screening for individual registration: ' . $e->getMessage(), [
                'registration_id' => $registration->id,
                'exception'       => $e,
            ]);
            return response()->json([
                'success' => false,
                'message' => 'An error occurred while running AML screening.',
                'error'   => config('app.debug') ? $e->getMessage() : 'Internal server error',
            ], 500);
        }
    }
}
