package com.ruoyi.web.modules.industryservice.support;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.modules.industryservice.domain.BizYakAsset;
import com.ruoyi.web.modules.industryservice.domain.dto.OpenYakEntryDto;
import com.ruoyi.web.modules.industryservice.domain.dto.YakAssetBundleDto;

/**
 * 将第三方入栏建档 OpenAPI 记录映射为本地同步数据包 {@link YakAssetBundleDto}。
 * <p>
 * 接口：{@code GET /open-api/v1/farming/entry-filings}，单条 Schema 为 {@link OpenYakEntryDto}。
 * </p>
 *
 * <h3>主表字段映射（OpenYakEntryDto → BizYakAsset）</h3>
 * <ul>
 *   <li>cattleId → externalId</li>
 *   <li>cattleNo → yakNo</li>
 *   <li>earTagNumber → earTagNumber</li>
 *   <li>farmId → farmExternalId（并供 pasture_id 解析）</li>
 *   <li>farmName → pastureName</li>
 *   <li>farmEnclosureId → enclosureExternalId</li>
 *   <li>farmEnclosureName → enclosureName / penLocation</li>
 *   <li>batchId → batchExternalId</li>
 *   <li>entryCycle → entryCycle</li>
 *   <li>farmLocation → location</li>
 *   <li>cattleSex → gender（规范为 公/母）</li>
 *   <li>cattleSource → source</li>
 *   <li>cattleVariety → cattleVariety</li>
 *   <li>cattlePicture → cattlePicture</li>
 *   <li>registrant → registrant</li>
 *   <li>weight → entryWeightKg</li>
 *   <li>entryTime / birthDate → entryDate / birthDate</li>
 *   <li>fatherNumber / motherNumber → fatherYakNo / motherYakNo</li>
 *   <li>remark → remark</li>
 * </ul>
 */
public final class YakEntryOpenApiMapper
{
    private static final SimpleDateFormat DATE_TIME = createDateTimeFormat();

    private static final SimpleDateFormat DATE_ONLY = createDateOnlyFormat();

    private YakEntryOpenApiMapper()
    {
    }

    /**
     * 单条入栏建档 → 同步数据包。
     *
     * @param dto 开放接口 records 中单条
     * @return 含主表 asset 及 thirdPartyPastureCode；子表列表均为 null
     */
    public static YakAssetBundleDto toBundle(OpenYakEntryDto dto)
    {
        if (dto == null)
        {
            throw new ServiceException("同步数据无效");
        }
        if (dto.getCattleId() == null)
        {
            throw new ServiceException("第三方牛只 ID 不能为空");
        }
        String yakNo = resolveYakNo(dto);
        YakAssetValidation.validateYakNoForSync(yakNo);

        BizYakAsset asset = new BizYakAsset();
        asset.setExternalId(dto.getCattleId());
        asset.setYakNo(yakNo);
        asset.setEarTagNumber(trimToNull(dto.getEarTagNumber()));
        asset.setFarmExternalId(dto.getFarmId());
        asset.setPastureName(trimToNull(dto.getFarmName()));
        asset.setEnclosureExternalId(dto.getFarmEnclosureId());
        String enclosureName = trimToNull(dto.getFarmEnclosureName());
        asset.setEnclosureName(enclosureName);
        asset.setPenLocation(enclosureName);
        asset.setBatchExternalId(dto.getBatchId());
        asset.setEntryCycle(trimToNull(dto.getEntryCycle()));
        asset.setGender(normalizeGender(dto.getCattleSex()));
        asset.setCattleVariety(trimToNull(dto.getCattleVariety()));
        asset.setCattlePicture(trimToNull(dto.getCattlePicture()));
        asset.setRegistrant(trimToNull(dto.getRegistrant()));
        asset.setBirthDate(parseDate(dto.getBirthDate()));
        asset.setEntryDate(parseDate(dto.getEntryTime()));
        asset.setEntryWeightKg(toBigDecimal(dto.getWeight()));
        asset.setSource(trimToNull(dto.getCattleSource()));
        asset.setLocation(trimToNull(dto.getFarmLocation()));
        asset.setFatherYakNo(trimToNull(dto.getFatherNumber()));
        asset.setMotherYakNo(trimToNull(dto.getMotherNumber()));
        asset.setRemark(trimToNull(dto.getRemark()));
        asset.setAssetStatus(YakAssetRules.ASSET_STATUS_MIN);

        YakAssetBundleDto bundle = new YakAssetBundleDto();
        bundle.setAsset(asset);
        if (dto.getFarmId() != null)
        {
            bundle.setThirdPartyPastureCode(String.valueOf(dto.getFarmId()));
        }
        return bundle;
    }

    /** 场内牛只编号 cattleNo */
    private static String resolveYakNo(OpenYakEntryDto dto)
    {
        if (StringUtils.isNotEmpty(dto.getCattleNo()))
        {
            return dto.getCattleNo().trim();
        }
        return null;
    }

    private static String normalizeGender(String cattleSex)
    {
        if (StringUtils.isEmpty(cattleSex))
        {
            return null;
        }
        String sex = cattleSex.trim();
        if ("1".equals(sex) || "M".equalsIgnoreCase(sex) || "公".equals(sex))
        {
            return "公";
        }
        if ("2".equals(sex) || "F".equalsIgnoreCase(sex) || "母".equals(sex))
        {
            return "母";
        }
        return sex;
    }

    public static List<YakAssetBundleDto> toBundles(List<OpenYakEntryDto> entries)
    {
        if (entries == null || entries.isEmpty())
        {
            return Collections.emptyList();
        }
        List<YakAssetBundleDto> bundles = new ArrayList<>(entries.size());
        for (OpenYakEntryDto entry : entries)
        {
            bundles.add(toBundle(entry));
        }
        return bundles;
    }

    private static BigDecimal toBigDecimal(Double value)
    {
        return value == null ? null : BigDecimal.valueOf(value);
    }

    private static String trimToNull(String value)
    {
        if (StringUtils.isEmpty(value))
        {
            return null;
        }
        return value.trim();
    }

    private static Date parseDate(String value)
    {
        if (StringUtils.isEmpty(value))
        {
            return null;
        }
        String text = value.trim();
        try
        {
            synchronized (DATE_TIME)
            {
                if (text.length() > 10)
                {
                    return DATE_TIME.parse(text);
                }
            }
            synchronized (DATE_ONLY)
            {
                return DATE_ONLY.parse(text);
            }
        }
        catch (ParseException e)
        {
            return null;
        }
    }

    private static SimpleDateFormat createDateTimeFormat()
    {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        df.setTimeZone(TimeZone.getTimeZone("GMT+8"));
        df.setLenient(false);
        return df;
    }

    private static SimpleDateFormat createDateOnlyFormat()
    {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        df.setTimeZone(TimeZone.getTimeZone("GMT+8"));
        df.setLenient(false);
        return df;
    }
}
