<?php
declare(strict_types=1);

require_once __DIR__ . DIRECTORY_SEPARATOR . 'auth.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'spa_store_sync.php';

fate_admin_require_login_api();

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    echo json_encode(['ok' => false, 'error' => 'method_not_allowed'], JSON_UNESCAPED_UNICODE);
    exit;
}

$pdo = null;
try {
    require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'pdo.php';
    if (isset($GLOBALS['pdo']) && $GLOBALS['pdo'] instanceof PDO) {
        $pdo = $GLOBALS['pdo'];
    }
} catch (Throwable $e) {
    http_response_code(500);
    echo json_encode(['ok' => false, 'error' => 'db', 'message' => $e->getMessage()], JSON_UNESCAPED_UNICODE);
    exit;
}

if (!$pdo instanceof PDO) {
    http_response_code(500);
    echo json_encode(['ok' => false, 'error' => 'no_pdo'], JSON_UNESCAPED_UNICODE);
    exit;
}

$raw = file_get_contents('php://input');
$in = json_decode($raw !== false && $raw !== '' ? $raw : '{}', true);
if (!is_array($in)) {
    $in = [];
}
if ($in === [] && isset($_POST['action'])) {
    $in = $_POST;
}

if (!fate_admin_csrf_check(isset($in['csrf']) ? (string) $in['csrf'] : '')) {
    http_response_code(403);
    echo json_encode(['ok' => false, 'error' => 'csrf'], JSON_UNESCAPED_UNICODE);
    exit;
}

$sessionKey = 'fate_spa_sync_job_v2';
$imageSessionKey = 'fate_spa_image_sync_job_v1';
$action = isset($in['action']) ? (string) $in['action'] : '';

