<?php

namespace App\Http\Controllers;

use App\Models\Pasien;
use App\Models\PemeriksaanKesehatan;
use App\Models\AnalisisAi;
use App\Models\Dokter;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

class LaporanController extends Controller
{
    /**
     * Halaman utama laporan dengan statistik ringkas
     */
    public function index(Request $request)
    {
        $tanggalMulai  = $request->tanggal_mulai  ? Carbon::parse($request->tanggal_mulai)  : Carbon::now()->startOfMonth();
        $tanggalSelesai = $request->tanggal_selesai ? Carbon::parse($request->tanggal_selesai) : Carbon::now()->endOfDay();

        // ── Statistik Ringkas ──────────────────────────────────────────────────
        $totalPemeriksaan = PemeriksaanKesehatan::whereBetween('waktu_pemeriksaan', [$tanggalMulai, $tanggalSelesai])->count();

        $distribusiSuhu = PemeriksaanKesehatan::whereBetween('waktu_pemeriksaan', [$tanggalMulai, $tanggalSelesai])
            ->select('kategori_suhu', DB::raw('COUNT(*) as total'))
            ->groupBy('kategori_suhu')
            ->pluck('total', 'kategori_suhu');

        $totalDemam = PemeriksaanKesehatan::whereBetween('waktu_pemeriksaan', [$tanggalMulai, $tanggalSelesai])
            ->whereIn('kategori_suhu', ['DEMAM_RINGAN', 'DEMAM_SEDANG', 'DEMAM_TINGGI'])
            ->count();

        $totalPasienUnik = PemeriksaanKesehatan::whereBetween('waktu_pemeriksaan', [$tanggalMulai, $tanggalSelesai])
            ->distinct('pasien_id')
            ->count('pasien_id');

        $perluReview = AnalisisAi::where('ditinjau_dokter', false)->count();

        // ── Chart: Tren Harian (ikuti range filter, max 90 hari) ────────────
        $diffDays    = (int) $tanggalMulai->diffInDays($tanggalSelesai);
        $trenStart   = $tanggalMulai->copy()->startOfDay();
        $trenEnd     = $tanggalSelesai->copy()->endOfDay();

        $trenHarian = PemeriksaanKesehatan::whereBetween('waktu_pemeriksaan', [$trenStart, $trenEnd])
            ->select(
                DB::raw('DATE(waktu_pemeriksaan) as tanggal'),
                DB::raw('COUNT(*) as total'),
                DB::raw('SUM(CASE WHEN kategori_suhu IN ("DEMAM_RINGAN","DEMAM_SEDANG","DEMAM_TINGGI") THEN 1 ELSE 0 END) as demam')
            )
            ->groupBy('tanggal')
            ->orderBy('tanggal')
            ->get()
            ->keyBy('tanggal');

        // Isi hari yang kosong dengan 0 — iterasi dari tanggalMulai s.d. tanggalSelesai
        $chartLabels = [];
        $chartTotal  = [];
        $chartDemam  = [];
        $cursor = $trenStart->copy();
        while ($cursor->lte($trenEnd)) {
            $tgl           = $cursor->format('Y-m-d');
            $chartLabels[] = $cursor->format('d M');
            $chartTotal[]  = $trenHarian->has($tgl) ? (int) $trenHarian[$tgl]->total : 0;
            $chartDemam[]  = $trenHarian->has($tgl) ? (int) $trenHarian[$tgl]->demam : 0;
            $cursor->addDay();
        }

        // ── Chart: Distribusi Kategori Suhu (donut) ───────────────────────────
        $kategoriLabels = ['HIPOTERMIA', 'NORMAL', 'SUBFEBRIS', 'DEMAM_RINGAN', 'DEMAM_SEDANG', 'DEMAM_TINGGI'];
        $kategoriData   = array_map(fn($k) => (int) ($distribusiSuhu[$k] ?? 0), $kategoriLabels);

        // ── Chart: Pemeriksaan per Dokter ─────────────────────────────────────
        $pemeriksaanPerDokter = Dokter::with('user')
            ->withCount(['pemeriksaanKesehatan' => function ($q) use ($tanggalMulai, $tanggalSelesai) {
                $q->whereBetween('waktu_pemeriksaan', [$tanggalMulai, $tanggalSelesai]);
            }])
            ->orderByDesc('pemeriksaan_kesehatan_count')
            ->limit(10)
            ->get()
            // Map nama: prioritas nama_dokter → user->name → fallback 'Dokter'
            ->each(function ($d) {
                $d->label_nama = $d->nama_dokter
                    ?? optional($d->user)->name
                    ?? 'Dokter';
            });

        // ── Tabel DataTables (semua pemeriksaan dalam range) ──────────────────
        $pemeriksaan = PemeriksaanKesehatan::with(['pasien', 'petugas', 'analisisAi'])
            ->whereBetween('waktu_pemeriksaan', [$tanggalMulai, $tanggalSelesai])
            ->orderByDesc('waktu_pemeriksaan')
            ->get();

        // ── Statistik Tambahan ────────────────────────────────────────────────
        $avgSuhu = PemeriksaanKesehatan::whereBetween('waktu_pemeriksaan', [$tanggalMulai, $tanggalSelesai])
            ->avg('suhu_tubuh');

        $pasienBaru = Pasien::whereBetween('created_at', [$tanggalMulai, $tanggalSelesai])->count();

        return view('admin.laporan.index', compact(
            'tanggalMulai', 'tanggalSelesai',
            'totalPemeriksaan', 'distribusiSuhu', 'totalDemam',
            'totalPasienUnik', 'perluReview', 'avgSuhu', 'pasienBaru',
            'chartLabels', 'chartTotal', 'chartDemam',
            'kategoriLabels', 'kategoriData',
            'pemeriksaanPerDokter',
            'pemeriksaan'
        ));
    }

