<?php

namespace App\Services;

use App\Models\LeasingDataUpload;
use App\Models\LeasingRecord;
use App\Models\Branch;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;

class LeasingUploadService
{
    protected $auditLog;
    protected $notification;

    public function __construct(AuditLogService $auditLog, NotificationService $notification)
    {
        $this->auditLog = $auditLog;
        $this->notification = $notification;
    }

    public function process(LeasingDataUpload $upload): array
    {
        $valid = 0;
        $invalid = 0;
        $errors = [];

        // Simple CSV Parser using private storage
        $disk = Storage::disk('local');
        $relativeDir = 'private/uploads/leasing/' . $upload->leasing_profile_id;
        $relativeFilePath = $relativeDir . '/' . $upload->filename;
        
        if (!$disk->exists($relativeFilePath)) {
            $upload->update(['status' => 'failed']);
            return ['valid' => 0, 'invalid' => 0, 'error' => 'File tidak ditemukan di penyimpanan aman.'];
        }

        $filePath = $disk->path($relativeFilePath);

        $handle = fopen($filePath, 'r');
        // Handle Byte Order Mark (BOM)
        $bom = fread($handle, 3);
        if ($bom != "\xEF\xBB\xBF") {
            rewind($handle);
        }

        $header = fgetcsv($handle, 1000, ",");
        if (!$header) {
            fclose($handle);
            $upload->update(['status' => 'failed']);
            return ['valid' => 0, 'invalid' => 0, 'error' => 'Header CSV tidak valid.'];
        }

        // Normalize headers
        $header = array_map(fn($h) => strtoupper(trim($h)), $header);
        $headerMap = array_flip($header);

        while (($row = fgetcsv($handle, 1000, ",")) !== false) {
            if (count($row) < 5) {
                $invalid++;
                continue;
            }

            try {
                DB::transaction(function () use ($row, $headerMap, $upload, &$valid) {
                    $getValue = fn($key) => isset($headerMap[$key]) ? trim($row[$headerMap[$key]]) : null;

                    // Find or Create Branch
                    $branchName = $getValue('CAB') ?: 'PUSAT';
                    $branch = Branch::firstOrCreate([
                        'leasing_profile_id' => $upload->leasing_profile_id,
                        'branch_name' => strtoupper($branchName),
                    ]);

                    LeasingRecord::updateOrCreate([
                        'leasing_profile_id' => $upload->leasing_profile_id,
                        'nopol' => strtoupper($getValue('NOPOL')),
                    ], [
                        'branch_id' => $branch->id,
                        'upload_id' => $upload->id,
                        'tgl_data' => $getValue('TGL') ?: now()->toDateString(),
                        'rangka' => strtoupper($getValue('RANGKA')),
                        'mesin' => strtoupper($getValue('MESIN')),
                        'model' => $getValue('MODEL'),
                        'kendaraan' => $getValue('KENDARAAN'),
                        'overdue_days' => (int)$getValue('OVERDUE'),
                        'sisa_saldo' => (float)$getValue('SISA_SALDO'),
                        'legal_flag' => $getValue('LEGAL_FLAG') ?: '0',
                        'member_warning' => $getValue('MEMBER_WARNING'),
                        'member_instruction' => $getValue('MEMBER_INSTRUCTION'),
                        'record_status' => 'active',
                    ]);

                    $valid++;
                });
            } catch (\Exception $e) {
                $invalid++;
                $errors[] = $e->getMessage();
            }
        }

        fclose($handle);

        $upload->update([
            'status' => 'completed',
            'row_count' => $valid,
        ]);

        $this->auditLog->log('BATCH_UPLOAD_PROCESSED', $upload, null, ['valid' => $valid, 'invalid' => $invalid]);
        $this->notification->notify(
            $upload->leasingProfile->user, 
            'Proses Upload Selesai', 
            "Data batch {$upload->filename} selesai diproses. Berhasil: $valid, Gagal: $invalid.", 
            'info', 
            route('leasing.uploads.show', $upload)
        );

        return ['valid' => $valid, 'invalid' => $invalid, 'errors' => $errors];
    }
}
