<?php
if (!function_exists('get_pdo')) require_once __DIR__ . '/helpers.php';
/**
 * Heritage Voice — QR Code Management
 * Dùng named functions để router (index.php match) gọi đúng.
 */

if (!defined('QR_CHARSET')) define('QR_CHARSET', '0123456789ABCDEFGHJKLMNPQRSTUVWXYZ');
if (!defined('QR_BASE_URL')) define('QR_BASE_URL', 'https://tads.ctv.hanoi.vn/p/');

/* ── Helpers ── */
function qr_gen_code(PDO $pdo, string $prefix): string {
    $len = strlen(QR_CHARSET);
    do {
        $code = $prefix;
        for ($i = 0; $i < 5; $i++) $code .= QR_CHARSET[random_int(0, $len - 1)];
        $ck = $pdo->prepare("SELECT 1 FROM qr_redirects WHERE code = ?");
        $ck->execute([$code]);
    } while ($ck->fetchColumn());
    return $code;
}
function qr_prefix(string $type): string {
    return match($type) { 'site' => 'S', 'partner' => 'P', 'tour' => 'T', default => 'X' };
}
function qr_url(string $code): string { return QR_BASE_URL . $code; }
function qr_row_out(array $r): array {
    $code = $r['custom_slug'] ?: $r['code'];
    $url  = qr_url($code);
    return [
        // Format mới
        'code'        => $r['code'],
        'custom_slug' => $r['custom_slug'],
        'type'        => $r['type'],
        'target_uuid' => $r['target_uuid'],
        'label'       => $r['label'],
        'is_active'   => (bool)$r['is_active'],
        'qr_url'      => $url,
        'created_at'  => $r['created_at'],
        // Alias tương thích admin UI cũ
        'id'          => $r['code'],
        'target_id'   => $r['target_uuid'],
        'target_type' => $r['type'],
        'target_name' => $r['label'],
        'deep_link'   => $url,
        'scan_count'  => (int)($r['scan_count'] ?? 0),
        'status'      => $r['is_active'] ? 'active' : 'inactive',
    ];
}

/* ── GET /api/qr/for/{type}/{uuid} — get-or-create ── */
function qr_for(string $type, string $uuid): void {
    $pdo = db();
    if (!in_array($type, ['site','partner','tour'])) json_error('Type không hợp lệ', 400);
    $st = $pdo->prepare("SELECT * FROM qr_redirects WHERE type=? AND target_uuid=? LIMIT 1");
    $st->execute([$type, $uuid]);
    $row = $st->fetch(PDO::FETCH_ASSOC);
    if (!$row) {
        $code = qr_gen_code($pdo, qr_prefix($type));
        $label = '';
        try {
            $tbl = match($type) { 'site'=>'heritage_sites','partner'=>'partners','tour'=>'tours' };
            $l = $pdo->prepare("SELECT name FROM {$tbl} WHERE uuid=? LIMIT 1");
            $l->execute([$uuid]);
            $label = $l->fetchColumn() ?: '';
        } catch (Throwable $e) {}
        $pdo->prepare("INSERT INTO qr_redirects (code,type,target_uuid,label) VALUES (?,?,?,?)")
            ->execute([$code, $type, $uuid, $label]);
        $st->execute([$type, $uuid]);
        $row = $st->fetch(PDO::FETCH_ASSOC);
    }
    json_ok(qr_row_out($row));
}

