<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Requests\VisitorRegistrationRequest;
use App\Models\Visit;
use App\Models\Visitor;
use App\Services\TokenService;
use App\Services\FileUploadService;
use App\Services\EmailService;
use App\Services\VisitStatusService;
use Illuminate\Http\Request;

class VisitorRegistrationController extends Controller
{
    public function __construct(
        private TokenService $tokenService,
        private FileUploadService $fileUploadService,
        private EmailService $emailService,
        private VisitStatusService $statusService
    ) {}

    /**
     * Validate registration token
     */
    public function validateToken(Request $request, int $id)
    {
        $token = $request->query('token');

        if (!$token) {
            return response()->json([
                'valid' => false,
                'error' => 'missing_token',
                'message' => 'Token is required',
            ], 400);
        }

        $visit = Visit::find($id);

        if (!$visit) {
            return response()->json([
                'valid' => false,
                'error' => 'invalid_visit',
                'message' => 'Visit not found',
            ], 404);
        }

        // Validate token
        $expectedToken = hash('sha256', $visit->id . $visit->created_at . config('app.key'));

        if ($token !== $expectedToken) {
            return response()->json([
                'valid' => false,
                'error' => 'invalid_token',
                'message' => 'Invalid token',
            ], 401);
        }

        return response()->json([
            'valid' => true,
            'message' => 'Token is valid',
        ]);
    }

    /**
     * Get visit details for registration
     */
    public function getVisitDetails(Request $request, int $id)
    {
        $token = $request->query('token');

        if (!$token) {
            return response()->json([
                'message' => 'Token is required',
            ], 401);
        }

        $visit = Visit::findOrFail($id);

        // Validate token
        $expectedToken = hash('sha256', $visit->id . $visit->created_at . config('app.key'));

        if ($token !== $expectedToken) {
            return response()->json([
                'message' => 'Invalid token',
            ], 401);
        }

        $visit->load(['location', 'mainVisitor', 'additionalVisitors']);

        // Convert times from 24-hour to 12-hour AM/PM format
        $startTime = $this->formatTimeTo12Hour($visit->start_time);
        $endTime = $this->formatTimeTo12Hour($visit->end_time);

        // Build response
        $response = [
            'visitId' => $visit->id,
            'requestId' => $visit->request_id,
            'hostVisitor' => [
                'name' => $visit->host_name,
                'email' => $visit->host_email,
                'phone' => $visit->host_phone,
                'location' => $visit->location->name,
            ],
            'visitReason' => $visit->visit_reason,
            'mainVisitorEmail' => $visit->main_visitor_email,
            'meetingType' => $visit->meeting_type,
            'startTime' => $startTime,
            'endTime' => $endTime,
            'tokenExpiresAt' => $visit->token_expires_at,
            'status' => $visit->status,
        ];

        // Add date fields based on meeting type
        if ($visit->meeting_type === 'single' && $visit->date) {
            $response['date'] = $visit->date->format('Y-m-d');
        } else {
            $response['dateFrom'] = $visit->date_from?->format('Y-m-d');
            $response['dateTo'] = $visit->date_to?->format('Y-m-d');
        }

        // Add main visitor data if exists
        if ($visit->mainVisitor) {
            $response['mainVisitor'] = [
                'id' => (string)$visit->mainVisitor->id,
                'name' => $visit->mainVisitor->name,
                'email' => $visit->mainVisitor->email,
                'phone' => $visit->mainVisitor->phone,
                'companyName' => $visit->mainVisitor->company_name,
                'idFrontImage' => $visit->mainVisitor->id_front_image_url,
                'idBackImage' => $visit->mainVisitor->id_back_image_url,
            ];
        } else {
            // If no main visitor data exists yet, use the main visitor email from visit
            $response['mainVisitor'] = [
                'id' => null,
                'name' => null,
                'email' => $visit->main_visitor_email,
                'phone' => null,
                'companyName' => null,
                'idFrontImage' => null,
                'idBackImage' => null,
            ];
        }

        // Add additional visitors if they exist
        $response['additionalVisitors'] = $visit->additionalVisitors->map(function ($visitor) {
            return [
                'id' => (string)$visitor->id,
                'name' => $visitor->name,
                'email' => $visitor->email,
                'phone' => $visitor->phone,
                'companyName' => $visitor->company_name,
                'idFrontImage' => $visitor->id_front_image_url,
                'idBackImage' => $visitor->id_back_image_url,
            ];
        })->toArray();

        return response()->json($response);
    }

