<?php
/**
 * VR票务插件 - 票务服务
 *
 * 核心业务：订单支付成功 → 生成电子票
 *
 * @package vr_ticket\service
 */

namespace app\plugins\vr_ticket\service;

class TicketService extends BaseService
{
    /**
     * 订单支付成功回调
     *
     * 从 plugin.json 的 hook 触发：
     * plugins_service_order_pay_success_handle_end
     *
     * @param array $params 钩子参数，含 business_data, user_id, business_ids(order_ids)
     * @return bool
     */
    public static function onOrderPaid($params = [])
    {
        $order_id = $params['business_id'] ?? ($params['business_ids'][0] ?? 0);
        if (empty($order_id)) {
            BaseService::log('onOrderPaid: empty order_id', $params, 'warning');
            return false;
        }

        // 查询订单
        $order = \Db::name('Order')->find($order_id);
        if (empty($order) || $order['pay_status'] != 1) {
            BaseService::log('onOrderPaid: order not paid or not found', ['order_id' => $order_id], 'warning');
            return false;
        }

        // 判断是否为票务商品
        if (!BaseService::isTicketGoods($order['goods_id'])) {
            BaseService::log('onOrderPaid: not a ticket goods', ['order_id' => $order_id], 'info');
            return true; // 不是票务商品，不报错
        }

        // 查询商品快照（规格信息）
        $order_goods = \Db::name('OrderGoods')
            ->where('order_id', $order_id)
            ->select();
        if (empty($order_goods)) {
            BaseService::log('onOrderPaid: no order goods', ['order_id' => $order_id], 'error');
            return false;
        }

        // 逐个生成票（每个规格选项 = 一张票）
        $count = 0;
        foreach ($order_goods as $og) {
            $ticket_id = self::issueTicket($order, $og);
            if ($ticket_id > 0) {
                $count++;
            }
        }

        BaseService::log('onOrderPaid: success', [
            'order_id' => $order_id,
            'tickets_issued' => $count,
        ]);

        return $count > 0;
    }

    /**
     * 发放单张票
     *
     * @param array $order 订单数据
     * @param array $order_goods 订单商品数据（包含 spec_base_id）
     * @return int 票ID
     */
    public static function issueTicket($order, $order_goods)
    {
        // P0-1 幂等保护：同一订单+同一规格只发一张票
        $existing = \Db::name(BaseService::table('tickets'))
            ->where('order_id', $order['id'])
            ->where('spec_base_id', $order_goods['spec_base_id'] ?? 0)
            ->find();
        if (!empty($existing)) {
            BaseService::log('issueTicket: idempotent_skip', [
                'order_id'    => $order['id'],
                'spec_base_id'=> $order_goods['spec_base_id'] ?? 0,
            ], 'info');
            return $existing['id'];
        }

        $ticket_code = BaseService::generateUuid();

        // 构建 QR 数据
        $qr_payload = [
            'id'    => 0,           // 写入后再更新
            'code'  => $ticket_code,
            'event' => $order['goods_id'],
            'seat'  => $order_goods['spec_name'] ?? '',   // 规格名=座位信息
        ];
        $qr_data = BaseService::encryptQrData($qr_payload);

        // 观演人信息（从订单扩展字段读取，由购票页表单写入）
        $extension_data = json_decode($order['extension_data'] ?? '{}', true);
        $attendee = $extension_data['attendee'] ?? [];

        $now = BaseService::now();

        $ticket_id = \Db::name(BaseService::table('tickets'))->insertGetId([
            'order_id'       => $order['id'],
            'order_no'       => $order['order_no'],
            'goods_id'       => $order['goods_id'],
            'goods_snapshot' => json_encode([
                'goods_name' => $order['goods_name'] ?? '',
                'spec_name'  => $order_goods['spec_name'] ?? '',
                'price'      => $order_goods['goods_price'] ?? 0,
            ], JSON_UNESCAPED_UNICODE),
            'user_id'        => $order['user_id'],
            'ticket_code'    => $ticket_code,
            'qr_data'        => $qr_data,
            'seat_info'      => $order_goods['spec_name'] ?? '',
            'spec_base_id'   => $order_goods['spec_base_id'] ?? 0,
            'real_name'      => $attendee['real_name'] ?? '',
            'phone'          => $attendee['phone'] ?? '',
            'id_card'        => $attendee['id_card'] ?? '',
            'verify_status'  => 0,          // 0=未核销
            'issued_at'      => $now,
            'created_at'     => $now,
            'updated_at'     => $now,
        ]);

        // 更新 QR 数据中的 ticket_id
        if ($ticket_id > 0) {
            $qr_payload['id'] = $ticket_id;
            $qr_data_updated = BaseService::encryptQrData($qr_payload);
            \Db::name(BaseService::table('tickets'))
                ->where('id', $ticket_id)
                ->update(['qr_data' => $qr_data_updated]);
        }

        return $ticket_id;
    }