    /**
     * Laporan Harian
     */
    public function harian(Request $request)
    {
        $tanggal = $request->tanggal ? Carbon::parse($request->tanggal) : Carbon::today();

        $pemeriksaan = PemeriksaanKesehatan::with(['pasien', 'petugas', 'analisisAi'])
            ->whereDate('waktu_pemeriksaan', $tanggal)
            ->orderBy('waktu_pemeriksaan')
            ->get();

        $stats = [
            'total'         => $pemeriksaan->count(),
            'normal'        => $pemeriksaan->where('kategori_suhu', 'NORMAL')->count(),
            'demam'         => $pemeriksaan->whereIn('kategori_suhu', ['DEMAM_RINGAN','DEMAM_SEDANG','DEMAM_TINGGI'])->count(),
            'demam_tinggi'  => $pemeriksaan->where('kategori_suhu', 'DEMAM_TINGGI')->count(),
            'avg_suhu'      => round($pemeriksaan->avg('suhu_tubuh'), 1),
        ];

        // Per jam
        $perJam = $pemeriksaan->groupBy(fn($p) => Carbon::parse($p->waktu_pemeriksaan)->format('H'))
            ->map->count();

        return view('admin.laporan.harian', compact('pemeriksaan', 'stats', 'perJam', 'tanggal'));
    }

    /**
     * Laporan Bulanan
     */
    public function bulanan(Request $request)
    {
        $bulan  = $request->bulan  ?? Carbon::now()->month;
        $tahun  = $request->tahun  ?? Carbon::now()->year;
        $mulai  = Carbon::create($tahun, $bulan, 1)->startOfDay();
        $selesai = Carbon::create($tahun, $bulan, 1)->endOfMonth();

        $perHari = PemeriksaanKesehatan::whereBetween('waktu_pemeriksaan', [$mulai, $selesai])
            ->select(
                DB::raw('DAY(waktu_pemeriksaan) as hari'),
                DB::raw('COUNT(*) as total'),
                DB::raw('SUM(CASE WHEN kategori_suhu IN ("DEMAM_RINGAN","DEMAM_SEDANG","DEMAM_TINGGI") THEN 1 ELSE 0 END) as demam'),
                DB::raw('AVG(suhu_tubuh) as avg_suhu')
            )
            ->groupBy('hari')
            ->orderBy('hari')
            ->get();

        $distribusi = PemeriksaanKesehatan::whereBetween('waktu_pemeriksaan', [$mulai, $selesai])
            ->select('kategori_suhu', DB::raw('COUNT(*) as total'))
            ->groupBy('kategori_suhu')
            ->pluck('total', 'kategori_suhu');

        $totalBulan = PemeriksaanKesehatan::whereBetween('waktu_pemeriksaan', [$mulai, $selesai])->count();

        return view('admin.laporan.bulanan', compact('perHari', 'distribusi', 'totalBulan', 'bulan', 'tahun', 'mulai'));
    }

