<?php
/**
 * VR票务插件 - 后台管理主控制器（admin/Admin.php 模式）
 *
 * 路由机制（Plugins/Index → PluginsService::PluginsControlCall）:
 *   sidebar URL: /plugins/vr_ticket/admin/seatTemplateList
 *   → pluginsname=vr_ticket, pluginscontrol=admin, pluginsaction=seatTemplateList
 *   → class = \app\plugins\vr_ticket\admin\Admin  (ucfirst('admin') = 'Admin')
 *   → method = ucfirst('seatTemplateList') = 'SeatTemplateList'
 *   → app/plugins/vr_ticket/admin/Admin.php::SeatTemplateList()  ✓
 *
 * ThinkPHP PSR-4 autoload: app\ → app/
 * 所以 \app\plugins\vr_ticket\admin\Admin
 * → app/plugins/vr_ticket/admin/Admin.php  ✓
 *
 * 旧结构 admin/controller/SeatTemplate.php (namespace 含 controller 子目录)
 * 会产生类路径 \app\plugins\vr_ticket\admin\SeatTemplate（无 controller 子目录）
 * → app/plugins/vr_ticket/admin/SeatTemplate.php  ✗ (不存在)
 * 这就是路由失败的根因!
 *
 * @package vr_ticket\admin
 */

namespace app\plugins\vr_ticket\admin;

define('START_TIME', microtime(true));

use app\admin\controller\Common;

/**
 * 所有后台控制器方法都在此类中实现
 * 直接继承 ShopXO Common 控制器以获得 IsLogin + IsPower + ViewInit
 */
class Admin extends Common
{
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * 初始化方法 - 自愈性安装检查
     */
    protected function initialize()
    {
        parent::initialize();
        
        // 增加缓存锁，避免每次请求都进行数据库结构自检（这是导致加载缓慢的潜在原因）
        $cache_key = 'vr_ticket_table_checked_v2';
        if (\think\facade\Cache::get($cache_key) !== 1) {
            try {
                $this->checkAndInstallTables();
                \think\facade\Cache::set($cache_key, 1, 3600); // 1小时检查一次
            } catch (\Exception $e) {
                // 静默失败
            }
        }
    }

    /**
     * 自动建表逻辑
     * 如果发现核心表不存在，则从 install.sql 读取 SQL 并执行
     */
    private function checkAndInstallTables()
    {
        $prefix = \think\facade\Config::get('database.connections.mysql.prefix', 'vrt_');
        $tableName = $prefix . 'vr_seat_templates';
        
        // 检查表是否存在
        $res = \think\facade\Db::query("SHOW TABLES LIKE '{$tableName}'");
        if (empty($res)) {
            $sqlFile = dirname(__DIR__) . '/install.sql';
            if (file_exists($sqlFile)) {
                $sqlContent = file_get_contents($sqlFile);
                // 替换前缀
                $sqlContent = str_replace('{{prefix}}', $prefix, $sqlContent);
                // 拆分 SQL 语句执行
                $sqls = explode(';', $sqlContent);
                foreach ($sqls as $sql) {
                    $sql = trim($sql);
                    if (!empty($sql)) {
                        try {
                            \think\facade\Db::execute($sql);
                        } catch (\Exception $e) {
                            // 记录日志或忽略错误
                        }
                    }
                }
            }
        }
        
        // 兼容性修补：如果已存在表且存在 uk_category_id 唯一索引，则将其删除
        // 场馆现在使用自由配置，不再强制要求绑定唯一的产品分类
        try {
            $indexCheck = \think\facade\Db::query("SHOW INDEX FROM `{$tableName}` WHERE Key_name = 'uk_category_id'");
            if (!empty($indexCheck)) {
                try {
                    \think\facade\Db::execute("ALTER TABLE `{$tableName}` DROP INDEX `uk_category_id`");
                } catch (\Exception $e) {
                    // 如果已经手动删除或报错则忽略
                }
            }
        } catch (\Exception $e) {
            // 忽略由于键不存在导致的异常
        }
    }
    public function index()
    {
        return $this->VenueList();
    }


    // ============================================================
    // 电子票（Ticket）
    // 视图: admin/view/ticket/{action}.html
    // ============================================================

