<?php

declare(strict_types=1);

namespace App\Entity\Parse;

use App\Model\Company;
use App\Model\Platform;
use App\Model\Store;
use App\Model\Model as Entity;
use Hyperf\Collection\LazyCollection;
use PhpAmqpLib\Message\AMQPMessage;

/**
 * EntityParseInterface 接口
 *
 * 定义消息解析器的标准接口
 */
interface EntityParseInterface
{
    /**
     * 消息数据验证
     *
     * 验证消息数据是否包含必需字段
     *
     * @param array $data
     * @return bool
     */
    public function messageValidate(array $data): bool;

    /**
     * 公司作用域匹配
     *
     * @param array $metadata
     * @return Company
     */
    public function companyScopeMatch(array $metadata): Company;

    /**
     * 平台作用域匹配
     *
     * @param array $metadata
     * @return Platform
     */
    public function platformScopeMatch(array $metadata): Platform;

    /**
     * 店铺作用域匹配
     *
     * @param array $metadata
     * @return Store
     */
    public function storeScopeMatch(array $metadata): Store;

    /**
     * 实体类型匹配
     *
     * 根据 metadata 返回实体模板实例
     *
     * @param array $metadata
     * @return Entity
     */
    public function entityMatch(array $metadata): Entity;

    /**
     * 实体数据映射
     *
     * 将原始数据转换为可填充到 Model 的数据集合
     *
     * @param array $rawData
     * @return LazyCollection
     */
    public function entityMap(array $rawData): LazyCollection;

    /**
     * 获取实体的唯一键字段（用于 upsert 的 uniqueBy 参数）
     *
     * 定义哪些字段组成唯一约束
     *
     * @return array 唯一键字段名数组
     */
    public function getUniqueBy(): array;

    /**
     * 获取可更新的字段列表（用于 upsert 的 update 参数）
     *
     * 明确定义哪些字段在更新时可以被修改
     * 通常需要排除：主键、唯一键、创建时间、关联 ID 等不应变更的字段
     *
     * @return array 可更新字段名数组
     */
    public function getUpdateFields(): array;

    /**
     * 获取消息数据
     *
     * @return array
     */
    public function getData(): array;

    /**
     * 获取消息对象
     *
     * @return AMQPMessage
     */
    public function getMessage(): AMQPMessage;

    /**
     * 获取平台对象
     *
     * @return Platform
     */
    public function getPlatform(): Platform;

    /**
     * 获取公司对象
     *
     * @return Company
     */
    public function getCompany(): Company;

    /**
     * 获取店铺对象
     *
     * @return Store
     */
    public function getStore(): Store;
}
