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.BizYakBatchRel;
import com.ruoyi.web.modules.industryservice.domain.BizYakPenRel;
import com.ruoyi.web.modules.industryservice.domain.dto.OpenYakEntryDto;
import com.ruoyi.web.modules.industryservice.domain.dto.YakAssetBundleDto;

/**
 * 将第三方入栏建档 OpenAPI 记录映射为本地同步数据包。
 */
public final class YakEntryOpenApiMapper
{
    private static final SimpleDateFormat DATE_TIME = createDateTimeFormat();

    private static final SimpleDateFormat DATE_ONLY = createDateOnlyFormat();

    private YakEntryOpenApiMapper()
    {
    }

    public static YakAssetBundleDto toBundle(OpenYakEntryDto dto)
    {
        if (dto == null)
        {
            throw new ServiceException("同步数据无效");
        }
        String yakNo = resolveYakNo(dto);
        if (StringUtils.isEmpty(yakNo))
        {
            throw new ServiceException("牦牛编号不能为空");
        }
        Long externalId = dto.getCattleId() != null ? dto.getCattleId() : dto.getId();
        if (externalId == null)
        {
            throw new ServiceException("第三方牛只 ID 不能为空");
        }

        BizYakAsset asset = new BizYakAsset();
        asset.setExternalId(externalId);
        asset.setYakNo(yakNo);
        asset.setPastureName(trimToNull(dto.getFarmName()));
        asset.setBatchNo(resolveBatchNo(dto));
        asset.setGender(normalizeGender(dto.getCattleSex()));
        asset.setBirthDate(parseDate(dto.getBirthDate()));
        asset.setEntryDate(parseDate(dto.getEntryTime()));
        asset.setEntryWeightKg(toBigDecimal(dto.getWeight()));
        asset.setSource(trimToNull(dto.getCattleSource()));
        asset.setPenLocation(trimToNull(dto.getFarmEnclosureName()));
        asset.setLocation(trimToNull(dto.getFarmLocation()));
        asset.setFatherYakNo(trimToNull(dto.getFatherNumber()));
        asset.setMotherYakNo(trimToNull(dto.getMotherNumber()));
        asset.setStatusChangeReason(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()));
        }
        bundle.setPenRecords(buildPenRecords(dto));
        bundle.setBatchRecords(buildBatchRecords(dto, asset.getBatchNo()));
        return bundle;
    }

    private static String resolveYakNo(OpenYakEntryDto dto)
    {
        if (StringUtils.isNotEmpty(dto.getEarTagNumber()))
        {
            return dto.getEarTagNumber().trim();
        }
        if (StringUtils.isNotEmpty(dto.getCattleNo()))
        {
            return dto.getCattleNo().trim();
        }
        return null;
    }

    private static String resolveBatchNo(OpenYakEntryDto dto)
    {
        if (StringUtils.isNotEmpty(dto.getEntryCycle()))
        {
            return dto.getEntryCycle().trim();
        }
        if (dto.getBatchId() != null)
        {
            return String.valueOf(dto.getBatchId());
        }
        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;
    }

    private static List<BizYakPenRel> buildPenRecords(OpenYakEntryDto dto)
    {
        if (StringUtils.isEmpty(dto.getFarmEnclosureName()))
        {
            return null;
        }
        BizYakPenRel pen = new BizYakPenRel();
        pen.setPenName(dto.getFarmEnclosureName().trim());
        return Collections.singletonList(pen);
    }

    private static List<BizYakBatchRel> buildBatchRecords(OpenYakEntryDto dto, String batchNo)
    {
        String resolved = batchNo;
        if (StringUtils.isEmpty(resolved))
        {
            return null;
        }
        BizYakBatchRel batch = new BizYakBatchRel();
        batch.setBatchNo(resolved);
        return Collections.singletonList(batch);
    }

    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;
    }
}