    /**
     * 电子票列表
     */
    public function TicketList()
    {
        $where = [];

        // 逐字段精确搜索（对应视图的独立搜索框）
        $order_no = input('order_no', '', '', 'trim');
        if ($order_no !== '') {
            $where[] = ['order_no', 'like', "%{$order_no}%"];
        }
        $ticket_code = input('ticket_code', '', '', 'trim');
        if ($ticket_code !== '') {
            $where[] = ['ticket_code', 'like', "%{$ticket_code}%"];
        }
        $real_name = input('real_name', '', '', 'trim');
        if ($real_name !== '') {
            $where[] = ['real_name', 'like', "%{$real_name}%"];
        }
        $phone = input('phone', '', '', 'trim');
        if ($phone !== '') {
            $where[] = ['phone', 'like', "%{$phone}%"];
        }
        $verify_status = input('verify_status', '', '', 'trim');
        if ($verify_status !== '' && $verify_status !== null) {
            $where[] = ['verify_status', '=', intval($verify_status)];
        }

        // 搜索参数回传（用于表单值保持）
        $params = [
            'order_no'      => $order_no,
            'ticket_code'   => $ticket_code,
            'real_name'     => $real_name,
            'phone'         => $phone,
            'verify_status' => $verify_status,
        ];

        $list = \think\facade\Db::name('vr_tickets')
            ->where($where)
            ->order('id', 'desc')
            ->paginate(20);
        $list_data = $list->toArray();

        // 补充商品名称
        $goods_ids = array_filter(array_column($list_data['data'], 'goods_id'));
        if (!empty($goods_ids)) {
            $goods_map = \think\facade\Db::name('Goods')
                ->where('id', 'in', $goods_ids)
                ->column('title', 'id');
            foreach ($list_data['data'] as &$item) {
                $item['goods_title'] = $goods_map[$item['goods_id']] ?? '已删除商品';
                $item['qr_code_url'] = \app\plugins\vr_ticket\service\TicketService::getQrCodeUrl($item['ticket_code']);
            }
            unset($item);
        }

        return MyView('../../../plugins/vr_ticket/view/admin/ticket/list', [
            'list'  => $list_data['data'],
            'page'  => $list->render() ?: '',
            'count' => $list_data['total'],
            'params'=> $params,
        ]);
    }

    /**
     * 票详情
     */
    public function TicketDetail()
    {
        $id = input('id', 0, 'intval');
        if ($id <= 0) {
            return DataReturn('参数错误', -1);
        }

        $ticket = \think\facade\Db::name('vr_tickets')->find($id);
        if (empty($ticket)) {
            return DataReturn('票不存在', -1);
        }

        $goods = \think\facade\Db::name('Goods')->find($ticket['goods_id']);

        $verifier = [];
        if ($ticket['verifier_id'] > 0) {
            $verifier = \think\facade\Db::name('vr_verifiers')->find($ticket['verifier_id']);
        }

        $ticket['qr_code_url'] = \app\plugins\vr_ticket\service\TicketService::getQrCodeUrl($ticket['ticket_code']);

        $verifiers = \think\facade\Db::name('vr_verifiers')
            ->where('status', 1)
            ->order('id', 'asc')
            ->select();

        return MyView('../../../plugins/vr_ticket/view/admin/ticket/detail', [
            'ticket'    => $ticket,
            'goods'     => $goods,
            'verifier'  => $verifier,
            'verifiers' => $verifiers,
        ]);
    }