    /**
     * 核销票（事务保护 + 悲观锁防并发）
     *
     * @param string $ticket_code 票码
     * @param int $verifier_id 核销员ID
     * @return array [code, msg]
     */
    public static function verifyTicket($ticket_code, $verifier_id)
    {
        try {
            return \Db::transaction(function () use ($ticket_code, $verifier_id) {
                // FOR UPDATE 悲观锁：防止并发核销同一张票
                $ticket = \Db::name(BaseService::table('tickets'))
                    ->where('ticket_code', $ticket_code)
                    ->lock(true)
                    ->find();

                if (empty($ticket)) {
                    return ['code' => -1, 'msg' => '票码不存在'];
                }

                if ($ticket['verify_status'] == 1) {
                    return ['code' => -2, 'msg' => '该票已核销'];
                }

                if ($ticket['verify_status'] == 2) {
                    return ['code' => -3, 'msg' => '该票已退款'];
                }

                $now = BaseService::now();

                // 更新票状态
                \Db::name(BaseService::table('tickets'))
                    ->where('id', $ticket['id'])
                    ->update([
                        'verify_status' => 1,
                        'verify_time'   => $now,
                        'verifier_id'   => $verifier_id,
                        'updated_at'    => $now,
                    ]);

                // 写入核销记录
                $verifier = \Db::name(BaseService::table('verifiers'))
                    ->where('id', $verifier_id)
                    ->find();

                \Db::name(BaseService::table('verifications'))->insert([
                    'ticket_id'    => $ticket['id'],
                    'ticket_code'  => $ticket_code,
                    'verifier_id'  => $verifier_id,
                    'verifier_name'=> $verifier['name'] ?? '',
                    'goods_id'     => $ticket['goods_id'],
                    'created_at'   => $now,
                ]);

                BaseService::log('verifyTicket: success', [
                    'ticket_id'   => $ticket['id'],
                    'verifier_id' => $verifier_id,
                ]);

                // 审计日志（失败也记录，便于追溯异常）
                AuditService::logVerify(
                    $ticket['id'],
                    $ticket_code,
                    $verifier_id,
                    $verifier['name'] ?? '',
                    'success',
                    0 // 原状态（核销前一定是 0）
                );

                return [
                    'code'  => 0,
                    'msg'   => '核销成功',
                    'data'  => [
                        'seat_info'  => $ticket['seat_info'],
                        'real_name'  => $ticket['real_name'],
                        'goods_name' => json_decode($ticket['goods_snapshot'] ?? '{}', true)['goods_name'] ?? '',
                    ],
                ];
            });
        } catch (\Throwable $e) {
            BaseService::log('verifyTicket: transaction_error', [
                'ticket_code' => $ticket_code,
                'error'       => $e->getMessage(),
            ], 'error');
            return ['code' => -999, 'msg' => '核销失败，请重试'];
        }
    }

    /**
     * 获取用户所有票
     */
    public static function getUserTickets($user_id, $status = null)
    {
        $where = ['user_id' => $user_id];
        if ($status !== null) {
            $where['verify_status'] = $status;
        }

        return \Db::name(BaseService::table('tickets'))
            ->where($where)
            ->order('created_at', 'desc')
            ->select();
    }

    /**
     * 生成 QR 码图片 URL
     *
     * @param string $ticket_code
     * @return string QR码图片URL
     */
    public static function getQrCodeUrl($ticket_code)
    {
        $content = base64_encode(json_encode([
            'type' => 'vr_ticket',
            'code' => $ticket_code,
        ]));

        return ROOT_URL . '?s=index/qrcode/index&content=' . urlencode($content) . '&size=8&level=H';
    }
}
