<?php

namespace App\Exports;

use App\Models\User;
use App\Models\HasilPrediksi;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithTitle;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithStyles;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Events\AfterSheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use Illuminate\Support\Collection;

class HasilPrediksiRekapExport implements WithMultipleSheets
{
    public function sheets(): array
    {
        $sheets = [];
        $pangkalanList = User::where(['role' => 'user'])->get();

        // Sheet 1: Halaman monitoring dashboard utama untuk semua pangkalan
        $sheets[] = new RingkasanEvaluasiPrediksiSheet($pangkalanList);

        // Sheet 2 dan seterusnya: Laporan detail per pangkalan
        foreach ($pangkalanList as $pangkalan) {
            $sheets[] = new PangkalanPredictionSheet($pangkalan);
        }

        return $sheets;
    }
}

class RingkasanEvaluasiPrediksiSheet implements FromCollection, WithTitle, WithHeadings, WithStyles, ShouldAutoSize, WithEvents
{
    private Collection $pangkalanList;

    public function __construct(Collection $pangkalanList)
    {
        $this->pangkalanList = $pangkalanList;
    }

    public function title(): string
    {
        return 'Pusat Mitigasi Prediksi';
    }

    public function collection(): Collection
    {
        Carbon::setLocale('id');
        $summaryData = collect();

        foreach ($this->pangkalanList as $index => $pangkalan) {
            // Mengambil total estimasi, total batas bawah, dan total batas atas per bulan
            $monthlyData = HasilPrediksi::where(['user_id' => $pangkalan->id])
                ->select(
                    DB::raw("DATE_FORMAT(tanggal, '%Y-%m') as bulan"), 
                    DB::raw("SUM(estimasi) as total_estimasi"),
                    DB::raw("SUM(batas_bawah) as total_bawah"),
                    DB::raw("SUM(batas_atas) as total_atas")
                )
                ->groupBy('bulan')
                ->get();

            if ($monthlyData->isEmpty()) {
                continue;
            }

            // Mencari bulan dengan nilai estimasi tertinggi
            $sortedMonthly = $monthlyData->sortByDesc('total_estimasi');
            $highestPredRow = $sortedMonthly->first();
            $lowestPredRow = $sortedMonthly->last();

            $highestMonth = Carbon::parse($highestPredRow->bulan . '-01')->translatedFormat('F Y');
            $lowestMonth = Carbon::parse($lowestPredRow->bulan . '-01')->translatedFormat('F Y');
            
            $peakValue = (int)$highestPredRow->total_estimasi;
            $averageValue = (int)round($monthlyData->pluck('total_estimasi')->avg());
            $averageBawah = (int)round($monthlyData->pluck('total_bawah')->avg());
            $averageAtas = (int)round($monthlyData->pluck('total_atas')->avg());

            // Menghitung persentase kenaikan puncak terhadap rata-rata bulanan
            $persentaseKenaikan = $averageValue > 0 ? (($peakValue - $averageValue) / $averageValue) * 100 : 0;

            if ($persentaseKenaikan > 20.0) {
                $statusTindakan = 'PERLU PERHATIAN KHUSUS';
                $alasanAnalisis = 'Diproyeksikan mengalami lonjakan permintaan ekstrem sebesar ' . round($persentaseKenaikan, 1) . '%. Alokasi pasokan wajib ditambah mendekati batas atas.';
            } else if ($persentaseKenaikan > 10.0) {
                $statusTindakan = 'Pantauan Berkala';
                $alasanAnalisis = 'Terdapat indikasi kenaikan permintaan pasar tingkat sedang. Diperlukan pemantauan stok berkala.';
            } else {
                $statusTindakan = 'Stabil (Aman)';
                $alasanAnalisis = 'Proyeksi fluktuasi permintaan cenderung landai. Alokasi kuota reguler aman.';
            }

            $summaryData->push([
                $index + 1,
                $pangkalan->name,
                $averageValue . ' Tabung',
                $averageBawah . ' Tabung', // Tambahan Kolom Rata-rata Batas Bawah bulanan
                $averageAtas . ' Tabung',  // Tambahan Kolom Rata-rata Batas Atas bulanan
                $highestMonth,
                $peakValue . ' Tabung',
                round($persentaseKenaikan, 1) . '%',
                $statusTindakan,
                $alasanAnalisis
            ]);
        }

        // Urutkan berdasarkan pangkalan yang statusnya PERLU PERHATIAN KHUSUS paling atas
        return $summaryData->sortBy(function($row) {
            return $row[8] === 'PERLU PERHATIAN KHUSUS' ? 0 : 1;
        });
    }