/* ── GET /api/qr — list (admin) ── */
function qr_list(): void {
    require_admin();
    $pdo    = db();
    $type   = $_GET['type']   ?? '';
    $search = $_GET['search'] ?? '';
    $limit  = min((int)($_GET['limit'] ?? 50), 200);
    $page   = max(1, (int)($_GET['page'] ?? 1));
    $offset = ($page - 1) * $limit;
    $where  = ['1=1']; $params = [];
    if ($type)   { $where[] = 'type=?';                                   $params[] = $type; }
    if ($search) { $where[] = '(code LIKE ? OR custom_slug LIKE ? OR label LIKE ?)';
                   array_push($params, "%$search%", "%$search%", "%$search%"); }
    $w   = implode(' AND ', $where);
    $sql = "SELECT q.*, COALESCE(sc.cnt,0) as scan_count
            FROM qr_redirects q
            LEFT JOIN (SELECT code, COUNT(*) as cnt FROM qr_scans GROUP BY code) sc ON sc.code=q.code
            WHERE $w ORDER BY q.created_at DESC LIMIT $limit OFFSET $offset";
    $st  = $pdo->prepare($sql);
    $st->execute($params);
    $cnt = $pdo->prepare("SELECT COUNT(*) FROM qr_redirects WHERE $w");
    $cnt->execute($params);
    // Summary analytics
    $stats = $pdo->query("
        SELECT COUNT(DISTINCT q.code) as total_qr,
               COALESCE(SUM(sc.cnt),0) as total_scans
        FROM qr_redirects q
        LEFT JOIN (SELECT code,COUNT(*) as cnt FROM qr_scans GROUP BY code) sc ON sc.code=q.code
        WHERE q.is_active=1")->fetch(PDO::FETCH_ASSOC);
    $top = $pdo->query("
        SELECT q.code, q.label, q.type, COALESCE(sc.cnt,0) as scan_count
        FROM qr_redirects q
        LEFT JOIN (SELECT code,COUNT(*) as cnt FROM qr_scans GROUP BY code) sc ON sc.code=q.code
        ORDER BY scan_count DESC LIMIT 5")->fetchAll(PDO::FETCH_ASSOC);
    json_ok([
        'items'      => array_map('qr_row_out', $st->fetchAll(PDO::FETCH_ASSOC)),
        'pagination' => ['total'=>(int)$cnt->fetchColumn(),'page'=>$page,'limit'=>$limit],
        'stats'      => [
            'total_qr'    => (int)($stats['total_qr']    ?? 0),
            'total_scans' => (int)($stats['total_scans'] ?? 0),
            'top_scanned' => $top,
        ],
    ]);
}

/* ── GET /api/qr/{code} — single (+ /scans analytics) ── */
function qr_resolve(string $id): void {
    global $sub;
    $pdo = db();
    if ($sub === 'scans') {
        require_admin();
        $daily = $pdo->prepare("SELECT DATE(scanned_at) AS day, COUNT(*) AS count
            FROM qr_scans WHERE code=? AND scanned_at>=DATE_SUB(NOW(),INTERVAL 30 DAY)
            GROUP BY DATE(scanned_at) ORDER BY day ASC");
        $daily->execute([$id]);
        $tot = $pdo->prepare("SELECT COUNT(*) FROM qr_scans WHERE code=?");
        $tot->execute([$id]);
        $ua = $pdo->prepare("SELECT
            SUM(CASE WHEN user_agent LIKE '%Mobile%' THEN 1 ELSE 0 END) AS mobile,
            SUM(CASE WHEN user_agent NOT LIKE '%Mobile%' THEN 1 ELSE 0 END) AS desktop
            FROM qr_scans WHERE code=?");
        $ua->execute([$id]);
        json_ok(['code'=>$id,'total_scans'=>(int)$tot->fetchColumn(),
                 'daily'=>$daily->fetchAll(PDO::FETCH_ASSOC),'devices'=>$ua->fetch(PDO::FETCH_ASSOC)]);
    }
    $st = $pdo->prepare("SELECT * FROM qr_redirects WHERE code=? OR custom_slug=? LIMIT 1");
    $st->execute([$id, $id]);
    $row = $st->fetch(PDO::FETCH_ASSOC);
    if (!$row) json_error('Không tìm thấy', 404);
    json_ok(qr_row_out($row));
}

/* ── POST /api/qr — tạo mới ── */
function qr_create(): void {
    require_admin();
    $pdo  = db();
    $b    = body();
    // Accept cả format admin cũ (target_type/target_id/id) và mới (type/target_uuid/code)
    $type = $b['type'] ?? $b['target_type'] ?? '';
    $uuid = $b['target_uuid'] ?? $b['target_id'] ?? '';
    $label= trim($b['label'] ?? '');
    $slug = trim($b['custom_slug'] ?? '') ?: null;
    $code = trim($b['code'] ?? $b['id'] ?? '') ?: null;
    $type_map = ['heritage_site'=>'site','destination'=>'site'];
    if (isset($type_map[$type])) $type = $type_map[$type];
    if (!in_array($type, ['site','partner','tour','audio_point'])) json_error('type không hợp lệ: '.$type, 400);
    if (!$uuid) json_error('target_uuid bắt buộc', 400);
    if (!$code) $code = qr_gen_code($pdo, qr_prefix($type));
    // Thu insert, neu trung code thi auto-generate moi
    $attempt = 0;
    while ($attempt < 3) {
        try {
            $pdo->prepare("INSERT INTO qr_redirects (code,custom_slug,type,target_uuid,label) VALUES (?,?,?,?,?)")
                ->execute([$code, $slug, $type, $uuid, $label]);
            break;
        } catch (PDOException $e) {
            if ($e->getCode()==='23000') {
                if ($slug) json_error('Slug đã được dùng', 409);
                $code = qr_gen_code($pdo, qr_prefix($type)); // tự generate lại
                $attempt++;
            } else throw $e;
        }
    }
    $st = $pdo->prepare("SELECT * FROM qr_redirects WHERE code=?");
    $st->execute([$code]);
    json_ok(qr_row_out($st->fetch(PDO::FETCH_ASSOC)));
}

/* ── PUT /api/qr/{code} — cập nhật ── */
function qr_update(string $id): void {
    require_admin();
    $pdo = db();
    $b   = body();
    $st  = $pdo->prepare("SELECT * FROM qr_redirects WHERE code=? LIMIT 1");
    $st->execute([$id]);
    if (!$st->fetch()) json_error('Không tìm thấy', 404);
    $fields = []; $params = [];
    foreach (['custom_slug','label','is_active','target_uuid'] as $f) {
        if (array_key_exists($f, $b)) { $fields[] = "$f=?"; $params[] = $b[$f]==='' ? null : $b[$f]; }
    }
    if (!$fields) json_error('Không có gì cập nhật', 400);
    $params[] = $id;
    try {
        $pdo->prepare("UPDATE qr_redirects SET ".implode(',',$fields)." WHERE code=?")->execute($params);
    } catch (PDOException $e) {
        if ($e->getCode()==='23000') json_error('Slug đã được dùng', 409);
        throw $e;
    }
    $st->execute([$id]);
    json_ok(qr_row_out($st->fetch(PDO::FETCH_ASSOC)));
}

/* ── DELETE /api/qr/{code} — vô hiệu hoá ── */
function qr_delete(string $id): void {
    require_admin();
    db()->prepare("UPDATE qr_redirects SET is_active=0 WHERE code=?")->execute([$id]);
    json_ok(['deactivated'=>true,'code'=>$id]);
}

/* ── Helper cho seed ── */
function _seed_one(PDO $pdo, string $type, string $id, string $label): array {
    $ck = $pdo->prepare("SELECT code FROM qr_redirects WHERE type=? AND target_uuid=? LIMIT 1");
    $ck->execute([$type, $id]);
    if ($existing = $ck->fetchColumn()) {
        return ['label'=>$label,'code'=>$existing,'status'=>'skip'];
    }
    $code = qr_gen_code($pdo, qr_prefix($type));
    $pdo->prepare("INSERT INTO qr_redirects (code,type,target_uuid,label) VALUES (?,?,?,?)")
        ->execute([$code, $type, $id, $label]);
    return ['label'=>$label,'code'=>$code,'status'=>'new'];
}

/* ── POST /api/qr/seed — bulk create QR cho toan bo entity ── */
function qr_seed(): void {
    require_admin();
    $b    = body();
    $type = $b['type'] ?? 'all';
    $pdo  = db();
    $created = 0; $skipped = 0; $results = [];

    if (in_array($type, ['site','all'])) {
        foreach ($pdo->query("SELECT id,name FROM heritage_sites WHERE status='active'")->fetchAll(PDO::FETCH_ASSOC) as $r) {
            $res = _seed_one($pdo,'site',$r['id'],$r['name']);
            $res['status']==='new' ? $created++ : $skipped++;
            $results[] = array_merge($res,['type'=>'site']);
        }
    }
    if (in_array($type, ['audio_point','all'])) {
        foreach ($pdo->query("SELECT id,title FROM audio_points WHERE status='active'")->fetchAll(PDO::FETCH_ASSOC) as $r) {
            $res = _seed_one($pdo,'audio_point',$r['id'],$r['title']);
            $res['status']==='new' ? $created++ : $skipped++;
            $results[] = array_merge($res,['type'=>'audio_point']);
        }
    }
    if (in_array($type, ['partner','all'])) {
        foreach ($pdo->query("SELECT uuid AS id,name FROM hv_partners WHERE status='active'")->fetchAll(PDO::FETCH_ASSOC) as $r) {
            $res = _seed_one($pdo,'partner',$r['id'],$r['name']);
            $res['status']==='new' ? $created++ : $skipped++;
            $results[] = array_merge($res,['type'=>'partner']);
        }
    }
    json_ok(['created'=>$created,'skipped'=>$skipped,'results'=>$results]);
}
