package com.njcn.gather.steady.datavie.component;

import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.gather.steady.datavie.pojo.bo.SteadyTrendResolvedFieldBO;
import com.njcn.gather.steady.datavie.pojo.param.SteadyTrendQueryParam;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 稳态趋势字段解析测试。
 */
class SteadyTrendFieldResolverTest {

    private SteadyTrendFieldResolver resolver;

    @BeforeEach
    void setUp() {
        resolver = new SteadyTrendFieldResolver(new SteadyTrendIndicatorCatalog());
    }

    @Test
    void shouldExpandAllCatalogPhasesWithoutRequestPhaseFilter() {
        SteadyTrendQueryParam param = new SteadyTrendQueryParam();
        param.setLineIds(Arrays.asList("line-001"));
        param.setIndicatorCodes(Arrays.asList("V_RMS"));
        param.setStatTypes(Arrays.asList("AVG"));
        param.setTimeStart("2026-05-01 00:00:00");
        param.setTimeEnd("2026-05-01 01:00:00");

        List<SteadyTrendResolvedFieldBO> fields = resolver.resolveFields(param);
        List<String> phases = fields.stream().map(SteadyTrendResolvedFieldBO::getPhase).collect(Collectors.toList());

        Assertions.assertEquals(Arrays.asList("A", "B", "C"), phases);
    }

    @Test
    void shouldResolveVoltageRmsToActualInfluxField() {
        SteadyTrendQueryParam param = new SteadyTrendQueryParam();
        param.setLineIds(Arrays.asList("00B78D00A8791"));
        param.setIndicatorCodes(Arrays.asList("V_RMS"));
        param.setStatTypes(Arrays.asList("AVG"));
        param.setTimeStart("2026-05-01 00:00:00");
        param.setTimeEnd("2026-05-01 01:00:00");

        List<SteadyTrendResolvedFieldBO> fields = resolver.resolveFields(param);

        Assertions.assertEquals("rms", fields.get(0).getField());
        Assertions.assertEquals("00B78D00A8791|V_RMS|A|AVG|rms", fields.get(0).getSeriesKey());
    }

    @Test
    void shouldExpandLineVoltageIndicatorWithQueryPhases() {
        SteadyTrendQueryParam param = new SteadyTrendQueryParam();
        param.setLineIds(Arrays.asList("line-001"));
        param.setIndicatorCodes(Arrays.asList("V_LINE_RMS"));
        param.setStatTypes(Arrays.asList("AVG"));
        param.setTimeStart("2026-05-01 00:00:00");
        param.setTimeEnd("2026-05-01 01:00:00");

        List<SteadyTrendResolvedFieldBO> fields = resolver.resolveFields(param);
        List<String> phases = fields.stream().map(SteadyTrendResolvedFieldBO::getPhase).collect(Collectors.toList());

        Assertions.assertEquals(Arrays.asList("A", "B", "C"), phases);
        Assertions.assertEquals("rms_lvr", fields.get(0).getField());
    }

    @Test
    void shouldResolveCommonIndicatorsToActualInfluxFields() {
        Assertions.assertEquals("freq", resolveSingleField("FREQ"));
        Assertions.assertEquals("v_thd", resolveSingleField("V_THD"));
        Assertions.assertEquals("rms", resolveSingleField("I_RMS"));
        Assertions.assertEquals("i_thd", resolveSingleField("I_THD"));
        Assertions.assertEquals("fluc", resolveSingleField("FLUC"));
        Assertions.assertEquals("pst", resolveSingleField("PST"));
        Assertions.assertEquals("plt", resolveSingleField("PLT"));
    }

    @Test
    void shouldExposeActualInfluxFieldsInIndicatorCatalog() {
        SteadyTrendIndicatorCatalog catalog = new SteadyTrendIndicatorCatalog();

        Assertions.assertEquals("rms", catalog.getIndicator("V_RMS").getSeriesFields().get(0).getField());
        Assertions.assertEquals("rms_lvr", catalog.getIndicator("V_LINE_RMS").getSeriesFields().get(0).getField());
        Assertions.assertEquals("freq", catalog.getIndicator("FREQ").getSeriesFields().get(0).getField());
        Assertions.assertEquals("v_thd", catalog.getIndicator("V_THD").getSeriesFields().get(0).getField());
        Assertions.assertEquals("rms", catalog.getIndicator("I_RMS").getSeriesFields().get(0).getField());
        Assertions.assertEquals("i_thd", catalog.getIndicator("I_THD").getSeriesFields().get(0).getField());
        Assertions.assertEquals("fluc", catalog.getIndicator("FLUC").getSeriesFields().get(0).getField());
        Assertions.assertEquals("pst", catalog.getIndicator("PST").getSeriesFields().get(0).getField());
        Assertions.assertEquals("plt", catalog.getIndicator("PLT").getSeriesFields().get(0).getField());
    }

