<?php

require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../../config/helpers.php';
require_once __DIR__ . '/../../config/app.php';
require_once __DIR__ . '/InboxRepository.php';
require_once __DIR__ . '/InboxService.php';

handleCors();

$method = getMethod();
$route = getApiRouteSegments();
$resource = strtolower($route[0] ?? '');
$action = strtolower($route[1] ?? 'session');
$subAction = strtolower($route[2] ?? '');
$detailAction = strtolower($route[3] ?? '');

if ($resource !== 'inbox') {
    jsonResponse(false, 'inbox.not_found', ['segments' => $route], 404);
}

global $pdo;
$config = require __DIR__ . '/../../config/app.php';
$repo = new InboxRepository($pdo);
$service = new InboxService($pdo, $config);

function inboxContextPayload(array $context, array $config): array
{
    $inbox = $context['inbox'];
    $inboxes = $context['inboxes'] ?? [$inbox];

    $payload = [
        'mode' => $context['mode'],
        'email_address' => $inbox['email_address'] ?? null,
        'expires_at' => $inbox['expires_at'] ?? null,
        'is_expired' => inboxIsExpired($inbox),
        'inbox' => [
            'id' => isset($inbox['id']) ? (int) $inbox['id'] : null,
            'type' => $inbox['type'] ?? null,
            'email_address' => $inbox['email_address'] ?? null,
            'expires_at' => $inbox['expires_at'] ?? null,
            'is_expired' => inboxIsExpired($inbox),
            'is_active' => isset($inbox['is_active']) ? (int) $inbox['is_active'] : null,
        ],
        'inboxes' => array_map(static function (array $item): array {
            return [
                'id' => isset($item['id']) ? (int) $item['id'] : null,
                'type' => $item['type'] ?? null,
                'email_address' => $item['email_address'] ?? null,
                'expires_at' => $item['expires_at'] ?? null,
                'is_expired' => inboxIsExpired($item),
                'is_active' => isset($item['is_active']) ? (int) $item['is_active'] : null,
            ];
        }, $inboxes),
        'user' => $context['user'] ?? null,
    ];

    if (($context['mode'] ?? '') === 'guest') {
        $payload['guest_access_token'] = (string) ($inbox['access_token'] ?? getGuestInboxAccessToken($config) ?? '');
    }

    return $payload;
}

function accessibleInboxIds(array $context): array
{
    $ids = [];
    foreach (($context['inboxes'] ?? []) as $item) {
        $id = (int) ($item['id'] ?? 0);
        if ($id > 0) {
            $ids[] = $id;
        }
    }

    if (empty($ids) && !empty($context['inbox']['id'])) {
        $ids[] = (int) $context['inbox']['id'];
    }

    return array_values(array_unique($ids));
}

function inboxIsExpired(array $inbox): bool
{
    if (empty($inbox['expires_at'])) {
        return false;
    }

    $expiresAt = strtotime((string) $inbox['expires_at']);
    return $expiresAt > 0 && $expiresAt <= time();
}


if ($action === 'discard-guest' && $method === 'POST') {
    $discarded = $service->discardCurrentGuestInbox();
    jsonResponse(true, 'inbox.guest_discarded', [
        'discarded_inbox' => $discarded ? [
            'id' => isset($discarded['id']) ? (int) $discarded['id'] : null,
            'email_address' => $discarded['email_address'] ?? null,
        ] : null,
    ]);
}

$context = $service->getCurrentInboxContext();
$inbox = $context['inbox'];
$inboxId = (int) ($inbox['id'] ?? 0);
$allowedInboxIds = accessibleInboxIds($context);

if (($context['mode'] ?? '') === 'guest' && !empty($inbox['access_token'])) {
    header('X-Guest-Inbox-Token: ' . $inbox['access_token']);
}

if ($action === 'session' && $method === 'GET') {
    jsonResponse(true, 'inbox.session_success', inboxContextPayload($context, $config));
}

if ($action === 'messages' && $method === 'GET' && $subAction === '') {
    $page = max(1, (int) ($_GET['page'] ?? 1));
    $limit = max(1, min(100, (int) ($_GET['limit'] ?? 25)));
    $result = $repo->listMessagesForInboxIds($allowedInboxIds, $page, $limit);
    http_response_code(200);
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode([
        'ok' => true,
        'message' => 'inbox.messages_list_success',
        'data' => $result['items'],
        'pagination' => $result['pagination'],
        'meta' => inboxContextPayload($context, $config),
    ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

if ($action === 'messages' && ctype_digit((string) $subAction)) {
    $messageId = (int) $subAction;
    $message = $repo->getMessageByIdForInboxIds($allowedInboxIds, $messageId);
    if (!$message) {
        jsonResponse(false, 'inbox.message_not_found', ['message_id' => $messageId], 404);
    }

    if ($method === 'GET') {
        $repo->markMessageReadStateForInboxIds($allowedInboxIds, $messageId, 1);
        $attachments = $repo->getMessageAttachmentsByMessageId($messageId);
        if (function_exists('replaceInlineCidSources')) {
            $message['html_body'] = replaceInlineCidSources($message['html_body'] ?? null, $attachments, (int) ($message['mailbox_id'] ?? 0), $messageId);
        }
        $message['attachments'] = $attachments;
        jsonResponse(true, 'inbox.message_show_success', $message);
    }

    if ($method === 'POST') {
        if ($detailAction === 'read') {
            $repo->markMessageReadStateForInboxIds($allowedInboxIds, $messageId, 1);
            jsonResponse(true, 'inbox.message_marked_read', ['id' => $messageId]);
        }
        if ($detailAction === 'unread') {
            $repo->markMessageReadStateForInboxIds($allowedInboxIds, $messageId, 0);
            jsonResponse(true, 'inbox.message_marked_unread', ['id' => $messageId]);
        }
        if ($detailAction === 'star') {
            $repo->markMessageStarStateForInboxIds($allowedInboxIds, $messageId, 1);
            jsonResponse(true, 'inbox.message_starred', ['id' => $messageId]);
        }
        if ($detailAction === 'unstar') {
            $repo->markMessageStarStateForInboxIds($allowedInboxIds, $messageId, 0);
            jsonResponse(true, 'inbox.message_unstarred', ['id' => $messageId]);
        }
    }
}

if ($action === 'cleanup-expired' && $method === 'POST') {
    $count = $repo->cleanupExpiredGuestInboxes();
    jsonResponse(true, 'inbox.cleanup_success', ['updated_count' => $count]);
}

jsonResponse(false, 'inbox.not_found', ['segments' => $route], 404);