    /**
     * 手动核销票（JSON API）
     */
    /**
     * 扫码核销页面（GET）和核销处理（AJAX POST）
     * GET: 显示核销表单
     * POST: 处理核销 AJAX 请求
     */
    public function TicketVerify()
    {
        // GET 请求 — 显示核销表单页面
        if (!request()->isAjax()) {
            return MyView('../../../plugins/vr_ticket/view/admin/ticket/verify', []);
        }

        // AJAX POST — 处理核销
        if (!request()->isPost()) {
            return json(['code' => -1, 'msg' => '非法请求']);
        }

        $ticket_code = input('ticket_code', '', '', 'trim');

        // M-05: verifier_id 从 session 获取，禁止客户端伪造
        // $this->admin 来自父类构造函数：AdminService::LoginInfo()
        $admin_id = isset($this->admin['id']) ? intval($this->admin['id']) : 0;
        $verifier = \think\facade\Db::name('vr_verifiers')
            ->where('user_id', $admin_id)
            ->where('status', 1)
            ->find();
        if (empty($verifier)) {
            return DataReturn('你不是核销员，无权核销', -1);
        }
        $verifier_id = $verifier['id'];

        if (empty($ticket_code)) {
            return DataReturn('票码不能为空', -1);
        }

        // 自动识别短码 vs UUID：短码长度 < 20 且不含连字符
        $is_short_code = (strlen($ticket_code) < 20 && strpos($ticket_code, '-') === false);

        if ($is_short_code) {
            // 短码核销
            $result = \app\plugins\vr_ticket\service\TicketService::verifyByShortCode($ticket_code, $verifier_id);
        } else {
            // UUID 核销
            $result = \app\plugins\vr_ticket\service\TicketService::verifyTicket($ticket_code, $verifier_id);
        }

        return DataReturn($result['msg'], $result['code'], $result['data'] ?? []);
    }

    /**
     * 获取核销统计数据（JSON API）
     * URL: /adminufgeyw.php?s=admin/plugins/index&pluginsname=vr_ticket&pluginscontrol=admin&pluginsaction=TicketStats
     */
    public function TicketStats()
    {
        if (!(request()->isAjax())) {
            return DataReturn('非法请求', -1);
        }
        $today_start = strtotime('today');
        $total = \think\facade\Db::name('vr_tickets')->count();
        $verified = \think\facade\Db::name('vr_tickets')->where('verify_status', 1)->count();
        $pending = \think\facade\Db::name('vr_tickets')->where('verify_status', 0)->count();
        $today = \think\facade\Db::name('vr_tickets')
            ->where('verify_status', 1)
            ->where('verify_time', '>=', $today_start)
            ->count();
        return DataReturn('获取成功', 0, [
            'total'    => $total,
            'verified' => $verified,
            'pending'  => $pending,
            'today'    => $today,
        ]);
    }

    /**
     * 导出票列表（CSV）
     */
    public function TicketExport()
    {
        if (!(request()->isAjax() && request()->isPost())) {
            return DataReturn('非法请求', -1);
        }

        $where = [];
        $goods_id = input('goods_id', 0, 'intval');
        if ($goods_id > 0) {
            $where[] = ['goods_id', '=', $goods_id];
        }

        $header = ['ID', '订单号', '票码', '观演人', '手机', '座位', '核销状态', '发放时间'];
        $rows = \think\facade\Db::name('vr_tickets')
            ->where($where)
            ->order('id', 'desc')
            ->cursor();

        $data = [];
        foreach ($rows as $item) {
            $status_text = $item['verify_status'] == 0 ? '未核销' : ($item['verify_status'] == 1 ? '已核销' : '已退款');
            $data[] = [
                $item['id'],
                $item['order_no'],
                $item['ticket_code'],
                $item['real_name'],
                $item['phone'],
                $item['seat_info'],
                $status_text,
                date('Y-m-d H:i:s', $item['issued_at']),
            ];
        }

        \app\plugins\vr_ticket\service\AuditService::logExport($goods_id, ['verify_status' => null], count($data));

        ExportCsv($header, $data, 'vr_tickets_' . date('Ymd'));
        return;
    }

    // ============================================================
    // 核销员（Verifier）
    // 视图: admin/view/verifier/{action}.html
    // ============================================================

