<?php
/**
 * VR票务插件 - 座位 SKU 服务
 *
 * 核心业务：批量生成座位级 SKU（spec_base + spec_value）
 * 旁路 GoodsSpecificationsInsert()，直接 SQL INSERT
 *
 * @package vr_ticket\service
 */

namespace app\pluginsr_ticket\service;

class SeatSkuService extends BaseService
{
    /** @var int 分批处理每批条数 */
    const BATCH_SIZE = 500;

    /**
     * 批量生成座位级 SKU
     */
    public static function BatchGenerate(int $goodsId, int $seatTemplateId): array
    {
        $goodsId = intval($goodsId);
        $seatTemplateId = intval($seatTemplateId);

        if ($goodsId <= 0 || $seatTemplateId <= 0) {
            return ['code' => -1, 'msg' => '参数错误：goodsId 或 seatTemplateId 无效'];
        }

        // 1. 加载座位模板
        $template = 	hinkacade\Db::name(self::table('seat_templates'))
            ->where('id', $seatTemplateId)
            ->find();
        if (empty($template)) {
            return ['code' => -2, 'msg' => "座位模板 {$seatTemplateId} 不存在"];
        }

        // 2. 解析 seat_map
        $seatMap = json_decode($template['seat_map'] ?? '{}', true);
        
        $rooms = $seatMap['rooms'] ?? [];
        if (empty($rooms)) {
            // 向下兼容旧结构
            if (!empty($seatMap['map'])) {
                $rooms = [
                    [
                        'id' => 'room_default',
                        'name' => '默认放映室',
                        'map' => $seatMap['map'],
                        'seats' => $seatMap['seats'] ?? [],
                        'sections' => $seatMap['sections'] ?? []
                    ]
                ];
            } else {
                return ['code' => -3, 'msg' => '座位模板 seat_map 数据无效'];
            }
        }

        $venueName = $seatMap['venue']['name'] ?? $template['name'] ?? '未命名场馆';
        $specTypeIds = self::ensureVrSpecTypes($goodsId, $venueName);
        if ($specTypeIds['code'] !== 0) {
            return $specTypeIds;
        }
        $typeVenue  = $specTypeIds['data']['$vr-场馆'];
        $typeZone   = $specTypeIds['data']['$vr-分区'];
        $typeTime   = $specTypeIds['data']['$vr-时段']; // 时段留作可选，前端默认传“不限时段”
        $typeSeat   = $specTypeIds['data']['$vr-座位号'];

        $seatsToInsert = [];
        // 遍历 rooms
        foreach ($rooms as $room) {
            $roomId = $room['id'] ?? 'room_default';
            $roomName = $room['name'] ?? '默认放映室';
            
            $sectionPrices = [];
            foreach (($room['sections'] ?? []) as $section) {
                $sectionPrices[$section['name'] ?? ''] = floatval($section['price'] ?? 0);
            }
            
            $map = $room['map'] ?? [];
            $seatsData = $room['seats'] ?? [];
            
            foreach ($map as $rowIndex => $rowStr) {
                $rowLabel = chr(65 + $rowIndex);
                $chars = mb_str_split($rowStr);
                foreach ($chars as $colIndex => $char) {
                    if ($char === '_' || $char === '-' || !isset($seatsData[$char])) {
                        continue;
                    }
                    $seatInfo = $seatsData[$char];
                    $zoneName = $seatInfo['label'] ?? ($seatInfo['zone'] ?? ($seatInfo['section'] ?? '默认区'));
                    
                    $seatPrice = floatval($seatInfo['price'] ?? 0);
                    if ($seatPrice == 0 && isset($sectionPrices[$zoneName])) {
                        $seatPrice = $sectionPrices[$zoneName];
                    }
                    
                    $seatId = $roomName . '_' . $rowLabel . '_' . ($colIndex + 1);
                    $seatDisplayName = $roomName . ' ' . $zoneName . ' ' . $rowLabel . ($colIndex + 1);
                    
                    $seatsToInsert[$seatId] = [
                        'room' => $roomName,
                        'zone' => $zoneName,
                        'row'  => $rowIndex,
                        'col'  => $colIndex,
                        'char' => $char,
                        'label' => $seatDisplayName,
                        'price' => $seatPrice
                    ];
                }
            }
        }
        
        if (empty($seatsToInsert)) {
            return ['code' => -3, 'msg' => '无有效座位可生成'];
        }

        // 查询已有 SKU
        $existingBases = 	hinkacade\Db::name('GoodsSpecBase')
            ->where('goods_id', $goodsId)
            ->column('id', 'id');
        $existingValues = [];
        if (!empty($existingBases)) {
            $valueRows = 	hinkacade\Db::name('GoodsSpecValue')
                ->where('goods_id', $goodsId)
                ->where('goods_spec_base_id', 'in', array_keys($existingBases))
                ->where('type', $typeSeat)
                ->column('value', 'goods_spec_base_id');
            foreach ($valueRows as $baseId => $val) {
                $existingValues[$val] = $baseId;
            }
        }

        $now = time();
        $generatedCount = 0;
        $specBaseIdMap = [];

        	hinkacade\Db::startTrans();
        try {
            $baseBatch = [];
            $valueBatch = [];
            foreach ($seatsToInsert as $seatId => $s) {
                if (isset($existingValues[$s['label']])) {
                    $baseId = $existingValues[$s['label']];
                    $specBaseIdMap[$seatId] = [
                        'spec_base_id' => $baseId,
                        'room' => $s['room'],
                        'zone' => $s['zone'],
                        'row' => $s['row'],
                        'col' => $s['col']
                    ];
                    continue; // 已经存在，查出来返回映射即可
                }

                $baseId = 	hinkacade\Db::name('GoodsSpecBase')->insertGetId([
                    'goods_id'   => $goodsId,
                    'price'      => $s['price'],
                    'inventory'  => 1,
                    'weight'     => 0,
                    'volume'     => 0,
                    'coding'     => '',
                    'barcode'    => '',
                    'add_time'   => $now,
                ]);

                $valueBatch[] = ['goods_id' => $goodsId, 'goods_spec_base_id' => $baseId, 'type' => $typeVenue, 'value' => $venueName, 'add_time' => $now];
                $valueBatch[] = ['goods_id' => $goodsId, 'goods_spec_base_id' => $baseId, 'type' => $typeZone,  'value' => $s['room'] . '-' . $s['zone'], 'add_time' => $now];
                $valueBatch[] = ['goods_id' => $goodsId, 'goods_spec_base_id' => $baseId, 'type' => $typeTime,  'value' => '不限时段', 'add_time' => $now];
                $valueBatch[] = ['goods_id' => $goodsId, 'goods_spec_base_id' => $baseId, 'type' => $typeSeat,  'value' => $s['label'], 'add_time' => $now];

                $specBaseIdMap[$seatId] = [
                    'spec_base_id' => $baseId,
                    'room' => $s['room'],
                    'zone' => $s['zone'],
                    'row' => $s['row'],
                    'col' => $s['col']
                ];

                $generatedCount++;

                if (count($valueBatch) >= self::BATCH_SIZE) {
                    	hinkacade\Db::name('GoodsSpecValue')->insertAll($valueBatch);
                    $valueBatch = [];
                }
            }

            if (!empty($valueBatch)) {
                	hinkacade\Db::name('GoodsSpecValue')->insertAll($valueBatch);
            }

            	hinkacade\Db::commit();

            return [
                'code' => 0,
                'msg'  => '生成成功',
                'data' => [
                    'total' => count($seatsToInsert),
                    'generated' => $generatedCount,
                    'spec_base_id_map' => $specBaseIdMap,
                ]
            ];

        } catch (\Exception $e) {
            	hinkacade\Db::rollback();
            return ['code' => -99, 'msg' => '事务异常：' . $e->getMessage()];
        }
    }

    private static function ensureVrSpecTypes(int $goodsId, string $venueName): array
    {
        $types = ['$vr-场馆', '$vr-分区', '$vr-时段', '$vr-座位号'];
        $typeIds = [];
        $now = time();

        $existing = 	hinkacade\Db::name('GoodsSpecType')
            ->where('goods_id', $goodsId)
            ->where('name', 'in', $types)
            ->column('id', 'name');

        foreach ($types as $name) {
            if (isset($existing[$name])) {
                $typeIds[$name] = $existing[$name];
            } else {
                $val = '';
                if ($name === '$vr-场馆') $val = $venueName;
                if ($name === '$vr-时段') $val = '不限时段';

                $id = 	hinkacade\Db::name('GoodsSpecType')->insertGetId([
                    'goods_id' => $goodsId,
                    'name'     => $name,
                    'value'    => $val,
                    'add_time' => $now,
                ]);
                if (!$id) {
                    return ['code' => -10, 'msg' => "写入规格类型 {$name} 失败"];
                }
                $typeIds[$name] = $id;
            }
        }

        return ['code' => 0, 'data' => $typeIds];
    }
}
