<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Session;
use App\Services\EncaissementService;
use App\Services\DocumentCycleService;
use Throwable;

final class EncaissementController extends Controller
{
    public function index(): void
    {
        $data = (new EncaissementService())->indexData();
        $this->view('encaissements/index', [
            'title' => 'Encaissements',
            'encaissements' => $data['encaissements'],
            'factures' => $data['factures'],
            'filters' => $data['filters'],
            'clients' => $data['clients'],
            'modesReglement' => $data['modesReglement'],
            'modeTotals' => $data['modeTotals'],
        ]);
    }

    public function receipt(): void
    {
        try {
            $this->view('encaissements/receipt', ['title' => 'Reçu d’encaissement'] + (new EncaissementService())->receiptData((int)Request::get('id', 0)));
        } catch (Throwable $exception) {
            Session::flash('error', $exception->getMessage());
            $this->redirect('encaissements');
        }
    }

    public function statement(): void
    {
        try {
            $this->view('encaissements/statement', ['title' => 'Relevé client'] + (new EncaissementService())->statementData((int)Request::get('client_id', 0), Request::all()));
        } catch (Throwable $exception) {
            Session::flash('error', $exception->getMessage());
            $this->redirect('encaissements');
        }
    }

    public function exportCsv(): void
    {
        $rows = (new EncaissementService())->exportRows(Request::all());
        header('Content-Type: text/csv; charset=UTF-8');
        header('Content-Disposition: attachment; filename="journal-encaissements-' . date('Y-m-d') . '.csv"');
        echo "\xEF\xBB\xBF";
        $out = fopen('php://output', 'wb');
        fputcsv($out, ['Date', 'Facture', 'Client', 'Mode', 'Référence', 'Montant MAD', 'Statut', 'Observations'], ';');
        foreach ($rows as $row) {
            fputcsv($out, [$row['date_encaissement'], $row['facture_numero'], $row['client_nom'], $row['mode_reglement'], $row['reference_reglement'], number_format((float)$row['montant'], 2, ',', ''), (int)$row['actif'] === 1 ? 'Actif' : 'Annulé', $row['observations']], ';');
        }
        fclose($out);
        exit;
    }

    public function create(): void
    {
        $data = (new EncaissementService())->createFormData((int) Request::get('facture_id', 0));
        $this->view('encaissements/form', ['title' => 'Nouvel encaissement'] + $data);
    }

    public function store(): void
    {
        try {
            $encaissementId = (new EncaissementService())->store(Request::all());
            $factureId = (int) Request::post('facture_id', 0);
            (new DocumentCycleService())->log('FACTURE', $factureId, 'ENCAISSEMENT', 'Paiement enregistré');
            Session::flash('success', 'Encaissement enregistré.');
            $this->redirect('factures_show&id=' . $factureId);
        } catch (Throwable $exception) {
            Session::flash('error', $exception->getMessage());
            $factureId = (int) Request::post('facture_id', 0);
            $this->redirect($factureId > 0 ? 'encaissements_create&facture_id=' . $factureId : 'encaissements_create');
        }
    }

    public function edit(): void
    {
        try {
            $data = (new EncaissementService())->editFormData((int) Request::get('id', 0));
            $this->view('encaissements/form', ['title' => 'Modifier un encaissement'] + $data);
        } catch (Throwable $exception) {
            Session::flash('error', $exception->getMessage());
            $this->redirect('encaissements');
        }
    }

    public function update(): void
    {
        $id = (int) Request::post('id', 0);
        try {
            $factureId = (new EncaissementService())->update($id, Request::all());
            (new DocumentCycleService())->log('FACTURE', $factureId, 'ENCAISSEMENT_MODIFIE', 'Paiement modifié');
            Session::flash('success', 'Encaissement modifié.');
            $this->redirect('factures_show&id=' . $factureId);
        } catch (Throwable $exception) {
            Session::flash('error', $exception->getMessage());
            $this->redirect($id > 0 ? 'encaissements_edit&id=' . $id : 'encaissements');
        }
    }

    public function cancel(): void
    {
        // Utiliser un nom explicite empêche toute confusion entre l'identifiant
        // de l'encaissement et celui de sa facture depuis le journal.
        $id = (int) Request::post('encaissement_id', 0);
        $returnTo = (string) Request::post('return_to', 'encaissements');
        $returnTo = $returnTo === 'facture' ? 'facture' : 'encaissements';
        try {
            $factureId = (new EncaissementService())->cancel($id);
            (new DocumentCycleService())->log('FACTURE', $factureId, 'ENCAISSEMENT_ANNULE', 'Paiement annulé');
            Session::flash('success', 'Le règlement a été annulé. La facture reste active et son reste dû a été recalculé.');
            $this->redirect($returnTo === 'facture' ? 'factures_show&id=' . $factureId : 'encaissements');
        } catch (Throwable $exception) {
            Session::flash('error', $exception->getMessage());
            $this->redirect('encaissements');
        }
    }
}
