<?php

declare(strict_types=1);

namespace Plugin\tnt_mcp\adminmenu\Controller;

use JTL\Helpers\Form;
use JTL\Helpers\Request;
use Plugin\tnt_mcp\src\Mcp\Admin\TokenAuditActions;
use Plugin\tnt_mcp\src\Mcp\Admin\TokenAuditOverview;

/**
 * "Tokens & Audit" tab: lists the legacy static bearer tokens, the registered OAuth clients, the
 * issued OAuth access tokens (masked), and the audit log — across the legacy and OAuth tables. No
 * secret is ever surfaced (see {@see TokenAuditOverview}).
 *
 * The tab also lets an admin REVOKE entries: static tokens, OAuth clients (cascading their
 * codes/tokens) and individual OAuth access tokens. Deletes are POST-only and gated on the JTL
 * backend XSRF token; access tokens are targeted by a SHA-256 handle so the raw value never leaves
 * the server (see {@see TokenAuditActions}).
 */
final class TokensAudit extends BaseAdminController
{
    public function render(): void
    {
        if (!$this->isAdmin()) {
            $this->notLoggedInNotice();

            return;
        }

        $flash = $this->handlePostAction();

        // Guarantee the backend XSRF token exists so the delete forms can carry it.
        Form::getTokenInput();

        $overview = new TokenAuditOverview($this->db());

        echo $this->fetch('tokens-audit.tpl', [
            'legacyTokens' => $overview->legacyTokens(),
            'oauthClients' => $overview->oauthClients(),
            'oauthTokens'  => $overview->oauthTokens(),
            'auditEntries' => $overview->auditEntries(),
            'flash'        => $flash,
            'jtlToken'     => $_SESSION['jtl_token'] ?? '',
        ]);
    }

    /**
     * Process a delete POST, if present. Returns a flash message
     * (['type' => 'success'|'danger', 'text' => string]) or null when there is nothing to do.
     *
     * @return array{type: string, text: string}|null
     */
    private function handlePostAction(): ?array
    {
        $action = (string)Request::postVar('tntMcpAction', '');
        if ($action === '') {
            return null;
        }

        if (!Form::validateToken()) {
            return ['type' => 'danger', 'text' => $this->text([
                'de' => 'Sicherheits-Token ungültig. Bitte erneut versuchen.',
                'en' => 'Security token invalid. Please try again.',
            ])];
        }

        $actions = new TokenAuditActions($this->db());

        try {
            switch ($action) {
                case 'delete_legacy':
                    $affected = $actions->deleteLegacyToken((int)Request::postVar('kToken', 0));

                    return $affected > 0
                        ? ['type' => 'success', 'text' => $this->text([
                            'de' => 'Statischer Token gelöscht.',
                            'en' => 'Static token deleted.',
                        ])]
                        : ['type' => 'danger', 'text' => $this->text([
                            'de' => 'Token nicht gefunden.',
                            'en' => 'Token not found.',
                        ])];

                case 'delete_client':
                    $affected = $actions->deleteOauthClient((string)Request::postVar('clientId', ''));

                    return $affected > 0
                        ? ['type' => 'success', 'text' => $this->text([
                            'de' => 'OAuth-Client inkl. zugehöriger Tokens gelöscht.',
                            'en' => 'OAuth client deleted, including its tokens.',
                        ])]
                        : ['type' => 'danger', 'text' => $this->text([
                            'de' => 'Client nicht gefunden.',
                            'en' => 'Client not found.',
                        ])];

                case 'delete_token':
                    $affected = $actions->deleteOauthAccessTokenByRef((string)Request::postVar('ref', ''));

                    return $affected > 0
                        ? ['type' => 'success', 'text' => $this->text([
                            'de' => 'OAuth-Access-Token widerrufen.',
                            'en' => 'OAuth access token revoked.',
                        ])]
                        : ['type' => 'danger', 'text' => $this->text([
                            'de' => 'Access-Token nicht gefunden.',
                            'en' => 'Access token not found.',
                        ])];

                default:
                    return null;
            }
        } catch (\Throwable $e) {
            return ['type' => 'danger', 'text' => $this->text([
                'de' => 'Löschen fehlgeschlagen: ',
                'en' => 'Deletion failed: ',
            ]) . $e->getMessage()];
        }
    }
}
