<?php

declare(strict_types=1);

namespace Budget;

use PDO;

final class Support
{
    public static function month(?string $month): string
    {
        $month = $month ?: date('Y-m');
        if (!preg_match('/^\d{4}-(0[1-9]|1[0-2])$/', $month)) {
            return date('Y-m');
        }
        return $month;
    }

    public static function money(float|int|string $amount, string $symbol = '$'): string
    {
        $value = (float) $amount;
        return ($value < 0 ? '-' : '') . $symbol . number_format(abs($value), 2);
    }

    public static function csrf(): string
    {
        if (empty($_SESSION['csrf_token'])) {
            $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
        }
        return (string) $_SESSION['csrf_token'];
    }

    public static function verifyCsrf(?string $token): void
    {
        if (!is_string($token) || !hash_equals(self::csrf(), $token)) {
            throw new \RuntimeException('The form expired. Please try again.');
        }
    }

    public static function flash(string $type, string $message): void
    {
        $_SESSION['flash'][] = ['type' => $type, 'message' => $message];
    }

    public static function pullFlash(): array
    {
        $messages = $_SESSION['flash'] ?? [];
        unset($_SESSION['flash']);
        return is_array($messages) ? $messages : [];
    }

    public static function audit(PDO $pdo, ?int $userId, string $action, ?string $entityType = null, ?int $entityId = null, array $metadata = []): void
    {
        $statement = $pdo->prepare(
            'INSERT INTO audit_logs (user_id, action, entity_type, entity_id, metadata)
             VALUES (:user_id, :action, :entity_type, :entity_id, :metadata)'
        );
        $statement->execute([
            'user_id' => $userId,
            'action' => $action,
            'entity_type' => $entityType,
            'entity_id' => $entityId,
            'metadata' => $metadata === [] ? null : json_encode($metadata, JSON_UNESCAPED_SLASHES),
        ]);
    }

    public static function trackVisit(PDO $pdo, string $route): void
    {
        if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
            return;
        }
        $ip = (string) ($_SERVER['REMOTE_ADDR'] ?? 'local');
        $agent = (string) ($_SERVER['HTTP_USER_AGENT'] ?? 'unknown');
        $hash = hash('sha256', date('Y-m-d') . '|' . $ip . '|' . $agent);
        $statement = $pdo->prepare('INSERT INTO visits (route, visitor_hash) VALUES (:route, :visitor_hash)');
        $statement->execute(['route' => $route, 'visitor_hash' => $hash]);
    }
}
