<?php

namespace App\Modules\Pilkades\Services;

use App\Modules\Pilkades\Models\Tps;
use App\Modules\Pilkades\Models\Voter;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\DB;

class VoterService
{
    public function create(string $desaId, array $data): Voter
    {
        $voter = new Voter($data);
        $voter->desa_id = $desaId;
        $voter->nama = $data['nama'];
        $voter->nik = $data['nik'];
        $voter->tps_id = $data['tps_id'];
        $voter->rt = $data['rt'] ?? null;
        $voter->rw = $data['rw'] ?? null;
        $voter->status_terdaftar = $data['status_terdaftar'] ?? 'terdaftar';
        $voter->save();

        return $voter;
    }

    public function update(Voter $voter, array $data): Voter
    {
        $voter->nama = $data['nama'];

        if (! empty($data['nik'])) {
            $voter->nik = $data['nik'];
        }

        $voter->tps_id = $data['tps_id'];
        $voter->rt = $data['rt'] ?? null;
        $voter->rw = $data['rw'] ?? null;
        $voter->status_terdaftar = $data['status_terdaftar'] ?? $voter->status_terdaftar;
        $voter->save();

        return $voter;
    }

    /**
     * Import voters from a CSV file. Expected header: nama,nik,tps,rt,rw
     * The "tps" column is a free-text TPS number — matched against existing
     * Tps records for this desa (created automatically if not found yet),
     * so imports don't fail just because a TPS hasn't been registered first.
     * Returns a summary of imported/skipped rows with reasons, per FR-031.
     */
    public function importFromCsv(string $desaId, UploadedFile $file): array
    {
        $handle = fopen($file->getRealPath(), 'r');
        $header = fgetcsv($handle);
        $header = array_map(fn ($h) => strtolower(trim((string) $h)), $header);

        $required = ['nama', 'nik', 'tps'];
        foreach ($required as $col) {
            if (! in_array($col, $header, true)) {
                fclose($handle);

                return ['imported' => 0, 'skipped' => 0, 'errors' => ["Kolom wajib '{$col}' tidak ditemukan di header CSV."]];
            }
        }

        $imported = 0;
        $skipped = 0;
        $errors = [];
        $rowNumber = 1;

        DB::transaction(function () use ($handle, $header, $desaId, &$imported, &$skipped, &$errors, &$rowNumber) {
            while (($row = fgetcsv($handle)) !== false) {
                $rowNumber++;
                $data = array_combine($header, $row);

                if (empty($data['nama']) || empty($data['nik']) || empty($data['tps'])) {
                    $skipped++;
                    $errors[] = "Baris {$rowNumber}: nama/nik/tps kosong, dilewati.";

                    continue;
                }

                if (! preg_match('/^\d{16}$/', trim($data['nik']))) {
                    $skipped++;
                    $errors[] = "Baris {$rowNumber}: NIK '{$data['nik']}' tidak valid (harus 16 digit), dilewati.";

                    continue;
                }

                $tps = Tps::firstOrCreate(
                    ['desa_id' => $desaId, 'nomor' => trim($data['tps'])],
                    ['nama_lokasi' => 'TPS '.trim($data['tps'])],
                );

                $this->create($desaId, [
                    'nama' => trim($data['nama']),
                    'nik' => trim($data['nik']),
                    'tps_id' => $tps->id,
                    'rt' => trim($data['rt'] ?? ''),
                    'rw' => trim($data['rw'] ?? ''),
                ]);

                $imported++;
            }
        });

        fclose($handle);

        return ['imported' => $imported, 'skipped' => $skipped, 'errors' => $errors];
    }
}