    @Test
    void shouldRejectHarmonicTrendWithoutOrders() {
        SteadyTrendQueryParam param = new SteadyTrendQueryParam();
        param.setLineIds(Arrays.asList("line-001"));
        param.setIndicatorCodes(Arrays.asList("V_HARMONIC"));
        param.setStatTypes(Arrays.asList("AVG"));
        param.setTimeStart("2026-05-01 00:00:00");
        param.setTimeEnd("2026-05-01 01:00:00");

        BusinessException exception = Assertions.assertThrows(BusinessException.class, () -> resolver.resolveFields(param));

        Assertions.assertTrue(exception.getMessage().contains("谐波次数不能为空"));
    }

    @Test
    void shouldRejectHarmonicTrendWithMoreThanThreeOrders() {
        SteadyTrendQueryParam param = new SteadyTrendQueryParam();
        param.setLineIds(Arrays.asList("line-001"));
        param.setIndicatorCodes(Arrays.asList("V_HARMONIC"));
        param.setStatTypes(Arrays.asList("AVG"));
        param.setHarmonicOrders(Arrays.asList(3, 5, 7, 11));
        param.setTimeStart("2026-05-01 00:00:00");
        param.setTimeEnd("2026-05-01 01:00:00");

        BusinessException exception = Assertions.assertThrows(BusinessException.class, () -> resolver.resolveFields(param));

        Assertions.assertTrue(exception.getMessage().contains("谐波次数不允许一次展示超过3个"));
    }

    @Test
    void shouldResolveSelectedHarmonicOrdersForAllCatalogPhases() {
        SteadyTrendQueryParam param = new SteadyTrendQueryParam();
        param.setLineIds(Arrays.asList("line-001"));
        param.setIndicatorCodes(Arrays.asList("V_HARMONIC"));
        param.setStatTypes(Arrays.asList("MAX"));
        param.setHarmonicOrders(Arrays.asList(3, 5));
        param.setTimeStart("2026-05-01 00:00:00");
        param.setTimeEnd("2026-05-01 01:00:00");

        List<SteadyTrendResolvedFieldBO> fields = resolver.resolveFields(param);

        Assertions.assertEquals(6, fields.size());
        Assertions.assertEquals("A", fields.get(0).getPhase());
        Assertions.assertEquals("v_3", fields.get(0).getField());
        Assertions.assertEquals("v_5", fields.get(1).getField());
        Assertions.assertEquals("B", fields.get(2).getPhase());
        Assertions.assertEquals("C", fields.get(4).getPhase());
    }

    @Test
    void shouldResolveHarmonicPowerToActualInfluxField() {
        SteadyTrendQueryParam param = new SteadyTrendQueryParam();
        param.setLineIds(Arrays.asList("line-001"));
        param.setIndicatorCodes(Arrays.asList("P_HARMONIC_POWER"));
        param.setStatTypes(Arrays.asList("CP95"));
        param.setHarmonicOrders(Arrays.asList(3));
        param.setTimeStart("2026-05-01 00:00:00");
        param.setTimeEnd("2026-05-01 01:00:00");

        List<SteadyTrendResolvedFieldBO> fields = resolver.resolveFields(param);

        Assertions.assertEquals("p_3", fields.get(0).getField());
    }

    private String resolveSingleField(String indicatorCode) {
        SteadyTrendQueryParam param = new SteadyTrendQueryParam();
        param.setLineIds(Arrays.asList("line-001"));
        param.setIndicatorCodes(Arrays.asList(indicatorCode));
        param.setStatTypes(Arrays.asList("AVG"));
        param.setTimeStart("2026-05-01 00:00:00");
        param.setTimeEnd("2026-05-01 01:00:00");
        return resolver.resolveFields(param).get(0).getField();
    }
}
