<?php

declare(strict_types=1);

namespace Ekdos\Relay;

use Ekdos\N8n\CachePolicy;
use Ekdos\Support\Json;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;

/**
 * Die drei Rechnungslisten des Buero-Ablaufs: anfertigen, pruefen, versenden.
 *
 * Anfertigen und Versenden waren frueher auf Svenja verdrahtet und haengen jetzt
 * am Recht "Rechnungen bearbeiten und versenden". Die Pruefliste war in der
 * Next.js-Fassung versehentlich voellig ungeschuetzt -- sie verlangt jetzt wie
 * jede andere Route eine angemeldete Sitzung.
 */
final readonly class InvoicesController extends RelayController
{
    public function createList(Request $request, Response $response): Response
    {
        $reply = $this->cachedGet(CachePolicy::InvoicesCreate, $this->n8nUrl->invoicesCreate());

        if (!$reply->ok()) {
            return $this->upstreamError($response, $reply, 'Die Rechnungsaufgaben-Schnittstelle ist nicht erreichbar.');
        }

        return Json::passthrough($response, $reply->body);
    }

    public function completeCreateTask(Request $request, Response $response): Response
    {
        $id = self::text($this->body($request), 'id');

        if ($id === '') {
            return Json::error($response, 'Die Rechnungsaufgabe fehlt.', 400);
        }

        $reply = $this->n8n->post($this->n8nUrl->invoicesCreateComplete(), ['id' => $id]);
        $decoded = $reply->decoded();

        // n8n meldet einen fachlichen Fehler auch mit HTTP 200 und ok:false.
        if (!$reply->ok() || ($decoded['ok'] ?? null) === false) {
            $message = self::text($decoded, 'error');

            return Json::error($response, $message !== '' ? $message : 'Die Rechnungsaufgabe konnte nicht abgeschlossen werden.', 502);
        }

        $this->cache->invalidate(CachePolicy::InvoicesCreate[0], CachePolicy::InvoicesReview[0]);

        return Json::passthrough($response, $reply->body);
    }

    public function reviewList(Request $request, Response $response): Response
    {
        $reply = $this->cachedGet(CachePolicy::InvoicesReview, $this->n8nUrl->invoicesReview());

        if (!$reply->ok()) {
            return $this->upstreamError($response, $reply, 'Die Prüflisten-Schnittstelle ist nicht erreichbar.');
        }

        return Json::passthrough($response, $reply->body);
    }

    public function sendList(Request $request, Response $response): Response
    {
        $reply = $this->cachedGet(CachePolicy::InvoicesSend, $this->n8nUrl->invoicesSend());

        if (!$reply->ok()) {
            return $this->upstreamError($response, $reply, 'Die Versandaufgaben-Schnittstelle ist nicht erreichbar.');
        }

        return Json::passthrough($response, $reply->body);
    }

    public function confirmSent(Request $request, Response $response): Response
    {
        $body = $this->body($request);
        $id = self::text($body, 'id');

        if ($id === '') {
            return Json::error($response, 'Die Versandaufgabe fehlt.', 400);
        }

        $reply = $this->n8n->post($this->n8nUrl->invoicesSend(), $body);

        if (!$reply->ok()) {
            return $this->upstreamError($response, $reply, 'Der Versand konnte nicht bestätigt werden.');
        }

        $this->cache->invalidate(CachePolicy::InvoicesSend[0], CachePolicy::Invoices[0]);

        return Json::passthrough($response, $reply->body);
    }

    /**
     * Die Digitale Akte zu einer Rechnungsaufgabe.
     * n8n liefert sie hier als base64 in einem JSON-Feld, nicht als Binaerrumpf.
     */
    public function digitalFile(Request $request, Response $response): Response
    {
        $taskId = $this->query($request, 'taskId');

        if ($taskId === '') {
            return Json::error($response, 'Die Rechnungsaufgabe fehlt.', 400);
        }

        $reply = $this->n8n->get($this->n8nUrl->digitalFile($taskId));
        $decoded = $reply->decoded();
        $contentBytes = self::text($decoded, 'contentBytes');

        if (!$reply->ok() || $contentBytes === '') {
            $message = self::text($decoded, 'error');

            return Json::error(
                $response,
                $message !== '' ? $message : 'Die Digitale Akte ist nicht verfügbar (HTTP ' . $reply->statusOr(502) . ').',
                502,
            );
        }

        $bytes = base64_decode($contentBytes, true);

        if ($bytes === false) {
            return Json::error($response, 'Die Digitale Akte konnte nicht gelesen werden.', 502);
        }

        $name = self::text($decoded, 'name');
        $filename = preg_replace('/[^a-zA-Z0-9._-]/', '_', $name !== '' ? $name : 'Digitale_Akte.pdf') ?? 'Digitale_Akte.pdf';

        return $this->pdfResponse($response, $bytes, $filename);
    }
}
