<?php

namespace Modules\Lpj\Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Modules\Lpj\Models\Debiture;
use Modules\Location\Models\City;
use Modules\Location\Models\District;
use Modules\Location\Models\Province;
use Modules\Location\Models\Village;
use Modules\Lpj\Models\DokumenJaminan;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\JenisJaminan;
use Modules\Lpj\Models\JenisLegalitasJaminan;
use Modules\Lpj\Models\PemilikJaminan;
use Modules\Lpj\Models\DetailDokumenJaminan;
use Illuminate\Support\Facades\Log;

class MigrationDetailDokumenJaminanSeeder extends Seeder
{
    protected $errorLogFile = __DIR__ . '/csv/detail.dokumen.jaminan_20251016_error.csv';
    /**
     * Run the database seeds.
     */

    public function run()
    {
        $this->initializeErrorLog();
        // Path ke file csv
        $filePath = realpath(__DIR__ . '/csv/detail.dokumen.jaminan_20251016.csv');

        if (!$filePath) {
            Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/detail.dokumen.jaminan_20251016.csv');
            $this->command->error('File csv tidak ditemukan.');
            return;
        }

        if (($handle = fopen($filePath, 'r')) === false) {
            Log::error('Gagal membuka file CSV: ' . $filePath);
            $this->command->error('Gagal membuka file CSV.');
            return;
        }

        $header = fgetcsv($handle, 0, ',');
        $rows = [];
        $batchSize = 1000; // Ukuran batch
        $permohonanCache = [];
        $jenisJaminanCache = [];
        $dokumenJaminanCache = [];
        $provinceCache = [];
        $cityCache = [];
        $districtCache = [];
        $subdistrictCache = [];
        $totalData = 0;
        $errorCount = 0;
        $errorDebitureIds = [];
        $hubunganPemilikCache = [];

        // Menghitung total data di file CSV
        while (($data = fgetcsv($handle, 0, ',')) !== false) {
            $totalData++;
        }

        rewind($handle); // Reset pointer ke awal file
        fgetcsv($handle, 0, ','); // Skip header

        $batchCount = 0;
        $currentRow = 0;


        // Membaca setiap baris dalam CSV
        while (($data = fgetcsv($handle, 0, ',')) !== false) {
            if (count($data) != count($header)) {
                Log::warning('Baris CSV memiliki jumlah kolom yang tidak sesuai: ' . json_encode($data));
                $errorCount++;
                $errorDebitureIds[] = $data[0] ?? 'ID tidak valid'; // Menyimpan ID yang error
                continue;
            }

            $rows[] = array_combine($header, $data);
            $currentRow++;

            // print_r($rows);


            if (count($rows) >= $batchSize) {
                $errorDebitureIds[] = $data[0] ?? 'ID tidak valid'; // Menyimpan ID yang error
                $this->processBatch($rows, $permohonanCache, $jenisJaminanCache, $dokumenJaminanCache, $batchCount, $currentRow, $totalData, $errorCount, $errorDebitureIds);
                $rows = [];
            }
        }

        // print_r($rows[0]);
        if (!empty($rows)) {
            $this->processBatch($rows, $permohonanCache, $jenisJaminanCache, $dokumenJaminanCache, $batchCount, $currentRow, $totalData, $errorCount, $errorDebitureIds);
        }

        fclose($handle);

        $this->command->info('Data debiture berhasil dimigrasikan.');
    }