switch ($action) {
    case 'start':
        $gate = fate_spa_sync_api_key_gate();
        if (!$gate['ok']) {
            $userMsg = fate_spa_sync_gate_user_message($gate);
            echo json_encode([
                'ok' => false,
                'error' => (string) ($gate['error'] ?? 'api_key_blocked'),
                'hint_zh' => $userMsg,
                'message' => $userMsg,
                'finished' => true,
            ], JSON_UNESCAPED_UNICODE);
            exit;
        }
        $force = !empty($in['force']);
        $_SESSION[$sessionKey] = fate_spa_sync_job_create($force);
        $_SESSION[$sessionKey]['diagnostics']['api_key_gate'] = (string) ($gate['hint_zh'] ?? '');
        $snap = fate_spa_sync_job_snapshot($_SESSION[$sessionKey]);
        echo json_encode(array_merge(['ok' => true], $snap), JSON_UNESCAPED_UNICODE);
        exit;

    case 'step':
        if (!isset($_SESSION[$sessionKey]) || !is_array($_SESSION[$sessionKey])) {
            echo json_encode([
                'ok' => false,
                'error' => 'no_job',
                'finished' => true,
                'fatal' => false,
                'hint_zh' => '請先按「開始分批同步」。',
            ], JSON_UNESCAPED_UNICODE);
            exit;
        }
        $job = &$_SESSION[$sessionKey];
        $batch = defined('FATE_SYNC_BATCH_DETAIL') ? FATE_SYNC_BATCH_DETAIL : 6;
        $snap = fate_spa_sync_job_step($pdo, $job, $batch, false);
        echo json_encode(array_merge(['ok' => true], $snap), JSON_UNESCAPED_UNICODE);
        exit;

    case 'status':
        if (!isset($_SESSION[$sessionKey]) || !is_array($_SESSION[$sessionKey])) {
            echo json_encode([
                'ok' => true,
                'finished' => true,
                'fatal' => false,
                'phase' => 'none',
                'progress_percent' => null,
                'catalog_total' => null,
                'stats' => null,
                'hint_zh' => '',
                'sync_ok' => false,
            ], JSON_UNESCAPED_UNICODE);
            exit;
        }
        $snap = fate_spa_sync_job_snapshot($_SESSION[$sessionKey]);
        echo json_encode(array_merge(['ok' => true], $snap), JSON_UNESCAPED_UNICODE);
        exit;

    case 'cancel':
        unset($_SESSION[$sessionKey]);
        echo json_encode([
            'ok' => true,
            'finished' => true,
            'fatal' => false,
            'phase' => 'cancelled',
            'progress_percent' => null,
            'catalog_total' => null,
            'stats' => null,
            'hint_zh' => '',
            'sync_ok' => false,
        ], JSON_UNESCAPED_UNICODE);
        exit;

    case 'images_start':
        $gate = fate_spa_sync_api_key_gate();
        if (!$gate['ok']) {
            $userMsg = fate_spa_sync_gate_user_message($gate);
            echo json_encode([
                'ok' => false,
                'error' => (string) ($gate['error'] ?? 'api_key_blocked'),
                'hint_zh' => $userMsg,
                'message' => $userMsg,
                'finished' => true,
            ], JSON_UNESCAPED_UNICODE);
            exit;
        }
        $forceImages = !empty($in['force']);
        $job = fate_spa_image_sync_job_create($forceImages);
        $inventory = fate_spa_image_sync_build_inventory($pdo);
        $paths = $inventory['paths'];
        $job['image_paths'] = $paths;
        $job['total'] = count($paths);
        $job['phase'] = $job['total'] > 0 ? 'download' : 'done';
        $job['done'] = $job['total'] === 0;
        $job['diagnostics']['api_key_gate'] = (string) ($gate['hint_zh'] ?? '');
        $job['diagnostics']['photo_refs'] = (int) ($inventory['photo_refs'] ?? 0);
        $job['diagnostics']['unique_basenames'] = (int) ($inventory['unique_basenames'] ?? 0);
        $job['diagnostics']['stores_with_photos'] = (int) ($inventory['stores_with_photos'] ?? 0);
        if ($job['total'] === 0) {
            $job['diagnostics']['hint_zh'] = '快照中尚無可下載的店家圖片；請先完成「同步店家」資料。';
        }
        $_SESSION[$imageSessionKey] = $job;
        $snap = fate_spa_image_sync_job_snapshot($job);
        echo json_encode(array_merge(['ok' => true], $snap), JSON_UNESCAPED_UNICODE);
        exit;

    case 'images_step':
        if (!isset($_SESSION[$imageSessionKey]) || !is_array($_SESSION[$imageSessionKey])) {
            echo json_encode([
                'ok' => false,
                'error' => 'no_job',
                'finished' => true,
                'fatal' => false,
                'hint_zh' => '請先按「開始同步圖片」。',
            ], JSON_UNESCAPED_UNICODE);
            exit;
        }
        $imageJob = &$_SESSION[$imageSessionKey];
        $imageBatch = defined('FATE_SYNC_BATCH_IMAGES') ? FATE_SYNC_BATCH_IMAGES : 4;
        $snap = fate_spa_image_sync_job_step($imageJob, $imageBatch);
        echo json_encode(array_merge(['ok' => true], $snap), JSON_UNESCAPED_UNICODE);
        exit;

    case 'images_cancel':
        unset($_SESSION[$imageSessionKey]);
        echo json_encode([
            'ok' => true,
            'finished' => true,
            'fatal' => false,
            'phase' => 'cancelled',
            'progress_percent' => null,
            'image_total' => null,
            'stats' => null,
            'hint_zh' => '',
            'sync_ok' => false,
        ], JSON_UNESCAPED_UNICODE);
        exit;

    case 'images_purge':
        unset($_SESSION[$imageSessionKey]);
        $purge = fate_spa_purge_synced_store_images($pdo);
        $uploadStats = fate_spa_stores_local_upload_stats();
        $purgeErrors = isset($purge['errors']) && is_array($purge['errors']) ? $purge['errors'] : [];
        $deleted = (int) ($purge['deleted'] ?? 0);
        $skipped = (int) ($purge['skipped_protected'] ?? 0);
        $freed = (int) ($purge['bytes'] ?? 0);
        $hint = $deleted > 0
            ? '已刪除 ' . $deleted . ' 張快取（釋放約 ' . fate_spa_format_bytes($freed) . '），保留 ' . $skipped . ' 張會員上傳。'
            : ($skipped > 0
                ? '沒有可刪除的快取；保留 ' . $skipped . ' 張會員上傳。'
                : '目錄中沒有快取檔案。');
        if ($purgeErrors !== []) {
            $hint .= ' 部分檔案刪除失敗：' . implode('、', array_slice($purgeErrors, 0, 5));
        }
        echo json_encode([
            'ok' => $purgeErrors === [],
            'purge' => $purge,
            'upload_stats' => [
                'count' => (int) ($uploadStats['count'] ?? 0),
                'bytes' => (int) ($uploadStats['bytes'] ?? 0),
            ],
            'hint_zh' => $hint,
        ], JSON_UNESCAPED_UNICODE);
        exit;

    default:
        http_response_code(400);
        echo json_encode(['ok' => false, 'error' => 'bad_action'], JSON_UNESCAPED_UNICODE);
        exit;
}
