<?php

declare(strict_types=1);

namespace ApiModel\Service;

use ApiModel\Domain\Repository\PagoFerreteriaRepositoryInterface;
use ApiModel\Infrastructure\Persistence\Database;
use ApiModel\Shared\Exceptions\BadRequestException;
use ApiModel\Shared\Exceptions\NotFoundException;

final class PagoFerreteriaService
{
    public function __construct(
        private readonly PagoFerreteriaRepositoryInterface $pagos
    ) {}

    /** @return list<array<string, mixed>> */
    public function listPagos(?string $ferreteriaId = null): array
    {
        $rows = ($ferreteriaId !== null && trim($ferreteriaId) !== '')
            ? $this->pagos->listAllByFerreteria($ferreteriaId)
            : $this->pagos->listAll();

        return array_map($this->mapRow(...), $rows);
    }

    /** @return array<string, mixed> */
    public function createPago(array $data, ?string $actorUserId): array
    {
        $ferreteriaId = trim((string) ($data['ferreteria_id'] ?? ''));
        $monto = (float) ($data['monto'] ?? 0.0);
        $fechaPago = trim((string) ($data['fecha_pago'] ?? ''));
        $referencia = isset($data['referencia']) && trim((string) $data['referencia']) !== '' ? trim((string) $data['referencia']) : null;
        $descripcion = isset($data['descripcion']) && trim((string) $data['descripcion']) !== '' ? trim((string) $data['descripcion']) : null;

        if ($ferreteriaId === '') {
            throw new BadRequestException('La ferretería es obligatoria');
        }
        if ($monto <= 0) {
            throw new BadRequestException('El monto debe ser mayor a cero');
        }
        if ($fechaPago === '') {
            $fechaPago = date('Y-m-d');
        }

        $id = Database::uuid();
        $this->pagos->insert($id, $ferreteriaId, $monto, $fechaPago, $referencia, $descripcion, $actorUserId);

        $row = $this->pagos->findById($id);
        if (!$row) {
            throw new NotFoundException('Pago no encontrado tras la creación');
        }

        return $this->mapRow($row);
    }

    public function deletePago(string $id): void
    {
        $row = $this->pagos->findById($id);
        if (!$row) {
            throw new NotFoundException('Pago no encontrado');
        }
        $this->pagos->delete($id);
    }

    /** @param array<string, mixed> $row @return array<string, mixed> */
    private function mapRow(array $row): array
    {
        return [
            'id' => $row['id'],
            'ferreteria_id' => $row['ferreteria_id'],
            'ferreteria_nombre' => $row['ferreteria_nombre'] ?? '',
            'monto' => (float) $row['monto'],
            'fecha_pago' => $row['fecha_pago'],
            'referencia' => $row['referencia'],
            'descripcion' => $row['descripcion'],
            'registrado_por' => $row['registrado_por'],
            'registrado_por_nombre' => $row['registrado_por_nombre'] ?? '',
            'created_at' => $row['created_at'],
        ];
    }
}