    public function headings(): array
    {
        return [
            ['DASHBOARD UTAMA MONITORING PREDIKSI AGEN: MITIGASI KERAWANAN PASOKAN'],
            ['Diunduh tgl:', Carbon::now()->translatedFormat('d F Y H:i') . ' WIB'],
            ['Berikut adalah daftar pangkalan yang diurutkan berdasarkan skala prioritas penambahan stok akibat proyeksi lonjakan tertinggi.'],
            [''],
            ['No', 'Nama Pangkalan', 'Rata-rata Prediksi / Bulan', 'Rata-rata Batas Bawah', 'Rata-rata Batas Atas', 'Bulan Lonjakan Tertinggi', 'Estimasi Puncak (Tabung)', 'Persentase Kenaikan', 'Rekomendasi Tindakan Agen', 'Penyebab / Alasan Analisis']
        ];
    }

    public function styles(Worksheet $sheet): array
    {
        return [
            1 => ['font' => ['bold' => true, 'size' => 14, 'color' => ['rgb' => '111111']]],
            2 => ['font' => ['italic' => true, 'size' => 10]],
            5 => [
                'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF']],
                'fill' => ['fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'startColor' => ['rgb' => '1F4E79']]
            ]
        ];
    }

    public function registerEvents(): array
    {
        return [
            AfterSheet::class => function (AfterSheet $event) {
                $sheet = $event->sheet->getDelegate();
                $highestRow = $sheet->getHighestRow();

                $sheet->mergeCells("A1:J1");
                $sheet->mergeCells("A2:J2");
                $sheet->mergeCells("A3:J3");

                $styleArray = [
                    'borders' => [
                        'allBorders' => [
                            'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
                            'color' => ['rgb' => 'CCCCCC'],
                        ],
                    ],
                ];
                $sheet->getStyle("A5:J{$highestRow}")->applyFromArray($styleArray);

                for ($row = 6; $row <= $highestRow; $row++) {
                    $cellValue = $sheet->getCell("I{$row}")->getValue();
                    if (str_contains($cellValue, 'PERHATIAN KHUSUS')) {
                        $sheet->getStyle("I{$row}")->getFont()->setBold(true)->getColor()->setRGB('9C0006');
                        $sheet->getStyle("I{$row}")->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)->getStartColor()->setRGB('FFC7CE');
                    } elseif (str_contains($cellValue, 'Pantauan Berkala')) {
                        $sheet->getStyle("I{$row}")->getFont()->setBold(true)->getColor()->setRGB('9C6500');
                        $sheet->getStyle("I{$row}")->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)->getStartColor()->setRGB('FFEB9C');
                    } else {
                        $sheet->getStyle("I{$row}")->getFont()->getColor()->setRGB('006100');
                        $sheet->getStyle("I{$row}")->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)->getStartColor()->setRGB('C6EFCE');
                    }
                }
            }
        ];
    }
}

class PangkalanPredictionSheet implements FromCollection, WithTitle, WithHeadings, WithStyles, ShouldAutoSize, WithEvents
{
    private User $pangkalan;
    private string $highestMonth = '-';
    private string $lowestMonth = '-';
    private int $highestBatasAtas = 0;
    private int $lowestBatasBawah = 0;
    private Collection $monthlySummary;

    public function __construct(User $pangkalan)
    {
        $this->pangkalan = $pangkalan;
        $this->monthlySummary = collect();
    }

    public function title(): string
    {
        return substr(preg_replace('/[^A-Za-z0-9 ]/', '', $this->pangkalan->name), 0, 30);
    }

