<?php
// ═══════════════════════════════════════════════════════════
//  FICTION IGNITION — api/lib/config.php
// ═══════════════════════════════════════════════════════════

declare(strict_types=1);

// ── Global error handler — ALWAYS return JSON, never blank ──
set_exception_handler(function (Throwable $e) {
    if (!headers_sent()) {
        header('Content-Type: application/json; charset=utf-8');
        http_response_code(500);
    }
    // Always show the real error message — you can restrict this later
    echo json_encode([
        'success' => false,
        'error'   => $e->getMessage(),
        '_trace'  => $e->getFile() . ':' . $e->getLine(),
    ]);
    exit;
});

set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline): bool {
    if (!($errno & error_reporting())) return false;
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
});

// ── Load .env ──────────────────────────────────────────────
function fi_load_env(string $path): void {
    if (!file_exists($path)) {
        error_log('Fiction Ignition: .env not found at: ' . $path);
        return;
    }
    foreach (file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
        $line = trim($line);
        if ($line === '' || $line[0] === '#' || !str_contains($line, '=')) continue;
        [$key, $val] = explode('=', $line, 2);
        $key = trim($key);
        $val = trim($val);
        if (($pos = strpos($val, '  #')) !== false) $val = trim(substr($val, 0, $pos));
        if (!array_key_exists($key, $_ENV)) { $_ENV[$key] = $val; putenv("$key=$val"); }
    }
}

// Search several candidate paths so it works regardless of server layout
foreach ([
    __DIR__ . '/../../api/.env',
    __DIR__ . '/../.env',
    dirname(__DIR__, 2) . '/.env',
    dirname(__DIR__, 3) . '/api/.env',
] as $candidate) {
    if (file_exists($candidate)) { fi_load_env($candidate); break; }
}

// ── Helpers ────────────────────────────────────────────────
function env(string $key, string $default = ''): string {
    $v = $_ENV[$key] ?? getenv($key);
    return ($v !== false && $v !== null && $v !== '') ? (string)$v : $default;
}

// ── JSON response helpers ──────────────────────────────────
function fi_json_headers(): void {
    $origin  = $_SERVER['HTTP_ORIGIN'] ?? '';
    $allowed = rtrim(env('APP_URL'), '/');
    if ($allowed && ($origin === $allowed || str_starts_with($origin, 'http://localhost') || str_starts_with($origin, 'http://127.'))) {
        header("Access-Control-Allow-Origin: $origin");
        header('Access-Control-Allow-Credentials: true');
        header('Access-Control-Allow-Headers: Content-Type, X-Requested-With');
        header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
    }
    header('Content-Type: application/json; charset=utf-8');
    if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(204); exit; }
}

function fi_json(mixed $data, int $status = 200): never {
    if (!headers_sent()) http_response_code($status);
    echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

function fi_error(string $message, int $status = 400): never {
    fi_json(['success' => false, 'error' => $message], $status);
}

function fi_ok(array $data = []): never {
    fi_json(array_merge(['success' => true], $data));
}

// ── Database (PDO singleton) ───────────────────────────────
function fi_db(): PDO {
    static $pdo = null;
    if ($pdo !== null) return $pdo;

    $host = env('DB_HOST', 'localhost');
    $port = env('DB_PORT', '3306');
    $name = env('DB_NAME');
    $user = env('DB_USER');
    $pass = env('DB_PASS');

    if (!$name) fi_error('DB_NAME is not set in your .env file.', 500);
    if (!$user) fi_error('DB_USER is not set in your .env file.', 500);

    $dsn = "mysql:host={$host};port={$port};dbname={$name};charset=utf8mb4";
    $pdo = new PDO($dsn, $user, $pass, [
        PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES   => false,
    ]);
    return $pdo;
}

// ── Tier definitions ───────────────────────────────────────
const TIERS = [
    'free'       => ['label' => 'Free',       'daily_limit' => 3,          'ad_free' => false, 'history' => false, 'export' => false, 'custom_genre' => false, 'advanced_ai' => false],
    'starter'    => ['label' => 'Starter',    'daily_limit' => 10,         'ad_free' => true,  'history' => false, 'export' => false, 'custom_genre' => false, 'advanced_ai' => false],
    'writer'     => ['label' => 'Writer',     'daily_limit' => 25,         'ad_free' => true,  'history' => true,  'export' => true,  'custom_genre' => false, 'advanced_ai' => false],
    'author_pro' => ['label' => 'Author Pro', 'daily_limit' => PHP_INT_MAX,'ad_free' => true,  'history' => true,  'export' => true,  'custom_genre' => true,  'advanced_ai' => true],
];

// ── Session auth ───────────────────────────────────────────
function fi_get_session(): ?array {
    $cookieName = env('SESSION_COOKIE_NAME', 'fi_session');
    $token = $_COOKIE[$cookieName] ?? null;
    if (!$token || strlen($token) !== 64) return null;
    $stmt = fi_db()->prepare('
        SELECT s.id as session_id, u.id, u.name, u.email, u.tier, u.email_verified, u.isAdmin
        FROM sessions s JOIN users u ON u.id = s.user_id
        WHERE s.id = ? AND s.expires_at > NOW() LIMIT 1
    ');
    $stmt->execute([$token]);
    return $stmt->fetch() ?: null;
}

function fi_require_auth(): array {
    $s = fi_get_session();
    if (!$s) fi_error('Unauthorized. Please sign in.', 401);
    return $s;
}

function fi_require_admin(): array {
    $s = fi_require_auth();
    if (!(bool)($s['isAdmin'] ?? false)) fi_error('Forbidden.', 403);
    return $s;
}

// ── UUID v4 ────────────────────────────────────────────────
function fi_uuid(): string {
    $b = random_bytes(16);
    $b[6] = chr(ord($b[6]) & 0x0f | 0x40);
    $b[8] = chr(ord($b[8]) & 0x3f | 0x80);
    return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($b), 4));
}

// ── Prompt usage ───────────────────────────────────────────
function fi_prompts_used_today(string $userId): int {
    $stmt = fi_db()->prepare('SELECT count FROM prompt_usage WHERE user_id = ? AND used_date = CURDATE()');
    $stmt->execute([$userId]);
    return (int)($stmt->fetchColumn() ?: 0);
}

function fi_increment_prompts(string $userId): void {
    fi_db()->prepare('
        INSERT INTO prompt_usage (user_id, used_date, count) VALUES (?, CURDATE(), 1)
        ON DUPLICATE KEY UPDATE count = count + 1
    ')->execute([$userId]);
}
