<?php
/**
 * VR票务插件 - 票夹服务（C端）
 *
 * 核心功能：
 * 1. 获取用户票列表
 * 2. 获取票详情
 * 3. 生成/缓存 QR payload
 *
 * @package vr_ticket\service
 */

namespace app\plugins\vr_ticket\service;

require_once __DIR__ . '/BaseService.php';

class WalletService extends BaseService
{
    /**
     * QR 有效期（秒）
     */
    const QR_TTL = 1800; // 30分钟

    /**
     * 获取用户所有票
     *
     * @param int $userId 用户ID
     * @return array
     */
    public static function getUserTickets(int $userId): array
    {
        // 直接查询 tickets 表（user_id 已存在）
        $tickets = \think\facade\Db::name('vr_tickets')
            ->where('user_id', $userId)
            ->order('issued_at', 'desc')
            ->select()
            ->toArray();

        if (empty($tickets)) {
            return [];
        }

        // 批量获取商品信息
        $goodsIds = array_filter(array_column($tickets, 'goods_id'));
        $goodsMap = [];
        if (!empty($goodsIds)) {
            $goodsMap = \think\facade\Db::name('Goods')
                ->where('id', 'in', $goodsIds)
                ->column('title', 'id');
        }

        // 格式化数据
        $result = [];
        foreach ($tickets as $ticket) {
            // 生成短码
            $shortCode = self::shortCodeEncode($ticket['goods_id'], $ticket['id']);

            // 优先从 seat_info 解析（5维 pipe 格式），兜底从 goods_snapshot 解析
            $seatInfo = self::parseSeatInfo($ticket['seat_info'] ?? '');
            $snapshot = json_decode($ticket['goods_snapshot'] ?? '{}', true);
            $snapshotKeys = array_filter(['session' => $snapshot['session'] ?? '', 'venue' => $snapshot['venue'] ?? '', 'studio' => $snapshot['studio'] ?? '', 'section' => $snapshot['section'] ?? '', 'seat' => $snapshot['seat'] ?? '']);
            if (empty($seatInfo['session']) && !empty($snapshotKeys)) {
                $seatInfo = array_merge($seatInfo, $snapshotKeys);
            }

            // goods_snapshot 里没有 session/venue 时，从商品表补全
            if (empty($seatInfo['session']) || empty($seatInfo['venue'])) {
                $goodsTitle = $goodsMap[$ticket['goods_id']] ?? '已下架商品';
                $goods = \think\facade\Db::name('Goods')->where('id', $ticket['goods_id'])->find();
                $vrConfig = json_decode($goods['vr_goods_config'] ?? '', true);
                if (!empty($vrConfig[0]['template_id'])) {
                    $template = \think\facade\Db::name('vr_seat_templates')
                        ->where('id', $vrConfig[0]['template_id'])->find();
                    $seatMap = json_decode($template['seat_map'] ?? '{}', true);
                    if (empty($seatInfo['venue']))  $seatInfo['venue']  = $template['name'] ?? '';
                    if (empty($seatInfo['session'])) {
                        $sessions = $vrConfig[0]['sessions'] ?? [];
                        $seatInfo['session'] = !empty($sessions[0]['start']) && !empty($sessions[0]['end'])
                            ? ($sessions[0]['start'] . '-' . $sessions[0]['end']) : '';
                    }
                }
            }
            if (empty($seatInfo['venue']))   $seatInfo['venue']   = $snapshot['venue']   ?? '';
            if (empty($seatInfo['session'])) $seatInfo['session'] = $snapshot['session'] ?? '';

            $result[] = [
                'id'            => $ticket['id'],
                'goods_id'      => $ticket['goods_id'],
                'goods_title'   => $goodsMap[$ticket['goods_id']] ?? '已下架商品',
                'seat_info'     => $ticket['seat_info'] ?? '',  // 完整 5 维（保留）
                'seat_number'   => self::parseSeatNumber($ticket['seat_info'] ?? ''), // 仅座位号
                'session_time'  => $seatInfo['session'] ?? '',
                'venue_name'    => $seatInfo['venue'] ?? '',
                'real_name'      => $ticket['real_name'] ?? '',
                'phone'          => self::maskPhone($ticket['phone'] ?? ''),
                'verify_status'  => $ticket['verify_status'],
                'issued_at'      => $ticket['issued_at'],
                'short_code'    => $shortCode,
            ];
        }

        return $result;
    }

    /**
     * 提取座位号（seat_info 最后一个 | 分段）
     * @param string $seatInfo 完整 5 维坐席信息
     * @return string 仅座位号
     */
    public static function parseSeatNumber(string $seatInfo): string
    {
        if (empty($seatInfo)) return '';
        $parts = explode('|', $seatInfo);
        return end($parts) ?: '';
    }