    private function processBatch(
        array $rows,
        array &$permohonanCache,
        array &$jenisJaminanCache,
        array &$dokumenJaminanCache,
        int $batchCount,
        int $currentRow,
        int $totalData,
        int &$errorCount,
        array &$errorDebitureIds
    ) {
        $groupedRows = $this->groupRowsByNomorLaporanAndKeterangan($rows);

        // print_r($groupedRows);

        foreach ($groupedRows as $nomorLaporan => $dataPerGrup) {

            // print_r($dataPerGrup);
            try {
                // Ambil salah satu baris untuk referensi (misal baris pertama dari grup)
                $firstRow = reset($dataPerGrup)['details'] ? reset($dataPerGrup) : reset($dataPerGrup);
                $debiturId = null;
                $nomorJaminan = null;


                // Cari debitur ID dari salah satu field
                foreach ($rows as $row) {
                    if ($row['mig_nomor_laporan'] == $nomorLaporan) {
                        $debiturId = $row['mig_kd_debitur_seq'] ?? null;
                        $nomorJaminan = $row['mig_nomor_jaminan'] ?? null;
                        break;
                    }
                }

                if (!$debiturId) {
                    throw new \Exception('Debitur ID tidak ditemukan');
                }



                // Ambil ID dokumen jaminan
                $dokumenJaminanId = $this->getDokumenJaminanId($debiturId,$nomorJaminan, $dokumenJaminanCache);
                if (!$dokumenJaminanId) {
                    throw new \Exception('Dokumen jaminan tidak ditemukan');
                }

                //dd($debiturId,$nomorJaminan);

                foreach ($dataPerGrup as $groupKey => $rowData) {
                    // Ambil legalitas jaminan ID berdasarkan grup keterangan
                    $legalitasJaminanId = $this->getLegalitasJaminanId($groupKey, $jenisJaminanCache);

                    if (!$legalitasJaminanId) {
                        throw new \Exception("Legalitas jaminan tidak ditemukan untuk grup: {$groupKey}");
                    }


                    // Simpan ke database
                    $detail =DetailDokumenJaminan::updateOrCreate(
                        [
                            'name' => $groupKey,
                            'dokumen_jaminan_id' => $dokumenJaminanId,
                        ],
                        [
                            'details' => json_encode($rowData['details']),
                            'jenis_legalitas_jaminan_id' => $legalitasJaminanId,
                            'dokumen_jaminan' => !empty($rowData['documents']) ? json_encode($rowData['documents']) : null,
                            'dokumen_nomor' => $nomorLaporan,
                            'keterangan' => $groupKey,
                        ]
                    );

                    if($nomorJaminan=='253339'){
                        //dd($debiturId,$nomorJaminan,$legalitasJaminanId, $detail, $dokumenJaminanId);
                    }
                }

                // Info progress
                $this->command->info("Proses data detail dokumen (Nomor Laporan: {$nomorLaporan}, batch ke: {$batchCount}, total dari: {$currentRow}/{$totalData})");

            } catch (\Exception $e) {
                Log::error("Error pada nomor laporan {$nomorLaporan}: " . $e->getMessage());
                $this->logError($debiturId ?? '-', $e->getMessage());
                $errorDebitureIds[] = $debiturId ?? '-';
                $errorCount++;
            }
        }
    }


    private function groupRowsByNomorLaporann(array $rows): array
    {
        $grouped = [];

        foreach ($rows as $row) {
            $nomorJaminan = $row['mig_nomor_laporan'] ?? null;
            if (!empty($nomorJaminan)) {
                $grouped[$nomorJaminan][] = $row;
            }
        }

        return $grouped;
    }


    // private function groupRowsByNomorLaporanAndKeterangan(array $rows): array
    // {
    //     $groupedByNomorLaporan = $this->groupRowsByNomorLaporann($rows);
    //     $finalGrouped = [];

    //     foreach ($groupedByNomorLaporan as $nomorLaporan => $rowList) {
    //         $groupedByGrpKeterangan = [];

    //         // Urutkan berdasarkan mig_urutan_sub (ascending)
    //         usort($rowList, function ($a, $b) {
    //             return $a['mig_urutan_sub'] <=> $b['mig_urutan_sub'];
    //         });

    //         foreach ($rowList as $row) {
    //             $grpKeterangan = $row['mig_grp_keterangan'] ?? 'UNKNOWN_GROUP';

    //             if (!isset($groupedByGrpKeterangan[$grpKeterangan])) {
    //                 $groupedByGrpKeterangan[$grpKeterangan] = [
    //                     'details' => [],
    //                     'documents' => []
    //                 ];
    //             }

    //             $keyKeterangan = $row['mig_key_keterangan'] ?? 'UNKNOWN_KEY';
    //             $value = $row['mig_nilai'] ?? null;