    /**
     * Laporan Pasien
     */
    public function laporanPasien(Request $request)
    {
        $query = Pasien::withCount('pemeriksaanKesehatan')
            ->with(['pemeriksaanKesehatan' => fn($q) => $q->latest()->limit(1)]);

        if ($request->filled('search')) {
            $query->where(function ($q) use ($request) {
                $q->where('nama_lengkap', 'like', "%{$request->search}%")
                  ->orWhere('no_rekam_medis', 'like', "%{$request->search}%");
            });
        }

        $pasien = $query->orderByDesc('pemeriksaan_kesehatan_count')->get();

        return view('admin.laporan.pasien', compact('pasien'));
    }

    /**
     * Laporan Dokter
     */
    public function laporanDokter(Request $request)
    {
        $dokterList = Dokter::with('user')
            ->withCount(['pemeriksaanKesehatan', 'analisisAiReviewed'])
            ->where('status_dokter', 'AKTIF')
            ->get();

        return view('admin.laporan.dokter', compact('dokterList'));
    }

    /**
     * Export Excel / PDF
     */
    public function export(Request $request)
    {
        $request->validate([
            'format'         => 'required|in:excel,pdf,csv',
            'jenis'          => 'required|in:pemeriksaan,pasien,dokter,harian,bulanan',
            'tanggal_mulai'  => 'nullable|date',
            'tanggal_selesai'=> 'nullable|date',
        ]);

        $tanggalMulai  = $request->tanggal_mulai  ? Carbon::parse($request->tanggal_mulai)->startOfDay()  : Carbon::now()->startOfMonth();
        $tanggalSelesai = $request->tanggal_selesai ? Carbon::parse($request->tanggal_selesai)->endOfDay() : Carbon::now()->endOfDay();

        $data = $this->getExportData($request->jenis, $tanggalMulai, $tanggalSelesai);

        switch ($request->format) {
            case 'excel':
                return $this->exportExcel($data, $request->jenis, $tanggalMulai, $tanggalSelesai);
            case 'csv':
                return $this->exportCsv($data, $request->jenis, $tanggalMulai, $tanggalSelesai);
            case 'pdf':
                return $this->exportPdf($data, $request->jenis, $tanggalMulai, $tanggalSelesai);
        }
    }

    // ── Private Helpers ──────────────────────────────────────────────────────

    private function getExportData($jenis, $mulai, $selesai)
    {
        switch ($jenis) {
            case 'pemeriksaan':
            case 'harian':
            case 'bulanan':
                return PemeriksaanKesehatan::with(['pasien', 'petugas'])
                    ->whereBetween('waktu_pemeriksaan', [$mulai, $selesai])
                    ->orderByDesc('waktu_pemeriksaan')
                    ->get();

            case 'pasien':
                return Pasien::withCount('pemeriksaanKesehatan')->orderBy('nama_lengkap')->get();

            case 'dokter':
                return Dokter::with('user')->withCount('pemeriksaanKesehatan')->get();
        }
    }

