<?php
require_once __DIR__ . '/../security.php';

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

register_shutdown_function(function (): void {
    $error = error_get_last();
    if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR], true)) {
        if (!headers_sent()) {
            http_response_code(500);
            header('Content-Type: application/json; charset=utf-8');
            header('Cache-Control: no-store');
        }
        echo json_encode([
            'ok' => false,
            'error' => 'Server error',
            'detail' => basename((string)$error['file']) . ':' . (int)$error['line'] . ' ' . (string)$error['message'],
        ], JSON_UNESCAPED_SLASHES);
    }
});

function mobile_json($payload, int $status = 200): void
{
    if (!headers_sent()) {
        http_response_code($status);
        header('Content-Type: application/json; charset=utf-8');
        header('Cache-Control: no-store');
    }
    echo json_encode($payload, JSON_UNESCAPED_SLASHES);
    exit;
}

function mobile_input(): array
{
    $raw = file_get_contents('php://input');
    $data = json_decode((string)$raw, true);
    if (is_array($data)) {
        return $data;
    }
    return $_POST;
}

function mobile_boot_tenant(array $input): void
{
    if (!defined('CONFIG_LOADED')) {
        if (!empty($input['tenant']) && empty($_REQUEST['tenant'])) {
            $_REQUEST['tenant'] = (string)$input['tenant'];
        }
        mobile_require_tenant_config();
    }

    if (!isset($GLOBALS['con']) || !($GLOBALS['con'] instanceof mysqli)) {
        mobile_json(['ok' => false, 'error' => 'Tenant database unavailable'], 500);
    }
}

function mobile_require_tenant_config(): void
{
    global $con, $master, $admin_con, $path, $dbTenant, $dbpass, $systemUser;

    $tenant = enrep_tenant_segment();
    $candidates = [];

    if ($tenant !== '') {
        $candidates[] = __DIR__ . '/../../../' . $tenant . '/config.php';
        $candidates[] = dirname(__DIR__, 2) . '/../' . $tenant . '/config.php';
        $candidates[] = dirname(__DIR__, 2) . '/' . $tenant . '/config.php';
    }
    $candidates[] = '/config.php';

    foreach ($candidates as $candidate) {
        if (is_file($candidate)) {
            require_once $candidate;
            return;
        }
    }

    mobile_json(['ok' => false, 'error' => 'Tenant config not found'], 400);
}

function mobile_token_secret(): string
{
    $parts = [
        defined('TENANT_URL') ? TENANT_URL : '',
        $GLOBALS['path'] ?? '',
        $GLOBALS['dbTenant'] ?? '',
    ];

    return hash('sha256', implode('|', $parts));
}

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

function mobile_base64url_decode(string $value): string
{
    $value = strtr($value, '-_', '+/');
    $padding = strlen($value) % 4;
    if ($padding) {
        $value .= str_repeat('=', 4 - $padding);
    }
    return (string)base64_decode($value, true);
}

function mobile_create_token(int $surveyorId, string $email): string
{
    $payload = [
        'type' => 'surveyor',
        'sid' => $surveyorId,
        'email' => $email,
        'iat' => time(),
        'exp' => time() + (60 * 60 * 24 * 7),
    ];
    $payloadEncoded = mobile_base64url_encode(json_encode($payload, JSON_UNESCAPED_SLASHES));
    $signature = hash_hmac('sha256', $payloadEncoded, mobile_token_secret());
    return $payloadEncoded . '.' . $signature;
}

function mobile_authorise(): array
{
    $header = $_SERVER['HTTP_AUTHORIZATION'] ?? $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ?? '';
    if (!preg_match('/Bearer\s+(.+)/i', $header, $match)) {
        $token = enrep_request_string('token', '', 3000);
    } else {
        $token = trim($match[1]);
    }

    if ($token === '') {
        $input = mobile_input();
        $token = trim((string)($input['token'] ?? ''));
    }

    if ($token === '' || strpos($token, '.') === false) {
        mobile_json(['ok' => false, 'error' => 'Missing token'], 401);
    }

    [$payloadEncoded, $signature] = explode('.', $token, 2);
    $expected = hash_hmac('sha256', $payloadEncoded, mobile_token_secret());
    if (!hash_equals($expected, $signature)) {
        mobile_json(['ok' => false, 'error' => 'Invalid token'], 401);
    }

    $payload = json_decode(mobile_base64url_decode($payloadEncoded), true);
    if (!is_array($payload) || ($payload['type'] ?? '') !== 'surveyor' || (int)($payload['exp'] ?? 0) < time()) {
        mobile_json(['ok' => false, 'error' => 'Expired token'], 401);
    }

    $surveyorId = (int)($payload['sid'] ?? 0);
    $stmt = $GLOBALS['con']->prepare("SELECT `id`, `email`, `forename`, `surname`, `access`, `statuslive`, `delAuth` FROM `surveyor` WHERE `id`=? LIMIT 1");
    if (!$stmt) {
        mobile_json(['ok' => false, 'error' => 'Authorisation unavailable'], 500);
    }
    $stmt->bind_param('i', $surveyorId);
    $stmt->execute();
    $result = $stmt->get_result();
    $stmt->close();
    $surveyor = mysqli_fetch_assoc($result);

    if (!$surveyor || (int)($surveyor['access'] ?? 0) === 0 || (int)($surveyor['statuslive'] ?? 0) !== 1) {
        mobile_json(['ok' => false, 'error' => 'Surveyor not active'], 403);
    }

    return $surveyor;
}

