<?php

declare(strict_types=1);

namespace App\Platform\Tmall\EntityParse;

use App\Constants\ProductStatus;
use App\Model\Company;
use App\Model\Store;
use App\Platform\AbstractProductParse;
use App\Platform\Tmall\Constants\ItemStatus;
use Carbon\Carbon;
use Hyperf\Collection\LazyCollection;
use InvalidArgumentException;

/**
 * 天猫产品解析器
 *
 * 将 Tmall 产品原始数据解析为本地 Product 模型格式
 */
class Product extends AbstractProductParse
{
    /**
     * 公司作用域匹配
     *
     * @param array $metadata
     * @return Company
     * @throws InvalidArgumentException
     */
    public function companyScopeMatch(array $metadata): Company
    {
        if (!isset($metadata['company_id'])) {
            throw new InvalidArgumentException('company_id is required in metadata');
        }

        $company_id = $metadata['company_id'];
        $company = Company::find($company_id);

        if (!$company) {
            throw new InvalidArgumentException("Company with ID {$company_id} not found");
        }

        return $company;
    }

    /**
     * 店铺作用域匹配
     *
     * @param array $metadata
     * @return Store
     * @throws InvalidArgumentException
     */
    public function storeScopeMatch(array $metadata): Store
    {
        if (!isset($metadata['store_id'])) {
            throw new InvalidArgumentException('store_id is required in metadata');
        }

        $store_id = $metadata['store_id'];
        $store = Store::find($store_id);

        if (!$store) {
            throw new InvalidArgumentException("Store with ID {$store_id} not found");
        }

        return $store;
    }

    /**
     * 实体数据映射
     *
     * 将原始产品数据映射为可供 Product Model 使用的数组集合
     * 
     * 每个 SKU 规格生成一条独立记录。
     * 
     * Tmall 平台两种场景，数据结构有区别，分别为
     * 1. 单个商品为一个独立 SKU
     * 2. 单个商品为套装或组合商品，内部包含多个 SKU
     *
     * @param array $raw_data 原始数据数组
     * @return LazyCollection
     */
    public function entityMap(array $raw_data): LazyCollection
    {
        return LazyCollection::make(function () use ($raw_data) {
            $records = isset($raw_data[0]) ? $raw_data : [$raw_data];

            foreach ($records as $record) {
                $skus = $record['skus']['sku'] ?? [];

                if (empty($skus)) {
                    // 无 SKU 规格商品，单条记录
                    yield $this->mapSingleProduct($record, null);
                } else {
                    // 有 SKU 规格商品，每个 SKU 一条记录
                    foreach ($skus as $sku) {
                        yield $this->mapSingleProduct($record, $sku);
                    }
                }
            }
        });
    }

    /**
     * 映射单个产品记录
     *
     * @param array $record 商品主记录
     * @param array|null $sku SKU 规格记录
     * @return array
     */
    private function mapSingleProduct(array $record, ?array $sku): array
    {
        $raw = \json_encode($record);
        $platform_item_id = (string) $record['num_iid'];
        $platform_model_id = $sku ? (string) $sku['sku_id'] : null;

        return [
            'company_id' => $this->getCompany()->id,
            'platform_id' => $this->getPlatform()->id,
            'store_id' => $this->getStore()->id,
            'status_id' => $this->getProductStatusId($record['approve_status'] ?? ItemStatus::ONSALE->value),
            'type_id' => 1, // 默认类型
            'warehouse_id' => null,
            'sub_warehouse_id' => null,
            'platform_item_id' => $platform_item_id,
            'platform_model_id' => $platform_model_id,
            'origin_sku_id' => $sku['outer_id'] ?? $record['outer_id'] ?? null,
            'mapped_sku_id' => null,
            'barcode' => $sku['barcode'] ?? $sku['outer_id']  ?? $record['outer_id'] ?? null,
            'hscode' => null,
            'bundled' => null,
            'price' => $sku['price'] ?? $record['price'] ?? '0.00',
            'currency' => 'CNY',
            'num' => $sku['quantity'] ?? $record['num'] ?? 0,
            'url' => $record['detail_url'] ?? null,
            'picture' => $record['pic_url'] ?? null,
            'name' => $record['title'] ?? null,
            'raw' => $raw,
            'ext' => null,
            'hash' => \md5($raw),
            'created_date' => isset($record['created']) ? Carbon::parse($record['created'], $this->getStore()->getTimezoneString())->format('Y-m-d H:i:sP') : null,
            'updated_date' => isset($record['modified']) ? Carbon::parse($record['modified'], $this->getStore()->getTimezoneString())->format('Y-m-d H:i:sP') : null,
            'created_at' => Carbon::now()->format('Y-m-d H:i:sP'),
            'updated_at' => Carbon::now()->format('Y-m-d H:i:sP'),
        ];
    }

    /**
     * 获取唯一键字段
     *
     * 对应数据库约束：products_store_item_model_unique
     *
     * @return array
     */
    public function getUniqueBy(): array
    {
        return ['store_id', 'platform_item_id', 'platform_model_id'];
    }

    /**
     * 获取可更新字段列表
     *
     * @return array
     */
    public function getUpdateFields(): array
    {
        return [
            'status_id',
            'type_id',
            'warehouse_id',
            'sub_warehouse_id',
            'origin_sku_id',
            'mapped_sku_id',
            'barcode',
            'hscode',
            'bundled',
            'price',
            'currency',
            'num',
            'url',
            'picture',
            'name',
            'raw',
            'ext',
            'hash',
            'created_date',
            'updated_date',
            'updated_at',
        ];
    }

    /**
     * 获取产品状态 ID
     *
     * 将 Tmall 产品状态映射到本地 ProductStatus 枚举
     *
     * @see ItemStatus Tmall 平台商品状态枚举
     * @see ProductStatus 本地产品状态枚举
     *
     * @param string $platform_status Tmall 平台状态
     * @return int
     */
    public function getProductStatusId(string $platform_status): int
    {
        $status_map = [
            ItemStatus::ONSALE->value => ProductStatus::ACTIVE->value,
            ItemStatus::INSTOCK->value => ProductStatus::INACTIVE->value,
        ];

        return $status_map[$platform_status] ?? ProductStatus::INACTIVE->value;
    }
}