    private function exportExcel($data, $jenis, $mulai, $selesai)
    {
        // Menggunakan native PHP untuk generate Excel (CSV with Excel-compatible encoding)
        // Untuk production, gunakan Laravel Excel / Maatwebsite
        $filename = "laporan_{$jenis}_{$mulai->format('Ymd')}_{$selesai->format('Ymd')}.csv";

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

        $callback = function () use ($data, $jenis) {
            $file = fopen('php://output', 'w');
            // BOM for Excel UTF-8
            fprintf($file, chr(0xEF) . chr(0xBB) . chr(0xBF));

            if ($jenis === 'pemeriksaan' || $jenis === 'harian' || $jenis === 'bulanan') {
                fputcsv($file, ['No', 'Kode', 'Tanggal', 'Nama Pasien', 'No. Rekam Medis',
                    'Suhu (°C)', 'Kategori Suhu', 'Detak Jantung', 'Tekanan Darah',
                    'Saturasi O2', 'Keluhan', 'Petugas', 'Status']);

                foreach ($data as $i => $p) {
                    fputcsv($file, [
                        $i + 1,
                        $p->kode_pemeriksaan ?? '-',
                        optional($p->waktu_pemeriksaan)->format('d/m/Y H:i') ?? '-',
                        optional($p->pasien)->nama_lengkap ?? '-',
                        optional($p->pasien)->no_rekam_medis ?? '-',
                        $p->suhu_tubuh,
                        $p->kategori_suhu,
                        $p->detak_jantung ?? '-',
                        ($p->tekanan_darah_sistol && $p->tekanan_darah_diastol) ? "{$p->tekanan_darah_sistol}/{$p->tekanan_darah_diastol}" : '-',
                        $p->saturasi_oksigen ?? '-',
                        $p->keluhan_utama ?? '-',
                        optional($p->petugas)->name ?? '-',
                        $p->status_pemeriksaan ?? '-',
                    ]);
                }

            } elseif ($jenis === 'pasien') {
                fputcsv($file, ['No', 'No. RM', 'Nama Lengkap', 'Tgl Lahir', 'JK',
                    'No. WA', 'Total Pemeriksaan', 'Wajah Terdaftar', 'Status']);
                foreach ($data as $i => $p) {
                    fputcsv($file, [
                        $i + 1,
                        $p->no_rekam_medis,
                        $p->nama_lengkap,
                        optional($p->tanggal_lahir)->format('d/m/Y') ?? '-',
                        $p->jenis_kelamin === 'L' ? 'Laki-laki' : 'Perempuan',
                        $p->no_wa ?? '-',
                        $p->pemeriksaan_kesehatan_count,
                        $p->wajah_terdaftar ? 'Ya' : 'Tidak',
                        $p->status_pasien,
                    ]);
                }

            } elseif ($jenis === 'dokter') {
                fputcsv($file, ['No', 'Nama Dokter', 'Spesialisasi', 'No. SIP',
                    'Total Pemeriksaan', 'Status']);
                foreach ($data as $i => $d) {
                    fputcsv($file, [
                        $i + 1,
                        optional($d->user)->name ?? $d->nama_dokter ?? '-',
                        $d->spesialisasi ?? '-',
                        $d->no_sip ?? '-',
                        $d->pemeriksaan_kesehatan_count,
                        $d->status_dokter,
                    ]);
                }
            }

            fclose($file);
        };

        return response()->stream($callback, 200, $headers);
    }

            // ✅ BENAR
        private function exportCsv($data, $jenis, $mulai, $selesai)
{
    return $this->exportExcel($data, $jenis, $mulai, $selesai);
}

    private function exportPdf($data, $jenis, $mulai, $selesai)
    {
        $view    = view('admin.laporan.pdf.' . $jenis, compact('data', 'mulai', 'selesai'))->render();
        $filename = "laporan_{$jenis}_{$mulai->format('Ymd')}.pdf";

        // Menggunakan DomPDF jika tersedia, fallback ke HTML download
        if (class_exists('\Barryvdh\DomPDF\Facade\Pdf')) {
            $pdf = \Barryvdh\DomPDF\Facade\Pdf::loadHTML($view)->setPaper('a4', 'landscape');
            return $pdf->download($filename);
        }

        // Fallback: kirim HTML agar browser bisa print ke PDF
        return response($view, 200, [
            'Content-Type'        => 'text/html',
            'Content-Disposition' => "attachment; filename=\"{$filename}.html\"",
        ]);
    }
}