<?php

namespace App\Http\Controllers;

use App\Models\Registration;
use Illuminate\Http\Request;
use App\Models\Holiday;
use App\Models\Setting;
use Carbon\Carbon;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class RegistrationController extends Controller
{
    private function generateKtpFilename($name, $nik, $date, $extension)
    {
        $filename = $name . '_' . $nik . '_' . $date . '.' . $extension;
        return str_replace(' ', '_', $filename);
    }

    private function generateKtpPath($date)
    {
        // Create base directory structure with year and month
        $year = date('Y', strtotime($date));
        $month = date('m', strtotime($date));
        $path = "ktp_images/{$year}/{$month}";

        // Use Storage facade to check/create directory
        if (!Storage::disk('private')->exists($path)) {
            Storage::disk('private')->makeDirectory($path);
        }

        // Debug log with relative paths
        \Log::info('KTP Path Generated:', [
            'path' => $path,
            'exists' => Storage::disk('private')->exists($path)
        ]);

        return $path;
    }

    private function generateUniqueBookingCode()
    {
        $attempt = 0;
        $maxAttempts = 10;
        
        do {
            // Generate a 6 character alphanumeric string
            $code = strtoupper(Str::random(6));
            
            // Check if this code already exists
            $exists = Registration::where('booking_code', $code)->exists();
            
            $attempt++;
        } while ($exists && $attempt < $maxAttempts);
        
        // If we couldn't generate a unique code after max attempts
        if ($exists) {
            \Log::error('Could not generate unique booking code after ' . $maxAttempts . ' attempts');
            throw new \Exception('Could not generate unique booking code');
        }
        
        return $code;
    }

    private function checkExistingRegistration($nik)
    {
        $twoWeeksAgo = Carbon::now()->subWeeks(2);
        
        $existingRegistration = Registration::where('nik', $nik)
            ->where('created_at', '>=', $twoWeeksAgo)
            ->first();

        if ($existingRegistration) {
            $nextAvailableDate = Carbon::parse($existingRegistration->created_at)
                ->addWeeks(2)
                ->format('d-m-Y');

            throw new \Exception("Anda sudah melakukan registrasi dalam 2 minggu terakhir. Silakan coba lagi setelah tanggal {$nextAvailableDate}.");
        }

        return true;
    }

    public function terms()
    {
        return view('terms');
    }

    public function showForm()
    {
        return view('register');
    }

    public function checkQuota($date, $time)
    {
        // Set timezone explicitly
        date_default_timezone_set('Asia/Jakarta');
        
        // Parse dates using Carbon with explicit timezone
        $currentDate = Carbon::now()->timezone('Asia/Jakarta');
        $selectedDate = Carbon::createFromFormat('Y-m-d', $date, 'Asia/Jakarta');
        
        // Debug logging
        \Log::info('Check Quota Request', [
            'date' => $date,
            'time' => $time,
            'current_time' => $currentDate->format('Y-m-d H:i:s'),
            'selected_parsed' => $selectedDate->format('Y-m-d'),
            'timezone' => config('app.timezone')
        ]);

        // Check if holiday
        if(Holiday::whereDate('date', $selectedDate->format('Y-m-d'))->exists()) {
            return response()->json(['available' => false, 'message' => 'Hari Libur']);
        }

        // Compare dates at start of day
        $todayJkt = $currentDate->copy()->startOfDay();
        $selectedStartOfDay = $selectedDate->copy()->startOfDay();

        if ($selectedStartOfDay->lt($todayJkt)) {
            return response()->json(['available' => false, 'message' => 'Tanggal tidak valid']);
        }

        // Convert time format (e.g., "08:00" to "quota_08_00")
        $quotaKey = 'quota_' . str_replace(':', '_', $time);
        
        // Get quota setting
        $setting = Setting::where('key', $quotaKey)->first();
        $maxQuota = $setting ? $setting->value : 0;
        
        // Count existing registrations
        $count = Registration::whereDate('visit_date', $date)
                            ->where('visit_time', $time)
                            ->count();

        return response()->json([
            'available' => $count < $maxQuota,
            'quota' => $maxQuota,
            'used' => $count,
            'debug' => [
                'date' => $date,
                'time' => $time,
                'today' => $todayJkt->format('Y-m-d'),
                'selected' => $selectedDate->format('Y-m-d')
            ]
        ]);
    }

    public function store(Request $request)
    {
        try {
            // 1. Define custom validation messages
            $customMessages = [
                'name.required' => 'Nama lengkap wajib diisi',
                'gender.required' => 'Jenis kelamin wajib dipilih',
                'gender.in' => 'Jenis kelamin harus L atau P',
                'nik.required' => 'Nomor KTP wajib diisi',
                'nik.digits' => 'Nomor KTP harus terdiri dari 16 digit angka',
                'no_kk.required' => 'Nomor KK wajib diisi',
                'no_kk.digits' => 'Nomor KK harus terdiri dari 16 digit angka',
                'phone.required' => 'Nomor telepon wajib diisi',
                'phone.regex' => 'Format nomor telepon harus diawali dengan 62',
                'email.email' => 'Format email tidak valid',
                'visit_date.required' => 'Tanggal kunjungan wajib diisi',
                'visit_date.date' => 'Format tanggal kunjungan tidak valid',
                'visit_date.after_or_equal' => 'Tanggal kunjungan tidak boleh kurang dari hari ini',
                'visit_time.required' => 'Jam kunjungan wajib diisi',
                'visit_time.in' => 'Jam kunjungan tidak valid',
                'ktp_image.required' => 'Foto KTP wajib diunggah',
                'ktp_image.image' => 'File harus berupa gambar',
                'ktp_image.mimes' => 'Format foto KTP harus jpeg, png, atau jpg',
                'ktp_image.max' => 'Ukuran foto KTP maksimal 2MB',
                'g-recaptcha-response.required' => 'Mohon verifikasi reCAPTCHA'
            ];

            // 2. Validate request
            $request->validate([
                'name' => 'required',
                'gender' => 'required|in:L,P',
                'nik' => 'required|digits:16',
                'no_kk' => 'required|digits:16',
                'phone' => 'required|regex:/^62\d+$/',
                'email' => 'nullable|email',
                'visit_date' => 'required|date|after_or_equal:today',
                'visit_time' => 'required|in:08:00,09:00,10:00,11:00',
                'ktp_image' => 'required|image|mimes:jpeg,png,jpg|max:2048',
                'g-recaptcha-response' => 'required'
            ], $customMessages);

            // 3. Check for existing registration within 2 weeks
            try {
                $this->checkExistingRegistration($request->nik);
            } catch (\Exception $e) {
                return back()
                    ->withErrors(['nik' => $e->getMessage()])
                    ->withInput();
            }

            // 4. Verify reCAPTCHA
            $recaptcha = $request->input('g-recaptcha-response');
            $secretKey = env('RECAPTCHA_SECRET_KEY');
            
            $url = 'https://www.google.com/recaptcha/api/siteverify';
            $data = [
                'secret' => $secretKey,
                'response' => $recaptcha,
                'remoteip' => $request->ip()
            ];
            
            $options = [
                'http' => [
                    'header' => "Content-type: application/x-www-form-urlencoded\r\n",
                    'method' => 'POST',
                    'content' => http_build_query($data)
                ]
            ];
            
            $context = stream_context_create($options);
            $result = file_get_contents($url, false, $context);
            $resultJson = json_decode($result);
            
            if (!$resultJson->success) {
                return back()
                    ->withErrors(['captcha' => 'Verifikasi reCAPTCHA gagal. Silakan coba lagi.'])
                    ->withInput();
            }

            // 5. Check quota availability
            $quotaResponse = $this->checkQuota($request->visit_date, $request->visit_time);
            $quotaData = json_decode($quotaResponse->getContent());
            
            if (!$quotaData->available) {
                return back()
                    ->withErrors(['quota' => 'Kuota untuk waktu yang dipilih sudah penuh. Silakan pilih waktu lain.'])
                    ->withInput();
            }

            // 6. Handle KTP image upload
            $ktpImagePath = null;
            if ($request->hasFile('ktp_image')) {
                try {
                    $ktpImage = $request->file('ktp_image');
                    
                    \Log::info('KTP Upload Start:', [
                        'original_name' => $ktpImage->getClientOriginalName(),
                        'mime_type' => $ktpImage->getMimeType(),
                        'size' => $ktpImage->getSize()
                    ]);

                    // Generate filename
                    $ktpImageName = $this->generateKtpFilename(
                        $request->name,
                        $request->nik,
                        $request->visit_date,
                        $ktpImage->getClientOriginalExtension()
                    );

                    // Get storage path
                    $storagePath = $this->generateKtpPath($request->visit_date);
                    
                    // Store using Storage facade
                    $ktpImagePath = Storage::disk('private')->putFileAs(
                        $storagePath,
                        $ktpImage,
                        $ktpImageName
                    );

                    \Log::info('KTP Upload Success:', [
                        'filename' => $ktpImageName,
                        'path' => $ktpImagePath
                    ]);

                } catch (\Exception $e) {
                    \Log::error('KTP Upload Error:', ['error' => $e->getMessage()]);
                    return back()
                        ->withErrors([
                            'ktp_image' => 'Gagal mengunggah foto KTP. Silakan coba lagi dengan ukuran file yang lebih kecil atau format yang berbeda.'
                        ])
                        ->withInput();
                }
            }

            // 7. Generate unique booking code and save registration
            try {
                $bookingCode = $this->generateUniqueBookingCode();
                
                $booking = Registration::create([
                    'booking_code' => $bookingCode,
                    'name' => $request->name,
                    'gender' => $request->gender,
                    'nik' => $request->nik,
                    'no_kk' => $request->no_kk,
                    'phone' => $request->phone,
                    'email' => $request->email,
                    'visit_date' => $request->visit_date,
                    'visit_time' => $request->visit_time,
                    'ktp_image' => $ktpImagePath,
                    'topic' => $request->topic,
                    'priority' => $request->has('priority'),
                    'pendamping' => $request->pendamping
                ]);

                \Log::info('Registration Created:', [
                    'id' => $booking->id,
                    'booking_code' => $booking->booking_code,
                    'ktp_path' => $booking->ktp_image
                ]);

                return view('booking-confirmation', compact('booking'));

            } catch (\Exception $e) {
                // If something fails, delete uploaded KTP
                if ($ktpImagePath) {
                    Storage::disk('private')->delete($ktpImagePath);
                }
                
                \Log::error('Registration Error:', ['message' => $e->getMessage()]);
                return back()
                    ->withErrors([
                        'system' => 'Mohon maaf, terjadi kesalahan saat memproses pendaftaran Anda. Silakan coba beberapa saat lagi atau hubungi administrator.'
                    ])
                    ->withInput();
            }

        } catch (\Exception $e) {
            \Log::error('Unexpected Error:', ['error' => $e->getMessage()]);
            return back()
                ->withErrors([
                    'system' => 'Mohon maaf, terjadi kesalahan yang tidak terduga. Silakan coba beberapa saat lagi.'
                ])
                ->withInput();
        }
    }
}