    /**
     * 核销员列表
     */
    public function VerifierList()
    {
        $where = [];

        $keywords = input('keywords', '', null, 'trim');
        if (!empty($keywords)) {
            $where[] = ['name|user_id', 'like', "%{$keywords}%"];
        }

        $status = input('status', '', null);
        if ($status !== '' && $status !== null) {
            $where[] = ['status', '=', intval($status)];
        }

        $list = \think\facade\Db::name('vr_verifiers')
            ->where($where)
            ->order('id', 'desc')
            ->paginate(20);
        $list_data = $list->toArray();

        // 关联 ShopXO 用户信息
        $user_ids = array_filter(array_column($list_data['data'], 'user_id'));
        if (!empty($user_ids)) {
            $users_raw = \think\facade\Db::name('User')
                ->where('id', 'in', $user_ids)
                ->select();
            $users = [];
            foreach ($users_raw as $u) {
                $users[$u['id']] = ($u['nickname'] ?: '') . '/' . ($u['username'] ?: '');
            }
            foreach ($list_data['data'] as &$item) {
                $item['user_name'] = $users[$item['user_id']] ?? '已删除用户';
            }
            unset($item);
        }

        return MyView('../../../plugins/vr_ticket/view/admin/verifier/list', [
            'list'  => $list_data['data'],
            'page'  => $list->render() ?: '',
            'count' => $list_data['total'],
        ]);
    }

    /**
     * 添加/编辑核销员
     */
    public function VerifierSave()
    {
        $id = input('id', 0, 'intval');

        if ((request()->isAjax() && request()->isPost())) {
            $user_id = input('user_id', 0, 'intval');
            $name = input('name', '', null, 'trim');
            $status = input('status', 1, 'intval');

            if ($user_id <= 0) {
                return DataReturn('请选择关联用户', -1);
            }
            if (empty($name)) {
                return DataReturn('核销员名称不能为空', -1);
            }

            $exist = \think\facade\Db::name('vr_verifiers')
                ->where('user_id', $user_id)
                ->where('id', '<>', $id)
                ->find();
            if ($exist) {
                return DataReturn('该用户已是核销员', -1);
            }

            if ($id > 0) {
                \think\facade\Db::name('vr_verifiers')
                    ->where('id', $id)
                    ->update(['name' => $name, 'status' => $status]);
                return DataReturn('更新成功', 0);
            } else {
                \think\facade\Db::name('vr_verifiers')->insert([
                    'user_id'    => $user_id,
                    'name'       => $name,
                    'status'     => $status,
                    'created_at' => time(),
                ]);
                return DataReturn('添加成功', 0);
            }
        }

        $info = [];
        if ($id > 0) {
            $info = \think\facade\Db::name('vr_verifiers')->find($id);
        }

        $users = \think\facade\Db::name('User')
            ->where('status', '<>', 3) // 3 usually means deleted/disabled in some versions, but to be safe:
            ->field('id, nickname, username')
            ->order('id', 'desc')
            ->select();

        return MyView('../../../plugins/vr_ticket/view/admin/verifier/save', [
            'info'  => $info,
            'users' => $users,
        ]);
    }

    /**
     * 删除核销员（软删除：禁用）
     */
    public function VerifierDelete()
    {
        if (!(request()->isAjax() && request()->isPost())) {
            return DataReturn('非法请求', -1);
        }

        $id = input('id', 0, 'intval');
        if ($id <= 0) {
            return DataReturn('参数错误', -1);
        }

        $verifier = \think\facade\Db::name('vr_verifiers')->where('id', $id)->find();
        \think\facade\Db::name('vr_verifiers')
            ->where('id', $id)
            ->update(['status' => 0]);

        \app\plugins\vr_ticket\service\AuditService::log(
            \app\plugins\vr_ticket\service\AuditService::ACTION_DISABLE_VERIFIER,
            \app\plugins\vr_ticket\service\AuditService::TARGET_VERIFIER,
            $id,
            ['before_status' => $verifier['status'] ?? 1],
            $verifier ? "核销员: {$verifier['name']}" : "ID:{$id}"
        );

        return DataReturn('已禁用', 0);
    }

    // ============================================================
    // 场馆配置（Venue）
    // 视图: admin/view/venue/{action}.html
    // 注意：admin/controller/Venue.php 的旧控制器仍在使用，
    // 但新路由走 Admin.php 的 VenueList/VenueSave。
    // ============================================================

