<?php

declare(strict_types=1);

namespace App\Services;

use App\Repositories\EncaissementRepository;
use App\Repositories\ModeReglementRepository;
use RuntimeException;

final class EncaissementService extends BaseService
{
    public function __construct(
        private readonly EncaissementRepository $encaissements = new EncaissementRepository(),
        private readonly ModeReglementRepository $modesReglement = new ModeReglementRepository(),
    ) {
    }

    public function indexData(): array
    {
        $filters = $this->filters($_GET);
        $rows = $this->encaissements->journal($filters);
        return [
            'encaissements' => $rows,
            'factures' => $this->encaissements->unpaidInvoices(),
            'filters' => $filters,
            'clients' => $this->encaissements->paymentClients(),
            'modesReglement' => $this->modesReglement->allActive(),
            'modeTotals' => $this->encaissements->modeTotals($rows),
        ];
    }

    public function receiptData(int $id): array
    {
        $payment = $this->encaissements->find($id);
        if (!$payment) throw new RuntimeException('Encaissement introuvable.');
        return ['encaissement' => $payment];
    }

    public function statementData(int $clientId, array $input): array
    {
        if ($clientId <= 0) throw new RuntimeException('Veuillez sélectionner un client.');
        $client = $this->encaissements->clientSummary($clientId);
        if (!$client) throw new RuntimeException('Client introuvable.');
        $filters = $this->filters($input);
        $rows = $this->encaissements->clientStatement($clientId, $filters);
        return ['client' => $client, 'encaissements' => $rows, 'filters' => $filters, 'modeTotals' => $this->encaissements->modeTotals($rows)];
    }

    public function exportRows(array $input): array
    {
        return $this->encaissements->journal($this->filters($input));
    }

    private function filters(array $input): array
    {
        $status = (string)($input['statut'] ?? 'tous');
        if (!in_array($status, ['tous', 'actifs', 'annules'], true)) $status = 'tous';
        return [
            'date_from' => preg_match('/^\d{4}-\d{2}-\d{2}$/', (string)($input['date_from'] ?? '')) ? (string)$input['date_from'] : '',
            'date_to' => preg_match('/^\d{4}-\d{2}-\d{2}$/', (string)($input['date_to'] ?? '')) ? (string)$input['date_to'] : '',
            'client_id' => max(0, (int)($input['client_id'] ?? 0)),
            'facture' => trim((string)($input['facture'] ?? '')),
            'mode' => trim((string)($input['mode'] ?? '')),
            'statut' => $status,
        ];
    }

    public function createFormData(int $factureId = 0): array
    {
        return [
            'factureId' => $factureId,
            'factures' => $this->encaissements->unpaidInvoices(),
            'modesReglement' => $this->modesReglement->allActive(),
            'encaissement' => null,
            'isEdit' => false,
        ];
    }

    public function editFormData(int $id): array
    {
        $encaissement = $this->encaissements->find($id);
        if (!$encaissement) {
            throw new RuntimeException('Encaissement introuvable.');
        }
        if ((int)$encaissement['actif'] !== 1) {
            throw new RuntimeException('Un encaissement annulé ne peut plus être modifié.');
        }

        return [
            'factureId' => (int)$encaissement['facture_id'],
            'factures' => [],
            'modesReglement' => $this->modesReglement->allActive(),
            'encaissement' => $encaissement,
            'isEdit' => true,
        ];
    }

    public function store(array $data): int
    {
        return $this->encaissements->store($data);
    }

    public function update(int $id, array $data): int
    {
        return $this->encaissements->update($id, $data);
    }

    public function cancel(int $id): int
    {
        return $this->encaissements->cancel($id);
    }
}
