<?php
/*
 * RoomZ Outlook add-in API bootstrap
 * Compatible with PHP 7.4+.
 */

declare(strict_types=1);

ini_set('display_errors', '0');
error_reporting(E_ALL);

require_once __DIR__ . '/../../../../includes/bootstrap.php';
require_once __DIR__ . '/../../lib.php';

header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache');
header('X-Content-Type-Options: nosniff');

if (!function_exists('api_json')) {
    function api_json(array $data, int $status = 200): void
    {
        http_response_code($status);

        $json = json_encode(
            $data,
            JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
        );

        if ($json === false) {
            $json = '{"ok":false,"message":"Could not encode the API response."}';
        }

        echo $json;
        exit;
    }
}

if (!function_exists('api_input')) {
    function api_input(): array
    {
        $raw = (string)file_get_contents('php://input');
        if ($raw === '') {
            return $_POST;
        }

        $decoded = json_decode($raw, true);
        return is_array($decoded) ? $decoded : $_POST;
    }
}

if (!function_exists('api_bearer')) {
    function api_bearer(): string
    {
        $header = '';

        if (!empty($_SERVER['HTTP_AUTHORIZATION'])) {
            $header = (string)$_SERVER['HTTP_AUTHORIZATION'];
        } elseif (!empty($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
            $header = (string)$_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
        } elseif (function_exists('getallheaders')) {
            $headers = getallheaders();
            if (is_array($headers)) {
                $header = (string)($headers['Authorization'] ?? $headers['authorization'] ?? '');
            }
        }

        return preg_match('/^Bearer\s+(.+)$/i', trim($header), $matches)
            ? trim((string)$matches[1])
            : '';
    }
}

if (!function_exists('api_table_exists')) {
    function api_table_exists(PDO $pdo, string $table): bool
    {
        $stmt = $pdo->prepare(
            "SELECT COUNT(*)
             FROM information_schema.tables
             WHERE table_schema = DATABASE()
               AND table_name = :table_name"
        );
        $stmt->execute([':table_name' => $table]);
        return (int)$stmt->fetchColumn() > 0;
    }
}

if (!function_exists('api_install_schema')) {
    function api_install_schema(PDO $pdo): void
    {
        $pdo->exec("
            CREATE TABLE IF NOT EXISTS communication_outlook_tokens (
                id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
                token_hash CHAR(64) NOT NULL,
                user_id BIGINT UNSIGNED NOT NULL,
                order_id BIGINT UNSIGNED NOT NULL,
                expires_at DATETIME NOT NULL,
                used_at DATETIME NULL,
                created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                created_ip VARCHAR(45) NULL,
                PRIMARY KEY (id),
                UNIQUE KEY uq_comm_outlook_token_hash (token_hash),
                KEY idx_comm_outlook_order (order_id),
                KEY idx_comm_outlook_expiry (expires_at)
            ) ENGINE=InnoDB
              DEFAULT CHARACTER SET utf8mb4
              COLLATE utf8mb4_general_ci
        ");

        $pdo->exec("
            CREATE TABLE IF NOT EXISTS communication_addin_sessions (
                id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
                session_hash CHAR(64) NOT NULL,
                user_id BIGINT UNSIGNED NOT NULL,
                order_id BIGINT UNSIGNED NOT NULL,
                expires_at DATETIME NOT NULL,
                revoked_at DATETIME NULL,
                created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                last_used_at DATETIME NULL,
                PRIMARY KEY (id),
                UNIQUE KEY uq_comm_addin_session_hash (session_hash),
                KEY idx_comm_addin_order (order_id),
                KEY idx_comm_addin_expiry (expires_at)
            ) ENGINE=InnoDB
              DEFAULT CHARACTER SET utf8mb4
              COLLATE utf8mb4_general_ci
        ");

        $pdo->exec("
            CREATE TABLE IF NOT EXISTS communication_log (
                id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
                order_id BIGINT UNSIGNED NOT NULL,
                user_id BIGINT UNSIGNED NULL,
                channel VARCHAR(30) NOT NULL,
                action VARCHAR(60) NOT NULL,
                recipient VARCHAR(255) NULL,
                subject VARCHAR(255) NULL,
                document_type VARCHAR(40) NULL,
                document_name VARCHAR(255) NULL,
                status VARCHAR(30) NOT NULL DEFAULT 'completed',
                notes TEXT NULL,
                created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                PRIMARY KEY (id),
                KEY idx_communication_order (order_id, created_at),
                KEY idx_communication_channel (channel, created_at)
            ) ENGINE=InnoDB
              DEFAULT CHARACTER SET utf8mb4
              COLLATE utf8mb4_general_ci
        ");
    }
}

if (!function_exists('api_session')) {
    function api_session(PDO $pdo, string $suppliedToken = ''): array
    {
        api_install_schema($pdo);

        /*
         * Some Apache/FastCGI/shared-hosting configurations remove the
         * Authorization header before PHP receives it. Prefer an explicitly
         * supplied JSON session token, then fall back to Bearer authentication.
         */
        $token = trim($suppliedToken);
        if ($token === '') {
            $token = api_bearer();
        }

        if ($token === '') {
            api_json([
                'ok' => false,
                'message' => 'Missing add-in session.'
            ], 401);
        }

        $stmt = $pdo->prepare("
            SELECT *
            FROM communication_addin_sessions
            WHERE session_hash = :session_hash
              AND revoked_at IS NULL
              AND expires_at > NOW()
            LIMIT 1
        ");
        $stmt->execute([
            ':session_hash' => comm_hash_token($token),
        ]);

        $session = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$session) {
            api_json([
                'ok' => false,
                'message' => 'The prepared Outlook session expired. Return to RoomZ and prepare it again.'
            ], 401);
        }

        $pdo->prepare("
            UPDATE communication_addin_sessions
            SET last_used_at = NOW()
            WHERE id = :id
        ")->execute([
            ':id' => (int)$session['id'],
        ]);

        return $session;
    }
}

set_exception_handler(function (Throwable $exception): void {
    error_log(
        'RoomZ Outlook API fatal error: ' .
        $exception->getMessage() .
        ' in ' . $exception->getFile() .
        ':' . $exception->getLine()
    );

    api_json([
        'ok' => false,
        'message' => 'RoomZ Outlook API error: ' . $exception->getMessage(),
    ], 500);
});