    //             // Jika belum ada detail, inisialisasi sebagai array asosiatif
    //             if (empty($groupedByGrpKeterangan[$grpKeterangan]['details'])) {
    //                 $groupedByGrpKeterangan[$grpKeterangan]['details'][] = [];
    //             }

    //             // Masukkan ke dalam object tunggal (bukan item baru)
    //             if ($value !== null) {
    //                 $lastIndex = count($groupedByGrpKeterangan[$grpKeterangan]['details']) - 1;
    //                 $groupedByGrpKeterangan[$grpKeterangan]['details'][$lastIndex][$keyKeterangan] = $value;
    //             }

    //             // Tambahkan dokumen jika ada
    //             $urlFile = $row['mig_url_file'] ?? null;
    //             if (!empty($urlFile)) {
    //                 $groupedByGrpKeterangan[$grpKeterangan]['documents'][] = $urlFile;
    //             }
    //         }

    //         $finalGrouped[$nomorLaporan] = $groupedByGrpKeterangan;
    //     }

    //     // print_r($finalGrouped);
    //     return $finalGrouped;
    // }


    private function groupRowsByNomorLaporanAndKeterangan(array $rows): array
{
    $groupedByNomorLaporan = $this->groupRowsByNomorLaporann($rows);
    $finalGrouped = [];

    foreach ($groupedByNomorLaporan as $nomorLaporan => $rowList) {
        $groupedByGrpKeterangan = [];

        // Urutkan berdasarkan mig_urutan_sub
        usort($rowList, function ($a, $b) {
            return $a['mig_urutan_sub'] <=> $b['mig_urutan_sub'];
        });

        foreach ($rowList as $row) {
            $grpKeterangan = $row['mig_grp_keterangan'] ?? 'UNKNOWN_GROUP';
            $keyKeterangan = $row['mig_key_keterangan'] ?? 'UNKNOWN_KEY';
            $value = $row['mig_nilai'] ?? null;

            if (!isset($groupedByGrpKeterangan[$grpKeterangan])) {
                $groupedByGrpKeterangan[$grpKeterangan] = [
                    'details' => [],
                    'documents' => []
                ];
            }

            // Masukkan sebagai object baru ke dalam details
            if ($value !== null) {
                $groupedByGrpKeterangan[$grpKeterangan]['details'][] = [
                    $keyKeterangan => $value
                ];
            }

            // Dokumen tetap masuk sebagai array string
            $urlFile = $row['mig_url_file'] ?? null;
            if (!empty($urlFile)) {
                $groupedByGrpKeterangan[$grpKeterangan]['documents'][] = $urlFile;
            }
        }

        $finalGrouped[$nomorLaporan] = $groupedByGrpKeterangan;
    }

    return $finalGrouped;
}
    private function getDokumenJaminanId(string $code,string $nomorLaporan, array &$dokumenJaminanCache)
    {
        $dokumen = DokumenJaminan::where('mig_kd_debitur_seq', $code)
            ->where('nomor_lpj', $nomorLaporan)
            ->first();

        if ($dokumen) {
            $dokumenJaminanCache[$code] = $dokumen->id;
            return $dokumen->id;
        }
    }

    private function getLegalitasJaminanId(string $code, array &$legalitasJaminanCache)
    {

        if (isset($legalitasJaminanCache[$code])) {
            return $legalitasJaminanCache[$code];
        }

        $legalitas = JenisLegalitasJaminan::whereRaw('LOWER(name) = ?', [strtolower($code)])->first();

        if ($legalitas) {
            $legalitasJaminanCache[$code] = $legalitas->id;
            return $legalitas->id;
        }

        return null;
    }

    private function initializeErrorLog()
{
    $file = $this->errorLogFile;

    if (file_exists($file)) {
        unlink($file); // Hapus file lama
    }

    $handle = fopen($file, 'w');
    fputcsv($handle, ['mig_kd_debitur_seq', 'Error']);
    fclose($handle);
}

private function logError(string $kode, string $message)
{
    Log::error("Error migrasi dokumen jaminan [$kode]: $message");

    $handle = fopen($this->errorLogFile, 'a');
    fputcsv($handle, [$kode, $message]);
    fclose($handle);
}

}
