<?php

declare(strict_types=1);

namespace App\Controllers;

use App\ApiClient\AdminClient;
use App\ApiClient\ApiException;
use App\Auth\SessionManager;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Views\Twig;

/**
 * `/app/audit` — filterable audit log list. Filters are passed
 * through to the api as-is; pagination is done page+page_size in
 * the query string. The page tolerates a partial outage by
 * rendering an empty state with the api error message.
 */
final class AuditController
{
    use CrudControllerSupport;

    private const ALLOWED_ACTIONS = [
        'reporter.created', 'reporter.updated', 'reporter.deleted',
        'reporter.audit_toggled',
        'consumer.created', 'consumer.updated', 'consumer.deleted',
        'consumer.audit_toggled',
        'token.created', 'token.revoked',
        'policy.created', 'policy.updated', 'policy.deleted',
        'category.created', 'category.updated', 'category.deleted',
        'manual_block.created', 'manual_block.deleted',
        'allowlist.created', 'allowlist.deleted',
        'job.triggered',
    ];

    private const ALLOWED_KINDS = ['user', 'admin-token', 'reporter', 'consumer', 'system'];

    public function __construct(
        private readonly Twig $twigEngine,
        private readonly SessionManager $sessionManager,
        private readonly AdminClient $admin,
    ) {
    }

    protected function twig(): Twig
    {
        return $this->twigEngine;
    }

    protected function sessions(): SessionManager
    {
        return $this->sessionManager;
    }

    public function index(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
    {
        if (($redirect = $this->requireUser($request, $response)) !== null) {
            return $redirect;
        }

        $user = $this->sessions()->getUser();
        // Guard for static analysis — requireUser bounced if null already.
        if ($user === null) {
            return $response->withStatus(302)->withHeader('Location', '/login');
        }

        $params = $request->getQueryParams();
        $filters = [
            'actor_kind' => self::clean($params['actor_kind'] ?? null),
            'actor_id' => self::clean($params['actor_id'] ?? null),
            'action' => self::clean($params['action'] ?? null),
            'entity_type' => self::clean($params['entity_type'] ?? null),
            'entity_id' => self::clean($params['entity_id'] ?? null),
            'subject_kind' => self::clean($params['subject_kind'] ?? null),
            'subject_id' => self::clean($params['subject_id'] ?? null),
            'from' => self::clean($params['from'] ?? null),
            'to' => self::clean($params['to'] ?? null),
        ];
        $page = isset($params['page']) && ctype_digit((string) $params['page']) ? max(1, (int) $params['page']) : 1;
        $pageSize = 50;

        $list = null;
        $error = null;
        try {
            $list = $this->admin->listAuditLog($user->userId, $filters, $page, $pageSize);
        } catch (ApiException $e) {
            $error = 'API error: ' . $e->getMessage();
        }

        return $this->twigEngine->render($response, 'pages/audit/index.twig', [
            'active_section' => 'audit',
            'list' => $list,
            'page' => $page,
            'page_size' => $pageSize,
            'filters' => $filters,
            'allowed_actions' => self::ALLOWED_ACTIONS,
            'allowed_kinds' => self::ALLOWED_KINDS,
            'error' => $error,
        ]);
    }

    private static function clean(mixed $v): ?string
    {
        if (!is_string($v)) {
            return null;
        }
        $trimmed = trim($v);

        return $trimmed === '' ? null : $trimmed;
    }
}