    /**
     * 获取票详情
     *
     * @param int $ticketId 票ID
     * @param int $userId 用户ID（用于权限校验）
     * @return array|null
     */
    public static function getTicketDetail(int $ticketId, int $userId): ?array
    {
        // 直接查询 tickets 表（包含 user_id）
        $ticket = \think\facade\Db::name('vr_tickets')
            ->where('id', $ticketId)
            ->where('user_id', $userId)
            ->find();

        if (empty($ticket)) {
            return null;
        }

        // 获取商品信息
        $goods = \think\facade\Db::name('Goods')->find($ticket['goods_id']);
        $seatInfo = self::parseSeatInfo($ticket['seat_info'] ?? '');
        $snapshot = json_decode($ticket['goods_snapshot'] ?? '{}', true);

        // 兜底补全：从 snapshot 补 seat_info 缺失字段
        if (empty($seatInfo['venue']) || empty($seatInfo['session'])) {
            $vrConfig = json_decode($goods['vr_goods_config'] ?? '', true);
            if (!empty($vrConfig[0]['template_id'])) {
                $template = \think\facade\Db::name('vr_seat_templates')
                    ->where('id', $vrConfig[0]['template_id'])->find();
                if (empty($seatInfo['venue']))   $seatInfo['venue']   = $template['name'] ?? '';
                if (empty($seatInfo['session'])) {
                    $sessions = $vrConfig[0]['sessions'] ?? [];
                    $seatInfo['session'] = !empty($sessions[0]['start']) && !empty($sessions[0]['end'])
                        ? ($sessions[0]['start'] . '-' . $sessions[0]['end']) : '';
                }
            }
        }
        if (empty($seatInfo['venue']))   $seatInfo['venue']   = $snapshot['venue']   ?? '';
        if (empty($seatInfo['session'])) $seatInfo['session'] = $snapshot['session'] ?? '';

        // 生成短码
        $shortCode = self::shortCodeEncode($ticket['goods_id'], $ticket['id']);

        // 生成 QR payload
        $qrData = self::getQrPayload($ticket);

        return [
            'id'            => $ticket['id'],
            'goods_id'      => $ticket['goods_id'],
            'goods_title'   => $goods['title'] ?? '已下架商品',
            'goods_image'   => $goods['images'] ?? '',
            'seat_info'     => $ticket['seat_info'] ?? '',
            'session_time'  => $seatInfo['session'] ?? '',
            'venue_name'    => $seatInfo['venue'] ?? '',
            'real_name'      => $ticket['real_name'] ?? '',
            'phone'          => self::maskPhone($ticket['phone'] ?? ''),
            'verify_status'  => $ticket['verify_status'],
            'verify_time'    => $ticket['verify_time'] ?? 0,
            'issued_at'      => $ticket['issued_at'],
            'short_code'     => $shortCode,
            'seat_number'    => self::parseSeatNumber($ticket['seat_info'] ?? ''),
            'qr_payload'     => $qrData['payload'],
            'qr_expires_at'  => $qrData['expires_at'],
            'qr_expires_in'  => $qrData['expires_in'],
        ];
    }

    /**
     * 生成 QR payload
     *
     * QR 有效期 30 分钟，动态生成，不存储
     *
     * @param array $ticket 票数据
     * @return array ['payload' => string, 'expires_at' => int, 'expires_in' => int]
     */
    public static function getQrPayload(array $ticket): array
    {
        $now = time();
        $expiresAt = $now + self::QR_TTL;

        $payload = [
            'id'   => $ticket['id'],
            'g'    => $ticket['goods_id'],
            'code' => $ticket['ticket_code'],
            'iat'  => $now,
            'exp'  => $expiresAt,
        ];

        $encoded = self::signQrPayload($payload);

        return [
            'payload'    => $encoded,
            'expires_at' => $expiresAt,
            'expires_in' => self::QR_TTL,
        ];
    }

    /**
     * 强制刷新 QR payload
     * 重新生成一个新的 QR payload（有效期重新计算）
     *
     * @param int $ticketId 票ID
     * @param int $userId 用户ID
     * @return array|null
     */
    public static function refreshQrPayload(int $ticketId, int $userId): ?array
    {
        // 直接调用 getTicketDetail，它会重新生成 QR
        return self::getTicketDetail($ticketId, $userId);
    }

    /**
     * 解析座位信息
     *
     * seat_info 格式：场次|场馆|演播室|分区|座位号
     * 例如：2026-06-01 20:00|国家体育馆|主要展厅|A区|A1
     *
     * @param string $seatInfo
     * @return array
     */
    private static function parseSeatInfo(string $seatInfo): array
    {
        $parts = explode('|', $seatInfo);

        return [
            'session' => $parts[0] ?? '',
            'venue'   => $parts[1] ?? '',
            'room'    => $parts[2] ?? '',
            'section' => $parts[3] ?? '',
            'seat'    => $parts[4] ?? '',
        ];
    }

    /**
     * 手机号脱敏
     *
     * @param string $phone
     * @return string
     */
    private static function maskPhone(string $phone): string
    {
        if (empty($phone) || strlen($phone) < 7) {
            return $phone;
        }

        return substr($phone, 0, 3) . '****' . substr($phone, -4);
    }
}