function mobile_formtypes(): array
{
    $formtypes = [];
    $enabledMaster = [];

    $res = mysqli_query($GLOBALS['con'], "SELECT `formnumber` FROM `master_formtypes` WHERE `toggle`=1");
    if ($res) {
        while ($row = mysqli_fetch_assoc($res)) {
            $enabledMaster[] = (int)$row['formnumber'];
        }
    }

    if (!empty($enabledMaster)) {
        $in = implode(',', array_map('intval', array_unique($enabledMaster)));
        $path = $GLOBALS['path'] ?? '';
        if ($path !== '') {
            $res = mysqli_query($GLOBALS['master'], "SELECT `formnumber`, `formtype`, `description`, `shortdesc`, `regs` FROM `" . mysqli_real_escape_string($GLOBALS['master'], $path) . "`.`dd_formtypes` WHERE `formnumber` IN ($in)");
        } else {
            $res = mysqli_query($GLOBALS['master'], "SELECT `formnumber`, `formtype`, `description`, `shortdesc`, `regs` FROM `dd_formtypes` WHERE `formnumber` IN ($in)");
        }
        if ($res) {
            while ($row = mysqli_fetch_assoc($res)) {
                if ((int)($row['formnumber'] ?? 0) === 101) {
                    continue;
                }
                $formtypes[(string)$row['formnumber']] = mobile_normalise_formtype($row, 'master');
            }
        }
    }

    $res = mysqli_query($GLOBALS['con'], "SELECT `formnumber`, `formtype`, `description`, `shortdesc`, `regs` FROM `dd_formtypes` ORDER BY `formnumber` ASC");
    if ($res) {
        while ($row = mysqli_fetch_assoc($res)) {
            if ((int)($row['formnumber'] ?? 0) === 101) {
                continue;
            }
            $formtypes[(string)$row['formnumber']] = mobile_normalise_formtype($row, 'tenant');
        }
    }

    ksort($formtypes, SORT_NATURAL);
    return array_values($formtypes);
}

function mobile_normalise_formtype(array $row, string $source): array
{
    $formnumber = (int)($row['formnumber'] ?? 0);
    if ($formnumber >= 5000) {
        $source = 'tenant';
    }
    $schema = mobile_report_schema_meta($formnumber, $source);

    return [
        'formnumber' => $formnumber,
        'formtype' => (string)($row['formtype'] ?? ''),
        'description' => (string)($row['description'] ?? ''),
        'shortdesc' => (string)($row['shortdesc'] ?? ''),
        'regs' => (string)($row['regs'] ?? ''),
        'source' => $source,
        'schema_version' => $schema['schema_version'],
        'schema' => $schema['schema'],
        'schema_checksum' => $schema['checksum'],
        'schema_updated_at' => $schema['updated_at'],
        'schema_origin' => $schema['origin'],
    ];
}

function mobile_report_schema_meta(int $formnumber, string $source): array
{
    $typeDir = ($source === 'master' && $formnumber < 5000) ? 'app_default_reports' : 'app_custom_reports';
    $filename = $formnumber . '.json';
    $paths = [];

    if (defined('TENANT_DEFER')) {
        $paths[] = rtrim((string)TENANT_DEFER, '/\\') . '/output/' . $typeDir . '/' . $filename;
    }

    $paths[] = __DIR__ . '/schema_templates/' . $typeDir . '/' . $filename;

    foreach ($paths as $path) {
        if (!is_file($path)) {
            continue;
        }

        $raw = file_get_contents($path);
        $schema = json_decode((string)$raw, true);
        if (!is_array($schema)) {
            continue;
        }

        return [
            'schema_version' => (int)($schema['schema_version'] ?? 1),
            'schema' => $schema,
            'checksum' => hash('sha256', (string)$raw),
            'updated_at' => filemtime($path) ?: 0,
            'origin' => strpos($path, '/schema_templates/') !== false || strpos($path, '\\schema_templates\\') !== false ? 'core_fallback' : 'tenant_output',
        ];
    }

    return [
        'schema_version' => 1,
        'schema' => null,
        'checksum' => '',
        'updated_at' => 0,
        'origin' => '',
    ];
}
