<?php

namespace Modules\Lpj\Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Modules\Basicdata\Models\Branch;
use Modules\Lpj\Models\Debiture;
use Modules\Usermanagement\Models\User;


class MigrationDebitureSeeder extends Seeder
{
    protected $errorLogFile = __DIR__ . '/csv/debitures/error_migration.csv';

    /**
     * Run the database seeds.
     */
    public function run()
    {
        // Bersihkan/Inisialisasi file error log
        $this->initializeErrorLog();

        // Path ke file csv
        $filePath = realpath(__DIR__ . '/csv/debitures/debitur.latest.csv');

        if (!$filePath) {
            Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/debitures/debitur.latest.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 = 500;
        $userData = [];
        $branchCache = [];
        $totalData = 0;

        // Hitung total baris
        while (($data = fgetcsv($handle, 0, '|')) !== false) {
            $totalData++;
        }

        rewind($handle);
        fgetcsv($handle, 0, '|'); // Lewati header

        $currentRow = 0;
        $batchCount = 0;

        while (($data = fgetcsv($handle, 0, '|')) !== false) {
            if (count($data) != count($header)) {
                $this->logError($data[0] ?? '-', 'Jumlah kolom tidak sesuai');
                continue;
            }

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

            if (count($rows) >= $batchSize) {
                $batchCount++;
                $this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
                $this->processBatch($rows, $branchCache, $userData);
                $rows = [];
            }
        }

        // print_r($rows);
        if (!empty($rows)) {
            $batchCount++;
            $this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
            $this->processBatch($rows, $branchCache, $userData);
        }

        fclose($handle);

        $this->command->info("Data debiture berhasil dimigrasikan. Total data: {$totalData}, Total batch: {$batchCount}");
    }

    private function processBatch(array $rows, array &$branchCache, array &$userData)
    {
        foreach ($rows as $index => $row) {
            try {
                $kode = $row['mig_kd_debitur_seq'] ?? '-';

                // Cek apakah sudah diproses sebelumnya
                $existingRecord = Debiture::where('mig_kd_debitur_seq', $kode)->first();
                if ($existingRecord && $existingRecord->processed_at) {
                    $this->command->info("Data sudah diproses sebelumnya: $kode");
                    //continue;
                }

                // Ambil branch_id
                $branchId = $this->getBranchId($row['mig_kd_cabang'] ?? null, $branchCache);
                if (!$branchId) {
                    $this->logError($row['mig_kd_cabang'], 'Cabang tidak ditemukan');
                    //continue;
                }

                // Ambil user IDs berdasarkan NIK
                $userIdUpdate = $this->getUserId($row['mig_user_update'] ?? null, $userData)['id'];
                $userIdOtorisasi = $this->getUserId($row['mig_user_oto'] ?? null, $userData)['id'];

                // if (!$userIdUpdate || !$userIdOtorisasi) {
                //     $this->logError($kode, 'Salah satu user tidak ditemukan');
                //     continue;
                // }

                // Mapping field user
                $mapUser = [
                    'created_by' => $userIdUpdate,
                    'updated_by' => $userIdUpdate,
                    'authorized_by' => $userIdOtorisasi,
                ];

                // Parsing nomor HP
                $nomorHp = !empty($row['mig_phone']) ? preg_replace('/[^0-9]/', '', $row['mig_phone']) : null;
                $email = !empty($row['email']) ? $row['email'] : null;
                $nomorId = !empty($row['nomor_id']) ? $row['nomor_id'] : null;

                // Parsing waktu
                $authorizedAt = $this->parseTimestamp($row['mig_tgl_oto'] ?? null);
                $createdAt = $this->parseTimestamp($row['created_at'] ?? null);
                $updatedAt = $this->parseTimestamp($row['updated_at'] ?? null);

                if (!$createdAt || !$updatedAt) {
                    $this->logError($kode, 'Gagal parsing created_at / updated_at');
                    continue;
                }

                // Simpan data
                Debiture::updateOrCreate([
                    'mig_kd_debitur_seq' => (int) strtok($row['mig_kd_debitur_seq'], '.'),
                ], [
                    'branch_id' => $branchId,
                    'name' => $row['name'] ?? '',
                    'cif' => (int) strtok($row['cif'],'.') ?: '0000000000',
                    'phone' => $nomorHp,
                    'nomor_id' => $nomorId,
                    'email' => $email,
                    'npwp' => null,
                    'address' => $row['address'] ?? null,
                    'authorized_at' => $authorizedAt,
                    'authorized_by' => $mapUser['authorized_by'],
                    'created_by' => $mapUser['created_by'] ?? null,
                    'updated_by' => $mapUser['updated_by'] ?? null,
                    'created_at' => $createdAt,
                    'updated_at' => $updatedAt,
                    'mig_kd_debitur_seq' => (int) strtok($row['mig_kd_debitur_seq'], '.'),
                    'processed_at' => now(),
                    'mig_debitur' => json_encode($row),
                    'is_mig' => 1
                ]);

                $this->command->info("Proses data debiture $kode (" . ($index + 1) . '/' . count($rows) . ')');

            } catch (\Exception $e) {
                $this->logError($row['mig_kd_debitur_seq'] ?? '-', "Error eksepsi: " . $e->getMessage());
            }
        }
    }

    private function getBranchId(?string $code, array &$cache): ?int
    {
        if (!$code) return null;

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

        $branch = Branch::where('code', $code)->first();

        if ($branch) {
            $cache[$code] = $branch->id;
            return $branch->id;
        }

        return null;
    }

    private function getUserId(?string $code, array &$cache): array
    {
        if (!$code) return ['id' => null, 'branch_id' => null];

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

        $user = User::where('nik', $code)->first();

        if ($user) {
            $cache[$code] = ['id' => $user->id, 'branch_id' => $user->branch_id];
            return $cache[$code];
        }

        return ['id' => null, 'branch_id' => null];
    }

    private function parseTimestamp(?string $timestamp): ?string
    {
        try {
            if ($timestamp) {
                // Cek jika format hanya tanggal (Y-m-d)
                if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $timestamp)) {
                    return \Carbon\Carbon::createFromFormat('Y-m-d', $timestamp)
                        ->startOfDay()
                        ->toDateTimeString();
                }
                // Format lengkap (Y-m-d H:i:s)
                if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $timestamp)) {
                    return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString();
                }
                // Format d/m/Y H:i:s (contoh: 28/4/2017 14:43:43)
                if (preg_match('/^\d{1,2}\/\d{1,2}\/\d{4} \d{2}:\d{2}:\d{2}$/', $timestamp)) {
                    return \Carbon\Carbon::createFromFormat('d/m/Y H:i:s', $timestamp)->toDateTimeString();
                }
            }
            return null;
        } catch (\Exception $e) {
            Log::error('Gagal memparsing timestamp: ' . $timestamp . '. Pesan: ' . $e->getMessage());
            return null;
        }
    }

    private function initializeErrorLog()
    {
        // Jika file lama ada, hapus
        if (file_exists($this->errorLogFile)) {
            unlink($this->errorLogFile);
        }

        // Buat file baru dengan header
        $handle = fopen($this->errorLogFile, 'w');
        fputcsv($handle, ['mig_kd_debitur_seq', 'Error']);
        fclose($handle);
    }

    private function logError(string $kode, string $message)
    {
        // Catat ke log
        Log::error("Error migrasi debiture [$kode]: $message");

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