    /**
     * Convert 24-hour time to 12-hour AM/PM format
     */
    private function formatTimeTo12Hour(string $time): string
    {
        // Parse time (HH:MM:SS format)
        $parts = explode(':', $time);
        $hour = (int)$parts[0];
        $minute = $parts[1];

        // Convert to 12-hour format
        $amPm = $hour >= 12 ? 'PM' : 'AM';
        $hour12 = $hour % 12;
        if ($hour12 === 0) {
            $hour12 = 12;
        }

        return sprintf('%d:%s %s', $hour12, $minute, $amPm);
    }

    /**
     * Save draft registration (partial data)
     */
    public function saveDraft(Request $request, int $id)
    {
        $token = $request->query('token');

        if (!$token) {
            return response()->json([
                'message' => 'Token is required',
            ], 401);
        }

        $visit = Visit::findOrFail($id);

        // Validate token
        $expectedToken = hash('sha256', $visit->id . $visit->created_at . config('app.key'));

        if ($token !== $expectedToken) {
            return response()->json([
                'message' => 'Invalid token',
            ], 401);
        }

        // Basic validation for draft - less strict than full submission
        $request->validate([
            'mainVisitor.name' => 'required|string|max:255',
            'mainVisitor.email' => 'required|email|max:255',
            'mainVisitor.phone' => 'required|string|max:20',
            'mainVisitor.companyName' => 'required|string|max:255',
        ]);

        try {
            \DB::beginTransaction();

            // Debug: Log all files received (PHP converts dots to underscores)
            \Log::info('Save Draft - Files received:', [
                'all_files' => $request->allFiles(),
                'has_front' => $request->hasFile('mainVisitor_idFrontImage'),
                'has_back' => $request->hasFile('mainVisitor_idBackImage'),
            ]);

            // Save main visitor data
            $mainVisitorData = [
                'visit_id' => $visit->id,
                'name' => $request->input('mainVisitor.name'),
                'email' => $request->input('mainVisitor.email'),
                'phone' => $request->input('mainVisitor.phone'),
                'company_name' => $request->input('mainVisitor.companyName'),
                'is_main_visitor' => true,
            ];

            // Upload images if provided
            // Note: PHP converts dots to underscores in field names
            if ($request->hasFile('mainVisitor_idFrontImage')) {
                $mainVisitorData['id_front_image'] = $this->fileUploadService->uploadVisitorIdImage(
                    $request->file('mainVisitor_idFrontImage'),
                    'front'
                );
            }

            if ($request->hasFile('mainVisitor_idBackImage')) {
                $mainVisitorData['id_back_image'] = $this->fileUploadService->uploadVisitorIdImage(
                    $request->file('mainVisitor_idBackImage'),
                    'back'
                );
            }

            // Create or update main visitor
            Visitor::updateOrCreate(
                ['visit_id' => $visit->id, 'is_main_visitor' => true],
                $mainVisitorData
            );

            // Handle additional visitors
            // First, get existing additional visitors to preserve their images
            $existingAdditionalVisitors = Visitor::where('visit_id', $visit->id)
                ->where('is_main_visitor', false)
                ->get();

            // Create a map of existing visitors by index (position in the list)
            $existingVisitorsMap = [];
            foreach ($existingAdditionalVisitors as $index => $visitor) {
                $existingVisitorsMap[$index] = $visitor;
            }

            // Delete existing additional visitors (we'll recreate them with updated data)
            Visitor::where('visit_id', $visit->id)
                ->where('is_main_visitor', false)
                ->delete();

            $additionalVisitorsCount = 0;
            if ($request->has('additionalVisitors')) {
                foreach ($request->input('additionalVisitors') as $index => $additionalVisitor) {
                    // Skip empty additional visitors
                    if (empty($additionalVisitor['name']) && empty($additionalVisitor['email'])) {
                        continue;
                    }

                    $visitorData = [
                        'visit_id' => $visit->id,
                        'name' => $additionalVisitor['name'],
                        'email' => $additionalVisitor['email'],
                        'phone' => $additionalVisitor['phone'],
                        'company_name' => $additionalVisitor['companyName'] ?? null,
                        'is_main_visitor' => false,
                    ];

                    // Check if new images are uploaded
                    // Note: PHP converts dots to underscores in field names
                    if ($request->hasFile("additionalVisitors_{$index}_idFrontImage")) {
                        $visitorData['id_front_image'] = $this->fileUploadService->uploadVisitorIdImage(
                            $request->file("additionalVisitors_{$index}_idFrontImage"),
                            'front'
                        );
                    } elseif (isset($existingVisitorsMap[$index]) && $existingVisitorsMap[$index]->id_front_image) {
                        // No new image uploaded, preserve existing image
                        $visitorData['id_front_image'] = $existingVisitorsMap[$index]->id_front_image;
                    }

                    if ($request->hasFile("additionalVisitors_{$index}_idBackImage")) {
                        $visitorData['id_back_image'] = $this->fileUploadService->uploadVisitorIdImage(
                            $request->file("additionalVisitors_{$index}_idBackImage"),
                            'back'
                        );
                    } elseif (isset($existingVisitorsMap[$index]) && $existingVisitorsMap[$index]->id_back_image) {
                        // No new image uploaded, preserve existing image
                        $visitorData['id_back_image'] = $existingVisitorsMap[$index]->id_back_image;
                    }

                    Visitor::create($visitorData);
                    $additionalVisitorsCount++;
                }
            }

            // Update visit record with visitor count
            $visit->update([
                'visitor_registered_at' => now(),
                'number_of_visitors' => 1 + $additionalVisitorsCount,
            ]);

            // NOTE: Status remains "Pending Visitor" - do NOT transition

            \DB::commit();

            return response()->json([
                'message' => 'Draft saved successfully. You can continue editing or submit when ready.',
                'visitId' => $visit->id,
                'status' => $visit->status, // Still "Pending Visitor"
            ]);
        } catch (\Exception $e) {
            \DB::rollBack();

            return response()->json([
                'message' => 'Failed to save draft: ' . $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Submit complete visitor registration
     */
    public function submit(VisitorRegistrationRequest $request, int $id)
    {
        $token = $request->query('token');

        if (!$token) {
            return response()->json([
                'message' => 'Token is required',
            ], 401);
        }

        $visit = Visit::findOrFail($id);

        // Validate token
        $expectedToken = hash('sha256', $visit->id . $visit->created_at . config('app.key'));

        if ($token !== $expectedToken) {
            return response()->json([
                'message' => 'Invalid token',
            ], 401);
        }

        try {
            \DB::beginTransaction();

            // Debug: Log all files received (PHP converts dots to underscores)
            \Log::info('Submit Registration - Files received:', [
                'all_files' => $request->allFiles(),
                'has_front' => $request->hasFile('mainVisitor_idFrontImage'),
                'has_back' => $request->hasFile('mainVisitor_idBackImage'),
            ]);

            // Check if main visitor exists with images
            $existingMainVisitor = Visitor::where('visit_id', $visit->id)
                ->where('is_main_visitor', true)
                ->first();

            // Validate that images are provided if they don't already exist
            $hasExistingFrontImage = $existingMainVisitor && $existingMainVisitor->id_front_image;
            $hasExistingBackImage = $existingMainVisitor && $existingMainVisitor->id_back_image;
            $hasNewFrontImage = $request->hasFile('mainVisitor_idFrontImage');
            $hasNewBackImage = $request->hasFile('mainVisitor_idBackImage');

            if (!$hasExistingFrontImage && !$hasNewFrontImage) {
                return response()->json([
                    'message' => 'Validation failed',
                    'errors' => [
                        'mainVisitor.idFrontImage' => ['Front ID image is required']
                    ]
                ], 422);
            }

            if (!$hasExistingBackImage && !$hasNewBackImage) {
                return response()->json([
                    'message' => 'Validation failed',
                    'errors' => [
                        'mainVisitor.idBackImage' => ['Back ID image is required']
                    ]
                ], 422);
            }

            // Upload main visitor images
            $mainVisitorData = [
                'visit_id' => $visit->id,
                'name' => $request->input('mainVisitor.name'),
                'email' => $request->input('mainVisitor.email'),
                'phone' => $request->input('mainVisitor.phone'),
                'company_name' => $request->input('mainVisitor.companyName'),
                'is_main_visitor' => true,
            ];

            // Note: PHP converts dots to underscores in field names
            if ($request->hasFile('mainVisitor_idFrontImage')) {
                $mainVisitorData['id_front_image'] = $this->fileUploadService->uploadVisitorIdImage(
                    $request->file('mainVisitor_idFrontImage'),
                    'front'
                );
            }

            if ($request->hasFile('mainVisitor_idBackImage')) {
                $mainVisitorData['id_back_image'] = $this->fileUploadService->uploadVisitorIdImage(
                    $request->file('mainVisitor_idBackImage'),
                    'back'
                );
            }

            // Create or update main visitor (in case draft was saved before)
            Visitor::updateOrCreate(
                ['visit_id' => $visit->id, 'is_main_visitor' => true],
                $mainVisitorData
            );

            // Handle additional visitors
            // First, get existing additional visitors to preserve their images
            $existingAdditionalVisitors = Visitor::where('visit_id', $visit->id)
                ->where('is_main_visitor', false)
                ->get();

            // Create a map of existing visitors by index (position in the list)
            $existingVisitorsMap = [];
            foreach ($existingAdditionalVisitors as $index => $visitor) {
                $existingVisitorsMap[$index] = $visitor;
            }

            // Delete existing additional visitors (we'll recreate them with updated data)
            Visitor::where('visit_id', $visit->id)
                ->where('is_main_visitor', false)
                ->delete();

            $additionalVisitorsCount = 0;
            if ($request->has('additionalVisitors')) {
                foreach ($request->input('additionalVisitors') as $index => $additionalVisitor) {
                    // Skip empty additional visitors
                    if (empty($additionalVisitor['name']) && empty($additionalVisitor['email'])) {
                        continue;
                    }

                    $visitorData = [
                        'visit_id' => $visit->id,
                        'name' => $additionalVisitor['name'],
                        'email' => $additionalVisitor['email'],
                        'phone' => $additionalVisitor['phone'],
                        'company_name' => $additionalVisitor['companyName'] ?? null,
                        'is_main_visitor' => false,
                    ];

                    // Check if new images are uploaded
                    // Note: PHP converts dots to underscores in field names
                    if ($request->hasFile("additionalVisitors_{$index}_idFrontImage")) {
                        $visitorData['id_front_image'] = $this->fileUploadService->uploadVisitorIdImage(
                            $request->file("additionalVisitors_{$index}_idFrontImage"),
                            'front'
                        );
                    } elseif (isset($existingVisitorsMap[$index]) && $existingVisitorsMap[$index]->id_front_image) {
                        // No new image uploaded, preserve existing image
                        $visitorData['id_front_image'] = $existingVisitorsMap[$index]->id_front_image;
                    }

                    if ($request->hasFile("additionalVisitors_{$index}_idBackImage")) {
                        $visitorData['id_back_image'] = $this->fileUploadService->uploadVisitorIdImage(
                            $request->file("additionalVisitors_{$index}_idBackImage"),
                            'back'
                        );
                    } elseif (isset($existingVisitorsMap[$index]) && $existingVisitorsMap[$index]->id_back_image) {
                        // No new image uploaded, preserve existing image
                        $visitorData['id_back_image'] = $existingVisitorsMap[$index]->id_back_image;
                    }

                    Visitor::create($visitorData);
                    $additionalVisitorsCount++;
                }
            }

            // Update visit
            $visit->update([
                'visitor_registered_at' => now(),
                'number_of_visitors' => 1 + $additionalVisitorsCount,
            ]);

            // Transition status to Pending Approve
            $this->statusService->transition($visit, 'Pending Approve');

            // Send notification emails
            $this->emailService->sendAfterSubmissionEmails($visit->fresh(['mainVisitor', 'location']));

            \DB::commit();

            return response()->json([
                'message' => 'Registration submitted successfully. Pending security approval.',
                'visitId' => $visit->id,
                'status' => 'Pending Approve',
            ]);
        } catch (\Exception $e) {
            \DB::rollBack();

            return response()->json([
                'message' => 'Registration failed: ' . $e->getMessage(),
            ], 500);
        }
    }
}
