<?php
require_once dirname(__DIR__, 2) . '/security.php';

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

if (!defined('CONFIG_LOADED')) {
    http_response_code(404);
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode(['ok' => false, 'error' => 'Not found'], JSON_UNESCAPED_SLASHES);
    exit;
}

if (!isset($GLOBALS['con']) || !($GLOBALS['con'] instanceof mysqli)) {
    http_response_code(500);
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode(['ok' => false, 'error' => 'Tenant database unavailable'], JSON_UNESCAPED_SLASHES);
    exit;
}

function enrep_api_json(array $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 | JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
    exit;
}

function enrep_api_fail(int $status, string $message): void
{
    enrep_api_json(['ok' => false, 'error' => $message], $status);
}

function enrep_api_bearer_token(): string
{
    $headers = [];
    if (function_exists('getallheaders')) {
        $headers = getallheaders();
    } elseif (function_exists('apache_request_headers')) {
        $headers = apache_request_headers();
    }

    $header = $_SERVER['HTTP_AUTHORIZATION'] ?? $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ?? '';
    if ($header === '') {
        foreach ($headers as $name => $value) {
            if (strtolower((string)$name) === 'authorization') {
                $header = (string)$value;
                break;
            }
        }
    }

    if (preg_match('/Bearer\s+(.+)/i', $header, $match)) {
        return trim((string)$match[1]);
    }

    $headerKey = $_SERVER['HTTP_X_API_KEY'] ?? '';
    if ($headerKey === '') {
        foreach ($headers as $name => $value) {
            if (strtolower((string)$name) === 'x-api-key') {
                $headerKey = (string)$value;
                break;
            }
        }
    }

    if ($headerKey !== '') {
        return trim((string)$headerKey);
    }

    return '';
}

function enrep_api_require_key(): array
{
    $key = enrep_api_bearer_token();
    if ($key === '') {
        enrep_api_fail(401, 'Missing API key');
    }

    $hash = hash('sha256', $key);
    $stmt = $GLOBALS['con']->prepare("SELECT `system_api_settings` FROM `system` WHERE `id`=1 LIMIT 1");

    if (!$stmt) {
        enrep_api_fail(503, 'API access is not configured');
    }

    $stmt->execute();
    $result = $stmt->get_result();
    $row = mysqli_fetch_assoc($result);
    $stmt->close();

    $settings = json_decode((string)($row['system_api_settings'] ?? ''), true);
    if (!is_array($settings) || empty($settings['enabled']) || empty($settings['key_hash'])) {
        enrep_api_fail(503, 'API access is not enabled');
    }

    if (!hash_equals((string)$settings['key_hash'], $hash)) {
        enrep_api_fail(401, 'Invalid API key');
    }

    $now = time();
    $settings['last_used_at'] = $now;
    $settingsJson = json_encode($settings, JSON_UNESCAPED_SLASHES);
    $update = $GLOBALS['con']->prepare("UPDATE `system` SET `system_api_settings`=? WHERE `id`=1");
    if ($update) {
        $update->bind_param('s', $settingsJson);
        $update->execute();
        $update->close();
    }

    return [
        'enabled' => true,
        'key_prefix' => (string)($settings['key_prefix'] ?? ''),
    ];
}

function enrep_api_page(): array
{
    $page = enrep_request_int('page', 1);
    $perPage = enrep_request_int('per_page', 100);

    if ($page < 1) {
        $page = 1;
    }
    if ($perPage < 1) {
        $perPage = 100;
    }
    if ($perPage > 500) {
        $perPage = 500;
    }

    return [
        'page' => $page,
        'per_page' => $perPage,
        'offset' => ($page - 1) * $perPage,
    ];
}

function enrep_api_date($value): string
{
    $value = trim((string)$value);
    if ($value === '' || $value === '0') {
        return '';
    }

    if (ctype_digit($value) && (int)$value > 100000) {
        return date('Y-m-d', (int)$value);
    }

    $timestamp = strtotime($value);
    if ($timestamp !== false) {
        return date('Y-m-d', $timestamp);
    }

    return $value;
}

function enrep_api_request_date_timestamp(string $key, bool $endOfDay = false): int
{
    $raw = enrep_request_string($key, '', 40);
    if ($raw === '') {
        return 0;
    }

    if (ctype_digit($raw)) {
        return (int)$raw;
    }

    $dateFormat = strtolower(enrep_request_enum('date_format', ['uk', 'us'], 'uk'));
    $formats = $dateFormat === 'us'
        ? ['!m-d-Y', '!m/d/Y', '!Y-m-d', '!Y/m/d']
        : ['!d-m-Y', '!d/m/Y', '!Y-m-d', '!Y/m/d'];

    foreach ($formats as $format) {
        $date = DateTime::createFromFormat($format, $raw);
        $errors = DateTime::getLastErrors();
        $warningCount = is_array($errors) ? (int)($errors['warning_count'] ?? 0) : 0;
        $errorCount = is_array($errors) ? (int)($errors['error_count'] ?? 0) : 0;
        if ($date instanceof DateTime && $warningCount === 0 && $errorCount === 0) {
            if ($endOfDay) {
                $date->setTime(23, 59, 59);
            } else {
                $date->setTime(0, 0, 0);
            }
            return $date->getTimestamp();
        }
    }

    $timestamp = strtotime($raw);
    if ($timestamp === false) {
        enrep_api_fail(400, 'Invalid date for ' . $key);
    }

    return $endOfDay
        ? strtotime(date('Y-m-d 23:59:59', $timestamp))
        : strtotime(date('Y-m-d 00:00:00', $timestamp));
}

function enrep_api_unix_date_filter(string $column, string $fromKey, string $toKey): string
{
    $from = enrep_api_request_date_timestamp($fromKey, false);
    $to = enrep_api_request_date_timestamp($toKey, true);
    $sql = '';

    if ($from > 0) {
        $sql .= ' AND CAST(' . $column . ' AS UNSIGNED) >= ' . (int)$from;
    }

    if ($to > 0) {
        $sql .= ' AND CAST(' . $column . ' AS UNSIGNED) <= ' . (int)$to;
    }

    return $sql;
}

function enrep_api_unix_exact_date_filter(string $column, string $key): string
{
    $raw = enrep_request_string($key, '', 40);
    if ($raw === '') {
        return '';
    }

    $from = enrep_api_request_date_timestamp($key, false);
    $to = enrep_api_request_date_timestamp($key, true);

    if ($from <= 0 || $to <= 0) {
        return '';
    }

    return ' AND CAST(' . $column . ' AS UNSIGNED) BETWEEN ' . (int)$from . ' AND ' . (int)$to;
}

function enrep_api_nullable_string($value): string
{
    $value = trim((string)$value);
    return $value === '0' ? '' : $value;
}

function enrep_api_report_data($value)
{
    $raw = trim((string)$value);
    if ($raw === '') {
        return null;
    }

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

function enrep_api_meta(array $page, int $count): array
{
    return [
        'page' => $page['page'],
        'per_page' => $page['per_page'],
        'returned' => $count,
    ];
}