    /**
     * 场馆列表
     * URL: /plugins/vr_ticket/admin/venueList
     */
    public function VenueList()
    {
        $where = [];

        $name = input('name', '', null);
        if ($name !== '') {
            $where[] = ['name', 'like', "%{$name}%"];
        }

        $status = input('status', '', null);
        if ($status !== '' && $status !== null) {
            $where[] = ['status', '=', intval($status)];
        }

        $list = \think\facade\Db::name('vr_seat_templates')
            ->where($where)
            ->order('id', 'desc')
            ->paginate(20);
        $list_data = $list->toArray();

        // 解析 venue.name 和座位数（v3.0 格式：seat_map.venue.name）
        foreach ($list_data['data'] as &$item) {
            $seatMap = json_decode($item['seat_map'] ?? '{}', true);
            $item['venue_name']    = $seatMap['venue']['name'] ?? $item['name'];
            $item['venue_address'] = $seatMap['venue']['address'] ?? '';
            $item['rooms']         = $seatMap['rooms'] ?? [];
            $zoneCount = 0;
            if (!empty($item['rooms'])) {
                foreach ($item['rooms'] as $rm) {
                    $zoneCount += count($rm['sections'] ?? []);
                }
            } else {
                $zoneCount = !empty($seatMap['sections']) ? count($seatMap['sections']) : 0;
            }
            $item['zone_count']    = $zoneCount;
            $item['seat_count']    = $this->countSeatsV2($seatMap);
        }
        unset($item);

        return MyView('../../../plugins/vr_ticket/view/venue/list', [
            'list'     => $list_data['data'],
            'page'     => $list->render() ?: '',
            'count'    => $list_data['total'],
            'data_req' => input(),
            'debug_time' => microtime(true) - START_TIME,
        ]);
    }

