<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Masjid;
use App\Models\JadwalSholatKoreksi;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Carbon\Carbon;

class JadwalSholatController extends Controller
{
    /**
     * 1. Get Jadwal Sholat Hari Ini
     */
    public function index(Request $request, $masjid_id): JsonResponse
    {
        $masjid = Masjid::find($masjid_id);
        
        if (!$masjid) {
            return response()->json([
                'type' => 'error',
                'message' => 'Masjid tidak ditemukan',
                'code' => 'MASJID_NOT_FOUND'
            ], 404);
        }

        if (!$masjid->latitude || !$masjid->longitude) {
            return response()->json([
                'type' => 'error',
                'message' => 'Lokasi masjid belum diset',
                'code' => 'LOCATION_NOT_SET'
            ], 400);
        }

        $tanggal = $request->query('tanggal', now()->format('Y-m-d'));
        
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $tanggal)) {
            return response()->json([
                'type' => 'error',
                'message' => 'Format tanggal tidak valid',
                'code' => 'INVALID_DATE_FORMAT'
            ], 400);
        }

        $date = Carbon::parse($tanggal);
        $jadwal = $this->calculatePrayerTimes($masjid, $date);
        $hijriah = $this->getHijriDate($date);

        return response()->json([
            'type' => 'jadwal_sholat',
            'data' => [
                'tanggal' => $date->format('Y-m-d'),
                'hijriah' => $hijriah,
                'lokasi' => [
                    'kota' => $masjid->kota,
                    'latitude' => (float) $masjid->latitude,
                    'longitude' => (float) $masjid->longitude
                ],
                'jadwal' => $jadwal
            ]
        ]);
    }

    /**
     * 2. Get Jadwal Sholat Bulanan
     */
    public function bulanan(Request $request, $masjid_id): JsonResponse
    {
        $masjid = Masjid::find($masjid_id);
        
        if (!$masjid) {
            return response()->json([
                'type' => 'error',
                'message' => 'Masjid tidak ditemukan',
                'code' => 'MASJID_NOT_FOUND'
            ], 404);
        }

        if (!$masjid->latitude || !$masjid->longitude) {
            return response()->json([
                'type' => 'error',
                'message' => 'Lokasi masjid belum diset',
                'code' => 'LOCATION_NOT_SET'
            ], 400);
        }

        $bulan = (int) $request->query('bulan', now()->month);
        $tahun = (int) $request->query('tahun', now()->year);

        if ($bulan < 1 || $bulan > 12) {
            return response()->json([
                'type' => 'error',
                'message' => 'Parameter bulan harus antara 1-12',
                'code' => 'INVALID_MONTH_PARAMETER'
            ], 400);
        }

        $startDate = Carbon::create($tahun, $bulan, 1);
        $endDate = $startDate->copy()->endOfMonth();
        
        $jadwalBulanan = [];
        $currentDate = $startDate->copy();

        while ($currentDate <= $endDate) {
            $jadwal = $this->calculatePrayerTimes($masjid, $currentDate);
            $hijriah = $this->getHijriDate($currentDate);

            $jadwalBulanan[] = array_merge([
                'tanggal' => $currentDate->format('Y-m-d'),
                'hijriah' => $hijriah,
                'hari' => $currentDate->locale('id')->dayName,
            ], $jadwal);

            $currentDate->addDay();
        }

        return response()->json([
            'type' => 'jadwal_sholat_bulanan',
            'data' => [
                'bulan' => $bulan,
                'tahun' => $tahun,
                'nama_bulan' => $startDate->locale('id')->monthName,
                'lokasi' => [
                    'kota' => $masjid->kota,
                    'latitude' => (float) $masjid->latitude,
                    'longitude' => (float) $masjid->longitude
                ],
                'jadwal' => $jadwalBulanan
            ]
        ]);
    }

    /**
     * 3. Get Waktu Sholat Berikutnya
     */
    public function berikutnya($masjid_id): JsonResponse
    {
        $masjid = Masjid::find($masjid_id);
        
        if (!$masjid) {
            return response()->json([
                'type' => 'error',
                'message' => 'Masjid tidak ditemukan',
                'code' => 'MASJID_NOT_FOUND'
            ], 404);
        }

        if (!$masjid->latitude || !$masjid->longitude) {
            return response()->json([
                'type' => 'error',
                'message' => 'Lokasi masjid belum diset',
                'code' => 'LOCATION_NOT_SET'
            ], 400);
        }

        $now = now();
        $jadwal = $this->calculatePrayerTimes($masjid, $now);
        
        $waktuSholat = [
            'Subuh' => $jadwal['subuh'],
            'Dzuhur' => $jadwal['dzuhur'],
            'Ashar' => $jadwal['ashar'],
            'Maghrib' => $jadwal['maghrib'],
            'Isya' => $jadwal['isya'],
        ];

        $sholatBerikutnya = null;
        $waktuSekarang = $now->format('H:i');

        foreach ($waktuSholat as $nama => $waktu) {
            if ($waktu > $waktuSekarang) {
                $sholatBerikutnya = [
                    'nama' => $nama,
                    'waktu' => $waktu
                ];
                break;
            }
        }

        // Jika tidak ada sholat berikutnya hari ini, ambil Subuh besok
        if (!$sholatBerikutnya) {
            $besok = $now->copy()->addDay();
            $jadwalBesok = $this->calculatePrayerTimes($masjid, $besok);
            $sholatBerikutnya = [
                'nama' => 'Subuh',
                'waktu' => $jadwalBesok['subuh']
            ];
        }

        // Hitung countdown
        $waktuSholatNext = Carbon::parse($now->format('Y-m-d') . ' ' . $sholatBerikutnya['waktu']);
        if ($waktuSholatNext < $now) {
            $waktuSholatNext->addDay();
        }
        
        $diff = $now->diff($waktuSholatNext);

        return response()->json([
            'type' => 'sholat_berikutnya',
            'data' => [
                'waktu_sekarang' => $now->toIso8601String(),
                'sholat_berikutnya' => [
                    'nama' => $sholatBerikutnya['nama'],
                    'waktu' => $sholatBerikutnya['waktu'],
                    'countdown' => [
                        'jam' => $diff->h,
                        'menit' => $diff->i,
                        'detik' => $diff->s
                    ]
                ],
                'jadwal_hari_ini' => $jadwal
            ]
        ]);
    }

    /**
     * 4. Update Lokasi Masjid
     */
    public function updateLokasi(Request $request, $masjid_id): JsonResponse
    {
        $masjid = Masjid::find($masjid_id);
        
        if (!$masjid) {
            return response()->json([
                'type' => 'error',
                'message' => 'Masjid tidak ditemukan',
                'code' => 'MASJID_NOT_FOUND'
            ], 404);
        }

        $validated = $request->validate([
            'kota' => 'required|string|max:255',
            'latitude' => 'required|numeric|between:-90,90',
            'longitude' => 'required|numeric|between:-180,180',
            'timezone' => 'nullable|string|max:50',
        ]);

        $masjid->update($validated);

        return response()->json([
            'type' => 'update_lokasi',
            'data' => [
                'message' => 'Lokasi masjid berhasil diperbarui',
                'lokasi' => [
                    'kota' => $masjid->kota,
                    'latitude' => (float) $masjid->latitude,
                    'longitude' => (float) $masjid->longitude,
                    'timezone' => $masjid->timezone
                ]
            ]
        ]);
    }

    /**
     * 5. Get Pengaturan Koreksi Waktu
     */
    public function getKoreksi($masjid_id): JsonResponse
    {
        $masjid = Masjid::find($masjid_id);
        
        if (!$masjid) {
            return response()->json([
                'type' => 'error',
                'message' => 'Masjid tidak ditemukan',
                'code' => 'MASJID_NOT_FOUND'
            ], 404);
        }

        $koreksi = JadwalSholatKoreksi::firstOrCreate(
            ['masjid_id' => $masjid_id],
            [
                'imsak' => 0,
                'subuh' => 0,
                'syuruq' => 0,
                'dzuhur' => 0,
                'ashar' => 0,
                'maghrib' => 0,
                'isya' => 0,
            ]
        );

        return response()->json([
            'type' => 'koreksi_waktu',
            'data' => [
                'imsak' => $koreksi->imsak,
                'subuh' => $koreksi->subuh,
                'syuruq' => $koreksi->syuruq,
                'dzuhur' => $koreksi->dzuhur,
                'ashar' => $koreksi->ashar,
                'maghrib' => $koreksi->maghrib,
                'isya' => $koreksi->isya,
            ],
            'meta' => [
                'satuan' => 'menit',
                'keterangan' => 'Nilai positif = mundur, nilai negatif = maju'
            ]
        ]);
    }

    /**
     * 6. Update Koreksi Waktu
     */
    public function updateKoreksi(Request $request, $masjid_id): JsonResponse
    {
        $masjid = Masjid::find($masjid_id);
        
        if (!$masjid) {
            return response()->json([
                'type' => 'error',
                'message' => 'Masjid tidak ditemukan',
                'code' => 'MASJID_NOT_FOUND'
            ], 404);
        }

        $validated = $request->validate([
            'imsak' => 'nullable|integer|between:-30,30',
            'subuh' => 'nullable|integer|between:-30,30',
            'syuruq' => 'nullable|integer|between:-30,30',
            'dzuhur' => 'nullable|integer|between:-30,30',
            'ashar' => 'nullable|integer|between:-30,30',
            'maghrib' => 'nullable|integer|between:-30,30',
            'isya' => 'nullable|integer|between:-30,30',
        ]);

        $koreksi = JadwalSholatKoreksi::updateOrCreate(
            ['masjid_id' => $masjid_id],
            $validated
        );

        return response()->json([
            'type' => 'update_koreksi',
            'data' => [
                'message' => 'Koreksi waktu berhasil diperbarui',
                'koreksi' => [
                    'imsak' => $koreksi->imsak,
                    'subuh' => $koreksi->subuh,
                    'syuruq' => $koreksi->syuruq,
                    'dzuhur' => $koreksi->dzuhur,
                    'ashar' => $koreksi->ashar,
                    'maghrib' => $koreksi->maghrib,
                    'isya' => $koreksi->isya,
                ]
            ]
        ]);
    }

    /**
     * Helper: Calculate Prayer Times
     * Simplified calculation based on standard formulas
     */
    private function calculatePrayerTimes(Masjid $masjid, Carbon $date): array
    {
        $lat = (float) $masjid->latitude;
        $lng = (float) $masjid->longitude;
        $timezone = 7; // WIB (Asia/Jakarta)

        // Get koreksi
        $koreksi = $masjid->koreksiJadwalSholat;
        $koreksiData = [
            'imsak' => $koreksi->imsak ?? 0,
            'subuh' => $koreksi->subuh ?? 0,
            'syuruq' => $koreksi->syuruq ?? 0,
            'dzuhur' => $koreksi->dzuhur ?? 0,
            'ashar' => $koreksi->ashar ?? 0,
            'maghrib' => $koreksi->maghrib ?? 0,
            'isya' => $koreksi->isya ?? 0,
        ];

        // Simplified calculation (for production, use proper library like adhan)
        $dayOfYear = $date->dayOfYear;
        
        // Base times (simplified - in production use proper astronomical calculations)
        $dzuhur = 12 + ($timezone - ($lng / 15));
        $ashar = $dzuhur + 3.5;
        $maghrib = 18 + ($timezone - ($lng / 15)) + (sin(deg2rad($lat)) * 0.5);
        $isya = $maghrib + 1.5;
        $subuh = $dzuhur - 7.5;
        $imsak = $subuh - 0.17;
        $syuruq = $subuh + 1.25;

        // Apply koreksi
        $times = [
            'imsak' => $this->formatTime($imsak + ($koreksiData['imsak'] / 60)),
            'subuh' => $this->formatTime($subuh + ($koreksiData['subuh'] / 60)),
            'syuruq' => $this->formatTime($syuruq + ($koreksiData['syuruq'] / 60)),
            'dzuhur' => $this->formatTime($dzuhur + ($koreksiData['dzuhur'] / 60)),
            'ashar' => $this->formatTime($ashar + ($koreksiData['ashar'] / 60)),
            'maghrib' => $this->formatTime($maghrib + ($koreksiData['maghrib'] / 60)),
            'isya' => $this->formatTime($isya + ($koreksiData['isya'] / 60)),
        ];

        return $times;
    }

    /**
     * Helper: Format time to HH:mm
     */
    private function formatTime(float $hours): string
    {
        $h = floor($hours);
        $m = round(($hours - $h) * 60);
        
        if ($m >= 60) {
            $h += 1;
            $m -= 60;
        }
        
        if ($h >= 24) {
            $h -= 24;
        }
        
        return sprintf('%02d:%02d', $h, $m);
    }

    /**
     * Helper: Get Hijri Date (simplified)
     */
    private function getHijriDate(Carbon $date): string
    {
        // Simplified Hijri conversion (for production, use proper library)
        // This is approximate calculation
        $gregorianYear = $date->year;
        $gregorianMonth = $date->month;
        $gregorianDay = $date->day;
        
        // Approximate Hijri year (simplified formula)
        $hijriYear = floor(($gregorianYear - 622) * 1.030684);
        $hijriMonth = (($gregorianMonth + 8) % 12) + 1;
        $hijriDay = $gregorianDay;
        
        return sprintf('%04d-%02d-%02d', $hijriYear, $hijriMonth, $hijriDay);
    }
}