    public function collection(): Collection
    {
        Carbon::setLocale('id');
        
        // Mengambil riwayat detail harian prediksi (Termasuk kolom batas bawah dan batas atas)
        $data = HasilPrediksi::where(['user_id' => $this->pangkalan->id])
            ->select('tanggal', 'estimasi', 'batas_bawah', 'batas_atas')
            ->orderBy('tanggal', 'asc')
            ->get()
            ->unique('tanggal');

        // Merekap nilai bulanan estimasi, batas bawah, dan batas atas
        $analytics = HasilPrediksi::where(['user_id' => $this->pangkalan->id])
            ->select(
                DB::raw("DATE_FORMAT(tanggal, '%Y-%m') as bulan_tahun"),
                DB::raw("SUM(estimasi) as total"),
                DB::raw("SUM(batas_bawah) as total_bawah"),
                DB::raw("SUM(batas_atas) as total_atas")
            )
            ->groupBy('bulan_tahun')
            ->orderBy('total', 'desc')
            ->get();

        if ($analytics->isNotEmpty()) {
            $this->highestMonth = Carbon::parse($analytics->first()->bulan_tahun . '-01')->translatedFormat('F Y');
            $this->lowestMonth = Carbon::parse($analytics->last()->bulan_tahun . '-01')->translatedFormat('F Y');
            $this->highestBatasAtas = (int)$analytics->first()->total_atas;
            $this->lowestBatasBawah = (int)$analytics->last()->total_bawah;
            
            $this->monthlySummary = $analytics->map(function ($item) {
                return [
                    'bulan' => Carbon::parse($item->bulan_tahun . '-01')->translatedFormat('F Y'),
                    'total' => (int)$item->total,
                    'bawah' => (int)$item->total_bawah,
                    'atas' => (int)$item->total_atas
                ];
            });
        }

        if ($data->isEmpty()) {
            return collect([[Carbon::today()->format('Y-m-d'), 0, 0, 0]]);
        }

        return $data->map(function ($item) {
            return [
                Carbon::parse($item->tanggal)->translatedFormat('d F Y'),
                $item->estimasi !== null && $item->estimasi !== '' ? (int)$item->estimasi : 0,
                $item->batas_bawah !== null && $item->batas_bawah !== '' ? (int)$item->batas_bawah : 0,
                $item->batas_atas !== null && $item->batas_atas !== '' ? (int)$item->batas_atas : 0,
            ];
        });
    }

    public function headings(): array
    {
        return [
            ['LAPORAN PROYEKSI ESTIMASI HASIL PREDIKSI KEBUTUHAN LPG'],
            ['Nama Pangkalan:', $this->pangkalan->name],
            ['Alamat Lokasi:', $this->pangkalan->alamat ?? 'Jember'],
            [""],
            ['Tanggal Prediksi', 'Estimasi Kebutuhan (Tabung)', 'Batas Bawah', 'Batas Atas']
        ];
    }

