<?php

use MintyPHP\Module\Helpdesk\HelpdeskAuthorizationPolicy;
use MintyPHP\Module\Helpdesk\Service\BcSoapGateway;
use MintyPHP\Router;
use MintyPHP\Support\Guard;

Guard::requireLogin();
Guard::requireAbilityOrForbidden(HelpdeskAuthorizationPolicy::ABILITY_ACCESS);

$request = requestInput();
if ($request->method() !== 'GET') {
    http_response_code(405);
    Router::json(['ok' => false, 'error' => 'method_not_allowed']);

    return;
}

$entryNo = (int) $request->query('entryNo', '0');
$ticketNo = trim((string) $request->query('ticketNo', ''));
$filename = trim((string) $request->query('filename', ''));

if ($entryNo <= 0) {
    http_response_code(400);
    Router::json(['ok' => false, 'error' => 'missing_entry_no']);

    return;
}

$soapGateway = app(BcSoapGateway::class);
$odataGateway = app(\MintyPHP\Module\Helpdesk\Service\BcODataGateway::class);

// Resolve contactNo from ticket's Current_Contact_Name for SOAP authorization
$contactNo = '';
if ($ticketNo !== '') {
    try {
        $ticket = $odataGateway->getTicket($ticketNo);
        if (is_array($ticket)) {
            $contactName = trim((string) ($ticket['Current_Contact_Name'] ?? ''));
            $customerName = trim((string) ($ticket['Company_Contact_Name'] ?? ''));
            if ($contactName !== '' && $customerName !== '') {
                $contacts = $odataGateway->getContactsForCustomer('', $customerName);
                foreach ($contacts as $contact) {
                    if (trim((string) ($contact['Name'] ?? '')) === $contactName) {
                        $contactNo = trim((string) ($contact['No'] ?? ''));
                        break;
                    }
                }
            }
        }
    } catch (\Throwable) {
        // Continue without contactNo — SOAP may still work
    }
}

try {
    $result = $soapGateway->getTicketFile($entryNo, $contactNo);
} catch (\Throwable) {
    http_response_code(502);
    Router::json(['ok' => false, 'error' => 'Failed to load file']);

    return;
}

if (!$result['ok'] || !isset($result['data'])) {
    http_response_code(404);
    Router::json(['ok' => false, 'error' => $result['error'] ?? 'File not found']);

    return;
}

$data = $result['data'];
$maxFileSize = 20 * 1024 * 1024; // 20 MB

if (strlen($data) > $maxFileSize) {
    http_response_code(413);
    Router::json(['ok' => false, 'error' => 'File too large']);

    return;
}

// Detect file type from magic bytes
$detectedType = match (true) {
    str_starts_with($data, "\x89PNG") => ['image/png', '.png'],
    str_starts_with($data, "\xFF\xD8\xFF") => ['image/jpeg', '.jpg'],
    str_starts_with($data, "GIF8") => ['image/gif', '.gif'],
    str_starts_with($data, "%PDF") => ['application/pdf', '.pdf'],
    str_starts_with($data, "PK\x03\x04") => ['application/zip', '.zip'],
    default => ['application/octet-stream', ''],
};
$mimeType = $detectedType[0];
$detectedExt = $detectedType[1];

$displayFilename = $filename !== '' ? $filename : 'attachment-' . $entryNo;
if (!str_contains($displayFilename, '.')) {
    $displayFilename .= $detectedExt;
}

$inline = trim((string) $request->query('inline', '')) === '1';
$isImage = str_starts_with($mimeType, 'image/');

header('X-Content-Type-Options: nosniff');
header('Content-Security-Policy: sandbox');

// For inline image requests, serve with correct MIME type
if ($inline && $isImage) {
    header('Content-Type: ' . $mimeType);
    header('Content-Disposition: inline; filename="' . addcslashes($displayFilename, '"\\') . '"');
    header('Content-Length: ' . strlen($data));
    header('Cache-Control: private, max-age=3600');

    while (ob_get_level()) {
        ob_end_clean();
    }

    $stream = fopen('php://memory', 'r+');
    fwrite($stream, $data);
    rewind($stream);
    fpassthru($stream);
    fclose($stream);

    return;
}

Router::download($displayFilename, $data);
