<?php

namespace App\Imports;

use App\Models\Department;
use App\Models\District;
use App\Models\Personero;
use App\Models\PoliticalParty;
use App\Models\Province;
use App\Models\User;
use App\Models\VotingLocation;
use App\Models\VotingTable;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\WithHeadingRow;

class PersonerosImport implements ToCollection, WithHeadingRow
{
    protected array $errors = [];
    protected int $imported = 0;

    public function collection(Collection $rows)
    {
        $functions = [
            'titular' => 'titular',
            'alterno' => 'alterno',
            'de local' => 'de_local',
            'de_local' => 'de_local',
        ];

        $scopes = [
            'departamental' => 'departamental',
            'provincial' => 'provincial',
            'distrital' => 'distrital',
            'local' => 'local',
            'mesa' => 'mesa',
        ];

        foreach ($rows as $index => $row) {
            $rowNumber = $index + 2;

            $dni = trim((string) $row['dni']);
            $firstName = trim((string) ($row['nombres'] ?? ''));
            $lastName = trim((string) ($row['apellidos'] ?? ''));
            $phone = trim((string) ($row['telefono'] ?? ''));
            $functionRaw = mb_strtolower(trim((string) ($row['funcion'] ?? 'titular')));
            $function = $functions[$functionRaw] ?? 'titular';
            $scopeRaw = mb_strtolower(trim((string) ($row['ambito'] ?? 'mesa')));
            $scope = $scopes[$scopeRaw] ?? 'mesa';
            $partyName = trim((string) ($row['partido_politico'] ?? ''));
            $deptName = trim((string) ($row['departamento'] ?? ''));
            $provName = trim((string) ($row['provincia'] ?? ''));
            $distName = trim((string) ($row['distrito'] ?? ''));
            $locName = trim((string) ($row['local_de_votacion'] ?? ''));
            $tableNumber = $row['nro_mesa'] ?? null;
            $observations = trim((string) ($row['observaciones'] ?? ''));

            $validator = Validator::make(
                ['dni' => $dni, 'first_name' => $firstName, 'last_name' => $lastName],
                [
                    'dni' => 'required|string|size:8',
                    'first_name' => 'required|string|max:255',
                    'last_name' => 'required|string|max:255',
                ],
            );

            if ($validator->fails()) {
                $this->errors[] = "Fila {$rowNumber}: " . implode(', ', $validator->errors()->all());
                continue;
            }

            if (Personero::where('dni', $dni)->exists()) {
                $this->errors[] = "Fila {$rowNumber}: DNI {$dni} ya registrado";
                continue;
            }

            // Find political party
            $party = null;
            if ($partyName) {
                $party = PoliticalParty::where('name', $partyName)
                    ->orWhere('acronym', $partyName)
                    ->first();
                if (!$party) {
                    $this->errors[] = "Fila {$rowNumber}: Partido '{$partyName}' no encontrado";
                    continue;
                }
            } else {
                $this->errors[] = "Fila {$rowNumber}: Partido político requerido";
                continue;
            }

            // Resolve ubigeo
            $departmentId = null;
            $provinceId = null;
            $districtId = null;
            $votingLocationId = null;
            $votingTableId = null;

            if ($deptName) {
                $dept = Department::where('name', 'like', $deptName)->first();
                if ($dept) {
                    $departmentId = $dept->id;

                    if ($provName) {
                        $prov = Province::where('department_id', $dept->id)
                            ->where('name', 'like', $provName)->first();
                        if ($prov) {
                            $provinceId = $prov->id;

                            if ($distName) {
                                $dist = District::where('province_id', $prov->id)
                                    ->where('name', 'like', $distName)->first();
                                if ($dist) {
                                    $districtId = $dist->id;

                                    if ($locName) {
                                        $loc = VotingLocation::where('district_id', $dist->id)
                                            ->where('name', 'like', $locName)->first();
                                        if ($loc) {
                                            $votingLocationId = $loc->id;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if ($tableNumber) {
                $votingTable = VotingTable::where('table_number', (int) $tableNumber)->first();
                if ($votingTable) {
                    $votingTableId = $votingTable->id;
                    // Auto-fill ubigeo from table if not set
                    if (!$votingLocationId && $votingTable->votingLocation) {
                        $votingLocationId = $votingTable->voting_location_id;
                    }
                }
            }

            try {
                DB::transaction(function () use ($firstName, $lastName, $dni, $phone, $function, $scope, $party, $departmentId, $provinceId, $districtId, $votingLocationId, $votingTableId, $observations) {
                    $tempPassword = strtoupper(substr(bin2hex(random_bytes(4)), 0, 8));

                    $user = User::create([
                        'name' => $firstName . ' ' . $lastName,
                        'email' => $dni . '@personero.local',
                        'password' => Hash::make($tempPassword),
                        'role' => 'personero',
                        'must_change_password' => true,
                        'temp_password' => $tempPassword,
                    ]);

                    Personero::create([
                        'user_id' => $user->id,
                        'political_party_id' => $party->id,
                        'department_id' => $departmentId,
                        'province_id' => $provinceId,
                        'district_id' => $districtId,
                        'voting_location_id' => $votingLocationId,
                        'voting_table_id' => $votingTableId,
                        'first_name' => $firstName,
                        'last_name' => $lastName,
                        'dni' => $dni,
                        'phone' => $phone ?: null,
                        'function' => $function,
                        'scope' => $scope,
                        'status' => 'active',
                        'attendance' => 'pending',
                        'observations' => $observations ?: null,
                    ]);
                });

                $this->imported++;
            } catch (\Exception $e) {
                $this->errors[] = "Fila {$rowNumber}: Error al importar - {$e->getMessage()}";
            }
        }
    }

    public function getErrors(): array
    {
        return $this->errors;
    }

    public function getImportedCount(): int
    {
        return $this->imported;
    }
}