    public function styles(Worksheet $sheet): array
    {
        return [
            1 => ['font' => ['bold' => true, 'size' => 14, 'color' => ['rgb' => '111111']]],
            2 => ['font' => ['bold' => true]],
            3 => ['font' => ['bold' => true]],
            5 => [
                'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF']],
                'fill' => ['fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'startColor' => ['rgb' => '36B9CC']]
            ]
        ];
    }

    public function registerEvents(): array
    {
        return [
            AfterSheet::class => function (AfterSheet $event) {
                $sheet = $event->sheet->getDelegate();
                $highestRow = $sheet->getHighestRow();
                
                $sheet->mergeCells("A1:D1");
                
                $styleArray = [
                    'borders' => [
                        'allBorders' => [
                            'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
                            'color' => ['rgb' => 'CCCCCC'],
                        ],
                    ],
                ];
                $sheet->getStyle("A5:D{$highestRow}")->applyFromArray($styleArray);
                $sheet->getStyle("B6:D{$highestRow}")->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_RIGHT);

                // 1. MEMBUAT TABEL REKAP BULANAN PREDIKSI + REKAP BATAS BAWAH ATAS
                $summaryStartRow = $highestRow + 3;
                $sheet->mergeCells("A{$summaryStartRow}:D{$summaryStartRow}");
                $sheet->setCellValue("A{$summaryStartRow}", " RINGKASAN TOTAL ESTIMASI PREDIKSI PER BULAN (TERTINGGI KE TERENDAH)");
                $sheet->getStyle("A{$summaryStartRow}")->getFont()->setBold(true)->setColor(new \PhpOffice\PhpSpreadsheet\Style\Color(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_WHITE));
                $sheet->getStyle("A{$summaryStartRow}")->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)->getStartColor()->setRGB('1F4E79');

                $headerRow = $summaryStartRow + 1;
                $sheet->setCellValue("A{$headerRow}", "Bulan & Tahun");
                $sheet->setCellValue("B{$headerRow}", "Total Estimasi (Tabung)");
                $sheet->setCellValue("C{$headerRow}", "Rekap Batas Bawah");
                $sheet->setCellValue("D{$headerRow}", "Rekap Batas Atas");
                $sheet->getStyle("A{$headerRow}:D{$headerRow}")->getFont()->setBold(true);
                $sheet->getStyle("A{$headerRow}:D{$headerRow}")->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)->getStartColor()->setRGB('EAECF4');

                $currentRow = $headerRow + 1;
                foreach ($this->monthlySummary as $sum) {
                    $sheet->setCellValue("A{$currentRow}", $sum['bulan']);
                    $sheet->setCellValue("B{$currentRow}", $sum['total']);
                    $sheet->setCellValue("C{$currentRow}", $sum['bawah']);
                    $sheet->setCellValue("D{$currentRow}", $sum['atas']);
                    $sheet->getStyle("B{$currentRow}:D{$currentRow}")->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_RIGHT);
                    $currentRow++;
                }
                $sheet->getStyle("A{$headerRow}:D" . ($currentRow - 1))->applyFromArray($styleArray);

                // 2. KOTAK MONITORING KESIMPULAN
                $analysisStartRow = $currentRow + 2;
                $sheet->mergeCells("A{$analysisStartRow}:D{$analysisStartRow}");
                $sheet->setCellValue("A{$analysisStartRow}", " KESIMPULAN ANALISIS & MONITORING PROYEKSI PASOKAN");
                $sheet->getStyle("A{$analysisStartRow}")->getFont()->setBold(true)->setColor(new \PhpOffice\PhpSpreadsheet\Style\Color(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_WHITE));
                $sheet->getStyle("A{$analysisStartRow}")->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)->getStartColor()->setRGB('D94F04');

                $r1 = $analysisStartRow + 1; 
                $sheet->mergeCells("A{$r1}:D{$r1}");
                $sheet->setCellValue("A{$r1}", " • Proyeksi lonjakan tertinggi diprediksi pada bulan " . $this->highestMonth . " dengan potensi puncak pasokan atas mencapai: " . $this->highestBatasAtas . " Tabung.");
                
                $r2 = $analysisStartRow + 2; 
                $sheet->mergeCells("A{$r2}:D{$r2}");
                $sheet->setCellValue("A{$r2}", " • Proyeksi permintaan terendah diprediksi pada bulan " . $this->lowestMonth . " dengan batas bawah pasokan minimum sebesar: " . $this->lowestBatasBawah . " Tabung.");
                
                $r3 = $analysisStartRow + 3; 
                $sheet->mergeCells("A{$r3}:D{$r3}");
                $sheet->setCellValue("A{$r3}", " • CATATAN AGEN: Jadikan bulan-bulan dengan volume tertinggi sebagai acuan utama penambahan pasokan taktis secara efisien, guna menghindari risiko kelangkaan stok LPG di pangkalan.");

                $boxRange = "A{$analysisStartRow}:D" . ($analysisStartRow + 4);
                $sheet->getStyle($boxRange)->getBorders()->getOutline()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUM)->getColor()->setRGB('D94F04');
            },
        ];
    }
}