<?php
declare(strict_types=1);

// Shared utilities: config loader, DB connection, response helpers, security (passwords & JWT)

function hw_config(): array {
    static $cfg = null;
    if ($cfg === null) {
        $cfg = require __DIR__ . '/config.php';
    }
    return $cfg;
}

function hw_db(): PDO {
    static $pdo = null;
    if ($pdo instanceof PDO) return $pdo;
    $c = hw_config()['db'];
    $dsn = sprintf('mysql:host=%s;port=%d;dbname=%s;charset=%s', $c['host'], $c['port'], $c['database'], $c['charset']);
    $pdo = new PDO($dsn, $c['username'], $c['password'], [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES => false,
    ]);
    return $pdo;
}

function hw_json($data, int $status = 200): void {
    http_response_code($status);
    header('Content-Type: application/json');
    // Basic CORS for local development
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Headers: Content-Type, Authorization');
    header('Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS');
    echo json_encode($data, JSON_UNESCAPED_SLASHES);
    exit;
}

function hw_input_json(): array {
    $raw = file_get_contents('php://input');
    $data = json_decode($raw ?: '[]', true);
    return is_array($data) ? $data : [];
}

function hw_now(): string { return gmdate('Y-m-d H:i:s'); }

// Security helpers
function hw_hash_password(string $password): string {
    return password_hash($password, PASSWORD_DEFAULT);
}

function hw_verify_password(string $password, string $hash): bool {
    return password_verify($password, $hash);
}

function hw_jwt_encode(array $payload): string {
    $cfg = hw_config()['security'];
    $header = ['alg' => 'HS256', 'typ' => 'JWT'];
    $iat = time();
    $exp = $iat + (int)$cfg['jwt_exp'];
    $payload = array_merge([
        'iss' => $cfg['jwt_issuer'],
        'iat' => $iat,
        'exp' => $exp,
    ], $payload);

    $segments = [
        hw_b64url(json_encode($header)),
        hw_b64url(json_encode($payload)),
    ];
    $signing_input = implode('.', $segments);
    $signature = hash_hmac('sha256', $signing_input, $cfg['jwt_secret'], true);
    $segments[] = hw_b64url($signature);
    return implode('.', $segments);
}

function hw_jwt_decode(string $jwt): ?array {
    $cfg = hw_config()['security'];
    $parts = explode('.', $jwt);
    if (count($parts) !== 3) return null;
    [$h64, $p64, $s64] = $parts;
    $signing_input = $h64 . '.' . $p64;
    $expected = hash_hmac('sha256', $signing_input, $cfg['jwt_secret'], true);
    $sig = hw_b64url_decode($s64);
    if (!hash_equals($expected, $sig)) return null;
    $payload = json_decode(hw_b64url_decode($p64) ?: '[]', true);
    if (!is_array($payload)) return null;
    if (($payload['exp'] ?? 0) < time()) return null;
    return $payload;
}

function hw_b64url(string $data): string {
    return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}

function hw_b64url_decode(string $data): string {
    $remainder = strlen($data) % 4;
    if ($remainder) {
        $padlen = 4 - $remainder;
        $data .= str_repeat('=', $padlen);
    }
    return base64_decode(strtr($data, '-_', '+/')) ?: '';
}

function hw_require_method(array $allowed): void {
    if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
        hw_json(['ok' => true]);
    }
    if (!in_array($_SERVER['REQUEST_METHOD'] ?? 'GET', $allowed, true)) {
        hw_json(['message' => 'Method Not Allowed'], 405);
    }
}

function hw_auth_user(): ?array {
    $auth = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
    if (preg_match('/Bearer\s+(.*)/i', $auth, $m)) {
        $token = trim($m[1]);
        $payload = hw_jwt_decode($token);
        return $payload ?: null;
    }
    // Check cookie fallback
    if (!empty($_COOKIE['hw_token'])) {
        $payload = hw_jwt_decode($_COOKIE['hw_token']);
        return $payload ?: null;
    }
    return null;
}

function hw_set_auth_cookie(string $token): void {
    $app = hw_config()['app'];
    setcookie('hw_token', $token, [
        'expires' => time() + (int)hw_config()['security']['jwt_exp'],
        'path' => $app['base_url'] ?: '/',
        'secure' => (bool)$app['cookie_secure'],
        'httponly' => true,
        'samesite' => 'Lax',
        'domain' => $app['cookie_domain'] ?: '',
    ]);
}

function hw_validate_email(string $email): bool {
    return (bool)filter_var($email, FILTER_VALIDATE_EMAIL);
}

function hw_sanitize_string(?string $s): string {
    return trim((string)$s);
}

function hw_get_auth_user(): ?array {
    $payload = hw_auth_user();
    if (!$payload) return null;
    
    // Get full user data from database
    $pdo = hw_db();
    $stmt = $pdo->prepare('SELECT u.id, u.email, u.first_name, u.last_name, u.status FROM users u WHERE u.id = ?');
    $stmt->execute([$payload['sub'] ?? 0]);
    $user = $stmt->fetch();
    
    if (!$user) return null;
    
    // Get user roles
    $stmt = $pdo->prepare('SELECT r.name FROM roles r JOIN user_roles ur ON r.id = ur.role_id WHERE ur.user_id = ?');
    $stmt->execute([$user['id']]);
    $roles = $stmt->fetchAll(PDO::FETCH_COLUMN);
    $user['roles'] = $roles;
    
    return $user;
}

function hw_require_auth(array $allowedRoles = []): void {
    $user = hw_get_auth_user();
    
    if (!$user) {
        // Redirect to login for web pages
        if (php_sapi_name() !== 'cli') {
            header('Location: /files/atasteofafricanmarketplace/login-choice.php');
            exit;
        }
        hw_json(['message' => 'Unauthorized'], 401);
    }
    
    // Check if user has required role
    if (!empty($allowedRoles)) {
        $hasRole = false;
        foreach ($allowedRoles as $role) {
            if (in_array($role, $user['roles'] ?? [], true)) {
                $hasRole = true;
                break;
            }
        }
        
        if (!$hasRole) {
            if (php_sapi_name() !== 'cli') {
                header('Location: /files/atasteofafricanmarketplace/login-choice.php');
                exit;
            }
            hw_json(['message' => 'Forbidden - Insufficient permissions'], 403);
        }
    }
}

function hw_get_content(string $section, string $default = ''): string {
    static $content_cache = [];
    
    if (!isset($content_cache[$section])) {
        $pdo = hw_db();
        $stmt = $pdo->prepare('SELECT content FROM website_content WHERE section = ?');
        $stmt->execute([$section]);
        $result = $stmt->fetchColumn();
        $content_cache[$section] = $result ?: $default;
    }
    
    return $content_cache[$section];
}
