<?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;

final readonly class OffersController extends RelayController
{
    public function index(Request $request, Response $response): Response
    {
        $reply = $this->cachedGet(CachePolicy::Offers, $this->n8nUrl->offers());

        if (!$reply->ok()) {
            return $this->upstreamError($response, $reply, 'Die Angebote konnten nicht aus n8n geladen werden.');
        }

        return $this->listResponse($response, $reply, 'offers', 'offers');
    }

    /** Versandstatus, Beauftragung und Ruecksetzung laufen ueber dieselbe Route. */
    public function update(Request $request, Response $response): Response
    {
        $body = $this->body($request);
        $id = self::text($body, 'id');
        $action = self::text($body, 'action');

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

        return match ($action) {
            'versendet' => $this->markSent($response, $body, $id),
            'beauftragt' => $this->markCommissioned($response, $body, $id),
            'zuruecksetzen' => $this->reset($response, $id),
            default => Json::error($response, 'Unbekannte Angebotsaktion.', 400),
        };
    }

    /** Vormals: nur Sascha. */
    public function delete(Request $request, Response $response): Response
    {
        $id = self::text($this->body($request), 'id');

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

        $reply = $this->n8n->post($this->n8nUrl->offers('/loeschen'), ['id' => $id]);

        if (!$reply->ok()) {
            return $this->upstreamError($response, $reply, 'Das Angebot konnte nicht gelöscht werden.');
        }

        $this->cache->invalidate(CachePolicy::Offers[0]);

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

    private function markSent(Response $response, array $body, string $id): Response
    {
        $shipping = self::text($body, 'versandart');

        if ($shipping !== 'E-Mail' && $shipping !== 'Post') {
            return Json::error($response, 'Bitte E-Mail oder Post auswählen.', 400);
        }

        $reply = $this->n8n->post($this->n8nUrl->offers('/versendet'), ['id' => $id, 'versandart' => $shipping]);

        if (!$reply->ok()) {
            return $this->upstreamError($response, $reply, 'Der Versandstatus konnte nicht gespeichert werden.');
        }

        $this->cache->invalidate(CachePolicy::Offers[0]);

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

    private function markCommissioned(Response $response, array $body, string $id): Response
    {
        $reply = $this->n8n->post($this->n8nUrl->offers('/beauftragt'), [
            'id' => $id,
            'angebot_nummer' => self::text($body, 'angebot_nummer'),
            'kunde' => self::text($body, 'kunde'),
            'objekt_zusatz' => self::text($body, 'objekt_zusatz'),
        ]);

        if (!$reply->ok()) {
            return $this->upstreamError($response, $reply, 'Die Beauftragung konnte nicht gespeichert werden.');
        }

        // Eine Beauftragung erzeugt in n8n eine Rechnungsaufgabe, deshalb faellt
        // auch der Rechnungs-Cache.
        $this->cache->invalidate(CachePolicy::Offers[0], CachePolicy::InvoicesCreate[0]);

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

    /** Geschuetzte Ruecksetzung: n8n verlangt hier das geteilte Geheimnis. */
    private function reset(Response $response, string $id): Response
    {
        $secret = $this->invoiceSyncSecret();

        if ($secret === '') {
            return Json::error($response, 'Die geschützte Rücksetzung ist noch nicht eingerichtet.', 503);
        }

        $reply = $this->n8n->post($this->n8nUrl->offers('/zuruecksetzen'), ['id' => $id], ['x-ekdos-invoice-sync' => $secret]);

        if (!$reply->ok()) {
            return $this->upstreamError($response, $reply, 'Der Versandstatus konnte nicht zurückgesetzt werden.');
        }

        $this->cache->invalidate(CachePolicy::Offers[0]);

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