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

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.web.modules.industryservice.domain.dto.OpenApiPageResult;
import com.ruoyi.web.modules.industryservice.domain.dto.OpenApiResponse;
import com.ruoyi.web.modules.industryservice.domain.dto.OpenBreedingProcessRecordDto;
import com.ruoyi.web.modules.industryservice.domain.dto.OpenDiagnosisRecordDto;
import com.ruoyi.web.modules.industryservice.domain.dto.OpenQuarantineRecordDto;

/**
 * 第三方健康源数据客户端：stub 读取 classpath JSON；http 分页调用开放接口。
 */
@Component
public class ThirdPartyHealthRecordClientImpl implements ThirdPartyHealthRecordClient
{
    private static final String STUB_QUARANTINE = "thirdparty/stub-quarantine-records.json";

    private static final String STUB_DIAGNOSIS = "thirdparty/stub-diagnosis-records.json";

    private static final String STUB_BREEDING = "thirdparty/stub-process-records.json";

    private static final String QUARANTINE_PATH = "/open-api/v1/farming/quarantine-records";

    private static final String DIAGNOSIS_PATH = "/open-api/v1/farming/diagnosis-records";

    private static final String BREEDING_PATH = "/open-api/v1/farming/process-records";

    private final ObjectMapper objectMapper = ThirdPartyFarmingHttpSupport.createObjectMapper();

    @Autowired
    private ThirdPartyFarmingProperties properties;

    @Override
    public List<OpenQuarantineRecordDto> fetchQuarantineRecords()
    {
        ensureEnabled();
        if (isHttpMode())
        {
            return fetchPaged(QUARANTINE_PATH, new TypeReference<OpenApiResponse<OpenApiPageResult<OpenQuarantineRecordDto>>>()
            {
            });
        }
        return readStub(STUB_QUARANTINE, new TypeReference<List<OpenQuarantineRecordDto>>()
        {
        });
    }

    @Override
    public List<OpenDiagnosisRecordDto> fetchDiagnosisRecords()
    {
        ensureEnabled();
        if (isHttpMode())
        {
            return fetchPaged(DIAGNOSIS_PATH, new TypeReference<OpenApiResponse<OpenApiPageResult<OpenDiagnosisRecordDto>>>()
            {
            });
        }
        return readStub(STUB_DIAGNOSIS, new TypeReference<List<OpenDiagnosisRecordDto>>()
        {
        });
    }

    @Override
    public List<OpenBreedingProcessRecordDto> fetchBreedingProcessRecords()
    {
        ensureEnabled();
        if (isHttpMode())
        {
            return fetchPaged(BREEDING_PATH,
                    new TypeReference<OpenApiResponse<OpenApiPageResult<OpenBreedingProcessRecordDto>>>()
                    {
                    });
        }
        return readStub(STUB_BREEDING, new TypeReference<List<OpenBreedingProcessRecordDto>>()
        {
        });
    }

    private void ensureEnabled()
    {
        if (!properties.isEnabled())
        {
            throw new ServiceException("第三方健康数据同步未启用");
        }
    }

    private boolean isHttpMode()
    {
        return "http".equalsIgnoreCase(properties.getMode());
    }

    private <T> List<T> readStub(String resource, TypeReference<List<T>> typeRef)
    {
        try
        {
            ClassPathResource file = new ClassPathResource(resource);
            if (!file.exists())
            {
                return Collections.emptyList();
            }
            try (InputStream in = file.getInputStream())
            {
                String json = StreamUtils.copyToString(in, StandardCharsets.UTF_8);
                return objectMapper.readValue(json, typeRef);
            }
        }
        catch (ServiceException e)
        {
            throw e;
        }
        catch (Exception e)
        {
            throw new ServiceException("读取第三方样例失败：" + e.getMessage());
        }
    }

    private <T> List<T> fetchPaged(String path, TypeReference<OpenApiResponse<OpenApiPageResult<T>>> typeRef)
    {
        ThirdPartyFarmingHttpSupport.requireBaseUrl(properties, "第三方生产管理系统 base-url 未配置");
        RestTemplate restTemplate = ThirdPartyFarmingHttpSupport.createRestTemplate(properties);
        HttpHeaders headers = ThirdPartyFarmingHttpSupport.buildOpenApiHeaders(properties);
        List<T> all = new ArrayList<>();
        int pageNum = 1;
        int pageSize = Math.min(Math.max(properties.getPageSize(), 1), 200);
        Long total = null;
        while (true)
        {
            String url = UriComponentsBuilder.fromHttpUrl(ThirdPartyFarmingHttpSupport.resolveUrl(properties, path))
                    .queryParam("pageNum", pageNum)
                    .queryParam("pageSize", pageSize)
                    .toUriString();
            try
            {
                ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET,
                        new HttpEntity<>(headers), String.class);
                if (!response.getStatusCode().is2xxSuccessful() || response.getBody() == null)
                {
                    throw new ServiceException("第三方接口返回异常");
                }
                OpenApiResponse<OpenApiPageResult<T>> body = objectMapper.readValue(response.getBody(), typeRef);
                if (body == null || body.getCode() == null || body.getCode() != 0)
                {
                    String msg = body != null && StringUtils.hasText(body.getMessage()) ? body.getMessage() : "业务失败";
                    throw new ServiceException("第三方接口：" + msg);
                }
                OpenApiPageResult<T> page = body.getData();
                if (page == null || CollectionUtils.isEmpty(page.getRecords()))
                {
                    break;
                }
                all.addAll(page.getRecords());
                if (total == null && page.getTotal() != null)
                {
                    total = page.getTotal();
                }
                if (page.getRecords().size() < pageSize)
                {
                    break;
                }
                if (total != null && all.size() >= total)
                {
                    break;
                }
                pageNum++;
            }
            catch (ServiceException e)
            {
                throw e;
            }
            catch (RestClientException e)
            {
                throw new ServiceException("第三方服务不可用：" + e.getMessage());
            }
            catch (Exception e)
            {
                throw new ServiceException("解析第三方数据失败：" + e.getMessage());
            }
        }
        return all;
    }
}