    /**
     * 添加/编辑场馆
     * URL: /plugins/vr_ticket/admin/venueSave
     */
    public function VenueSave()
    {
        $id = input('id', 0, 'intval');

        if ((request()->isAjax() && request()->isPost())) {
            $data = [
                'name'        => input('name', '', null, 'trim'),
                'category_id' => 0, // 分类绑定已弃用，强置为 0
                'status'      => input('status', 1, 'intval'),
                'upd_time'    => time(),
            ];

            if (empty($data['name'])) {
                return DataReturn('场馆名称不能为空', -1);
            }

            // 使用 request()->post() 获取原始字符串，并兼容 Base64 编码绕过净化
            $seat_map_raw = request()->post('seat_map_raw', '{}');
            $decoded_json = $seat_map_raw;
            if(!empty($seat_map_raw) && $seat_map_raw !== '{}') {
                // 判断是否是 Base64 字符串 (如果是以 ey 开头通常是 JSON 的 Base64)
                if(preg_match('/^[a-zA-Z0-9\/\+=]+$/', $seat_map_raw) && strlen($seat_map_raw) % 4 == 0) {
                    $decoded_json = base64_decode($seat_map_raw);
                } else {
                    // 如果不是 Base64 则按原样处理并进行 htmlspecialchars_decode
                    $decoded_json = htmlspecialchars_decode($seat_map_raw);
                }
            }
            $seat_map = json_decode($decoded_json, true);

            if (empty($seat_map) || !is_array($seat_map)) {
                return DataReturn('场馆配置数据无效或解析失败', -1);
            }

            // 基本验证
            if (empty($seat_map['venue']['name'])) {
                return DataReturn('场馆详情名称不能为空', -1);
            }

            $rooms = $seat_map['rooms'] ?? [];
            if (!is_array($rooms) || empty($rooms)) {
                return DataReturn('请至少添加一个放映室/展厅', -1);
            }

            foreach ($rooms as &$room) {
                if (empty($room['name'])) {
                    return DataReturn('放映室名称不能为空', -1);
                }

                // 生成 room.id（兜底：保证每个房间有唯一 id，支持前端按 id 引用）
                // 使用 random_int() (CSPRNG)，UUID v4 格式（版本=4，变体=10xx）
                if (empty($room['id'])) {
                    $room['id'] = sprintf('%08x-%04x-%04x-%04x-%04x%08x',
                        time(),
                        random_int(0, 0xffff),
                        random_int(0, 0xffff),
                        (random_int(0, 0x3fff) & 0x0fff) | 0x4000,  // 版本4 + 变体10xx
                        random_int(0, 0xffff),
                        random_int(0, 0xffffffff));
                }

                // --- 自动补全 seats 字典，解决 'A' 未定义报错 ---
                $room['seats'] = [];
                if (!empty($room['sections']) && is_array($room['sections'])) {
                    foreach ($room['sections'] as $sec) {
                        if (isset($sec['char']) && $sec['char'] !== '') {
                            $room['seats'][$sec['char']] = $sec;
                        }
                    }
                }

                // 处理 map 数组，过滤空行并修剪
                $map = is_array($room['map']) ? $room['map'] : [];
                $room['map'] = array_values(array_filter(array_map('trim', $map), function($v) {
                    return $v !== '';
                }));

                if (empty($room['map'])) {
                    return DataReturn("放映室 {$room['name']} 座位排布不能为空", -1);
                }
                foreach ($room['map'] as $rowStr) {
                    // 此时 $rowStr 已经 trim 过且非空
                    foreach (str_split($rowStr) as $char) {
                        if ($char !== '_' && $char !== '-' && !isset($room['seats'][$char])) {
                            return DataReturn("放映室 {$room['name']} 中座位字符 '{$char}' 未在分区中定义", -1);
                        }
                    }
                }
            }

            // 保存最终 JSON，注意避免反斜杠转义
            // 注意：此时 $rooms 已被引用并修改了 map 数组（过滤了空行）
            $seat_map['rooms'] = $rooms;
            $data['seat_map'] = json_encode($seat_map, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

            if ($id > 0) {
                \think\facade\Db::name('vr_seat_templates')->where('id', $id)->update($data);
                return DataReturn('更新成功', 0);
            } else {
                $data['add_time'] = time();
                $data['upd_time'] = time();
                $data['spec_base_id_map'] = '';
                \think\facade\Db::name('vr_seat_templates')->insert($data);
                return DataReturn('添加成功', 0);
            }
        }

        $info = [];
        if ($id > 0) {
            $row = \think\facade\Db::name('vr_seat_templates')->find($id);
            if (!empty($row)) {
                $seatMap = json_decode($row['seat_map'] ?? '{}', true);
                $row['venue_name']     = $seatMap['venue']['name'] ?? '';
                $row['venue_address']  = $seatMap['venue']['address'] ?? '';
                $row['venue_image']    = $seatMap['venue']['image'] ?? '';
                $row['zones_json']     = json_encode($seatMap['sections'] ?? [], JSON_UNESCAPED_UNICODE);
                $row['venue_json']     = json_encode([
                    'name'    => $seatMap['venue']['name'] ?? '',
                    'address' => $seatMap['venue']['address'] ?? '',
                    'image'   => $seatMap['venue']['image'] ?? '',
                ], JSON_UNESCAPED_UNICODE);
                $row['map_json']       = json_encode($seatMap['map'] ?? [], JSON_UNESCAPED_UNICODE);
                $info = $row;
            }
        }

        $categories = \think\facade\Db::name('GoodsCategory')
            ->where('is_enable', 1)
            ->order('id', 'asc')
            ->select();

        // 加载插件配置，用于获取高德 API Key 等
        $config_ret = \app\service\PluginsService::PluginsData('vr_ticket');
        $config = $config_ret['data'] ?? [];

        return MyView('../../../plugins/vr_ticket/view/venue/save', [
            'info'       => $info,
            'categories' => $categories,
            'vr_config'  => $config,
        ]);
    }

    /**
     * 插件设置视图
     */
    public function Setup()
    {
        $data_ret = \app\service\PluginsService::PluginsData('vr_ticket');
        $data = $data_ret['data'] ?? [];
        return MyView('../../../plugins/vr_ticket/view/admin/setup', [
            'data' => $data,
        ]);
    }

    /**
     * 插件设置保存
     */
    public function SetupSave()
    {
        if (!(request()->isAjax() && request()->isPost())) {
            return DataReturn('非法请求', -1);
        }

        $data = [
            'amap_api_key' => input('amap_api_key', '', null, 'trim'),
            'other_config' => input('other_config', '', null, 'trim'),
        ];

        $params = [
            'plugins' => 'vr_ticket',
            'data'    => $data,
        ];
        $ret = \app\service\PluginsService::PluginsDataSave($params);
        if ($ret['code'] == 0) {
            return DataReturn('保存成功', 0);
        } else {
            return DataReturn($ret['msg'], -1);
        }
    }

    /**
     * 删除场馆（软删除/硬删除）
     * @param hard_delete: 0=软删除(禁用), 1=硬删除 (兼容旧的自定义JS调用)
     * @param value: 'hard'=硬删除 (submit-ajax新方式)
     */
    public function VenueDelete()
    {
        if (!(request()->isAjax() && request()->isPost())) {
            return DataReturn('非法请求', -1);
        }

        $id = input('id', 0, 'intval');
        if ($id <= 0) {
            return DataReturn('参数错误', -1);
        }

        // 兼容旧方式: hard_delete=1 为硬删除
        $hardDelete = input('hard_delete', 0, 'intval');
        // 新方式: value='hard' 为硬删除
        $value = input('value', '', null, 'trim');
        if ($value === 'hard') {
            $hardDelete = 1;
        }

        $template = \think\facade\Db::name('vr_seat_templates')->where('id', $id)->find();
        if (empty($template)) {
            return DataReturn('记录不存在', -1);
        }

        if ($hardDelete) {
            // 检查是否有关联商品（使用 is_delete_time 而不是 is_delete）
            $goods = \think\facade\Db::name('Goods')
                ->where('vr_goods_config', 'like', '%"template_id":' . $id . '%')
                ->where('is_delete_time', 0)
                ->find();
            \think\facade\Db::name('vr_seat_templates')->where('id', $id)->delete();
            \app\plugins\vr_ticket\service\AuditService::log(
                \app\plugins\vr_ticket\service\AuditService::ACTION_DELETE_TEMPLATE,
                \app\plugins\vr_ticket\service\AuditService::TARGET_TEMPLATE,
                $id,
                ['name' => $template['name'], 'has_goods' => !empty($goods)],
                "场馆: {$template['name']}"
            );
            return DataReturn('删除成功', 0, ['has_goods' => !empty($goods)]);
        }


        // 软删除（禁用）
        \think\facade\Db::name('vr_seat_templates')
            ->where('id', $id)
            ->update(['status' => 0, 'upd_time' => time()]);
        \app\plugins\vr_ticket\service\AuditService::log(
            \app\plugins\vr_ticket\service\AuditService::ACTION_DISABLE_TEMPLATE,
            \app\plugins\vr_ticket\service\AuditService::TARGET_TEMPLATE,
            $id,
            ['before_status' => $template['status'] ?? 1],
            $template ? "场馆: {$template['name']}" : "ID:{$id}"
        );
        return DataReturn('已禁用', 0);
    }

    public function VenueEnable()
    {
        if (!(request()->isAjax() && request()->isPost())) {
            return DataReturn('非法请求', -1);
        }

        $id = input('id', 0, 'intval');
        if ($id <= 0) {
            return DataReturn('参数错误', -1);
        }

        \think\facade\Db::name('vr_seat_templates')
            ->where('id', $id)
            ->update(['status' => 1, 'upd_time' => time()]);
        \app\plugins\vr_ticket\service\AuditService::log(
            \app\plugins\vr_ticket\service\AuditService::ACTION_ENABLE_TEMPLATE,
            \app\plugins\vr_ticket\service\AuditService::TARGET_TEMPLATE,
            $id,
            ['after_status' => 1],
            "场馆ID:{$id}"
        );
        return DataReturn('已启用', 0);
    }

    // ============================================================
    // 核销记录（Verification）
    // 视图: admin/view/verification/{action}.html
    // ============================================================

    /**
     * 核销记录列表
     */
    public function VerificationList()
    {
        $where = [];

        $keywords = input('keywords', '', null, 'trim');
        if (!empty($keywords)) {
            $where[] = ['ticket_code|verifier_name', 'like', "%{$keywords}%"];
        }

        $verifier_id = input('verifier_id', 0, 'intval');
        if ($verifier_id > 0) {
            $where[] = ['verifier_id', '=', $verifier_id];
        }

        $start_date = input('start_date', '', null, 'trim');
        $end_date = input('end_date', '', null, 'trim');
        if (!empty($start_date)) {
            $where[] = ['created_at', '>=', strtotime($start_date)];
        }
        if (!empty($end_date)) {
            $where[] = ['created_at', '<=', strtotime($end_date . ' 23:59:59')];
        }

        $list = \think\facade\Db::name('vr_verifications')
            ->where($where)
            ->order('id', 'desc')
            ->paginate(20);
        $list_data = $list->toArray();

        // 补充票信息
        $ticket_ids = array_filter(array_column($list_data['data'], 'ticket_id'));
        if (!empty($ticket_ids)) {
            $tickets_raw = \think\facade\Db::name('vr_tickets')
                ->where('id', 'in', $ticket_ids)
                ->select();
            $tickets = [];
            foreach ($tickets_raw as $t) {
                $tickets[$t['id']] = $t;
            }
            foreach ($list_data['data'] as &$item) {
                $ticket = $tickets[$item['ticket_id']] ?? [];
                $item['seat_info'] = $ticket['seat_info'] ?? '';
                $item['real_name'] = $ticket['real_name'] ?? '';
                $item['goods_id'] = $ticket['goods_id'] ?? 0;
            }
            unset($item);
        }

        // 商品名
        $goods_ids = array_filter(array_unique(array_column($list_data['data'], 'goods_id')));
        if (!empty($goods_ids)) {
            $goods_map = \think\facade\Db::name('Goods')
                ->where('id', 'in', $goods_ids)
                ->column('title', 'id');
            foreach ($list_data['data'] as &$item) {
                $item['goods_title'] = $goods_map[$item['goods_id']] ?? '已删除';
            }
            unset($item);
        }

        // 核销员列表（用于筛选）
        $verifiers = \think\facade\Db::name('vr_verifiers')
            ->where('status', 1)
            ->column('name', 'id');

        return MyView('../../../plugins/vr_ticket/view/admin/verification/list', [
            'list'      => $list_data['data'],
            'page'      => $list->render() ?: '',
            'count'     => $list_data['total'],
            'verifiers' => $verifiers,
        ]);
    }

    // ============================================================
    // 辅助方法
    // ============================================================

    /**
     * 统计座位数（v1 格式：直接传入 seat_map JSON 字符串）
     */
    private function countSeats($seat_map_json)
    {
        if (empty($seat_map_json)) {
            return 0;
        }
        $map = json_decode($seat_map_json, true);
        if (empty($map['seats']) || empty($map['map'])) {
            return 0;
        }
        $count = 0;
        foreach ($map['map'] as $row) {
            foreach (str_split($row) as $char) {
                if ($char !== '_' && isset($map['seats'][$char])) {
                    $count++;
                }
            }
        }
        return $count;
    }

    /**
     * 获取场次已售座位列表（JSON API）
     * URL: /plugins/vr_ticket/admin/soldSeats
     * GET 参数: goods_id, spec_base_id
     * 返回: {code:0, data:{sold_seats:['A_1','A_2','B_5']}}
     */
    public function SoldSeats()
    {
        // 鉴权（移动端登录）
        if (empty($_SESSION['user']['id'])) {
            return json_encode(['code' => 401, 'msg' => '请先登录']);
        }

        // 获取参数
        $goodsId = input('goods_id', 0, 'intval');
        $specBaseId = input('spec_base_id', 0, 'intval');

        if (empty($goodsId) || empty($specBaseId)) {
            return json_encode(['code' => 400, 'msg' => '参数错误']);
        }

        // TODO: 从已支付订单的 vr_tickets 表查询真实已售座位
        // 第一版返回空数组，后续迭代接入真实数据
        $soldSeats = [];
        return json_encode(['code' => 0, 'data' => ['sold_seats' => $soldSeats]]);
    }

    /**
     * 统计座位数（支持 v3 多房间格式 或 v2 格式）
     */
    private function countSeatsV2($seatMap)
    {
        if (empty($seatMap['rooms']) || !is_array($seatMap['rooms'])) {
            return 0;
        }
        $total = 0;
        foreach ($seatMap['rooms'] as $rm) {
            if (!empty($rm['map']) && is_array($rm['map'])) {
                foreach ($rm['map'] as $row) {
                    if (is_string($row)) {
                        $total += strlen(str_replace(['_', '-'], '', $row));
                    }
                }
            }
        }
        return $total;
    }
}
