package com.njcn.gather.steady.checksquare.service.impl;

import com.njcn.gather.steady.checksquare.component.SteadyChecksquareCalculator;
import com.njcn.gather.steady.checksquare.component.SteadyChecksquareInfluxQueryComponent;
import com.njcn.gather.steady.checksquare.pojo.param.SteadyChecksquareQueryParam;
import com.njcn.gather.steady.checksquare.pojo.vo.SteadyChecksquareItemVO;
import com.njcn.gather.steady.checksquare.pojo.vo.SteadyChecksquareQueryVO;
import com.njcn.gather.steady.datavie.component.SteadyTrendIndicatorCatalog;
import com.njcn.gather.tool.adddata.component.AddDataTimeSlotCalculator;
import com.njcn.gather.tool.addledger.pojo.vo.AddLedgerLinePathVO;
import com.njcn.gather.tool.addledger.service.AddLedgerService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
 * 数据校验服务测试。
 */
class SteadyChecksquareServiceImplTest {

    @Test
    void shouldUseFixedFlickerIntervalsPerIndicator() {
        SteadyChecksquareInfluxQueryComponent influxQueryComponent = mock(SteadyChecksquareInfluxQueryComponent.class);
        AddLedgerService addLedgerService = mock(AddLedgerService.class);
        SteadyChecksquareServiceImpl service = new SteadyChecksquareServiceImpl(new SteadyTrendIndicatorCatalog(),
                influxQueryComponent, new SteadyChecksquareCalculator(), new AddDataTimeSlotCalculator(), addLedgerService);
        AddLedgerLinePathVO linePath = new AddLedgerLinePathVO();
        linePath.setLineId("line-001");
        linePath.setLineName("进线一");
        linePath.setLineInterval(1);
        when(addLedgerService.listLinePathByLineIds(eq(Collections.singletonList("line-001"))))
                .thenReturn(Collections.singletonMap("line-001", linePath));
        when(influxQueryComponent.queryExistingSlots(any(), any(LocalDateTime.class), any(LocalDateTime.class), eq(10)))
                .thenReturn(new HashSet<LocalDateTime>(Arrays.asList(
                        LocalDateTime.of(2026, 5, 1, 0, 0),
                        LocalDateTime.of(2026, 5, 1, 0, 10))));
        when(influxQueryComponent.queryExistingSlots(any(), any(LocalDateTime.class), any(LocalDateTime.class), eq(120)))
                .thenReturn(new HashSet<LocalDateTime>(Collections.singletonList(
                        LocalDateTime.of(2026, 5, 1, 0, 0))));

        SteadyChecksquareQueryParam param = new SteadyChecksquareQueryParam();
        param.setLineId("line-001");
        param.setIndicatorCodes(Arrays.asList("FLUC", "PST", "PLT"));
        param.setTimeStart("2026-05-01 00:00:00");
        param.setTimeEnd("2026-05-01 02:00:00");

        SteadyChecksquareQueryVO result = service.query(param);

        Assertions.assertEquals(Integer.valueOf(1), result.getIntervalMinutes());
        Assertions.assertEquals(3, result.getItems().size());
        assertItemInterval(result.getItems().get(0), "FLUC", 10, 13);
        assertItemInterval(result.getItems().get(1), "PST", 10, 13);
        assertItemInterval(result.getItems().get(2), "PLT", 120, 2);
    }

    @Test
    void shouldOnlyQueryRequestedHarmonicOrders() {
        SteadyChecksquareInfluxQueryComponent influxQueryComponent = mock(SteadyChecksquareInfluxQueryComponent.class);
        AddLedgerService addLedgerService = mock(AddLedgerService.class);
        SteadyChecksquareServiceImpl service = new SteadyChecksquareServiceImpl(new SteadyTrendIndicatorCatalog(),
                influxQueryComponent, new SteadyChecksquareCalculator(), new AddDataTimeSlotCalculator(), addLedgerService);
        AddLedgerLinePathVO linePath = new AddLedgerLinePathVO();
        linePath.setLineId("line-001");
        linePath.setLineName("进线一");
        linePath.setLineInterval(1);
        when(addLedgerService.listLinePathByLineIds(eq(Collections.singletonList("line-001"))))
                .thenReturn(Collections.singletonMap("line-001", linePath));
        when(influxQueryComponent.queryExistingSlots(any(), any(LocalDateTime.class), any(LocalDateTime.class), eq(1)))
                .thenReturn(new HashSet<LocalDateTime>(Collections.singletonList(
                        LocalDateTime.of(2026, 5, 1, 0, 0))));

        SteadyChecksquareQueryParam param = new SteadyChecksquareQueryParam();
        param.setLineId("line-001");
        param.setIndicatorCodes(Collections.singletonList("V_HARMONIC"));
        param.setHarmonicOrders(Collections.singletonList(5));
        param.setTimeStart("2026-05-01 00:00:00");
        param.setTimeEnd("2026-05-01 00:01:00");

        SteadyChecksquareQueryVO result = service.query(param);

        Assertions.assertEquals(1, result.getItems().size());
        Assertions.assertEquals(Integer.valueOf(5), result.getItems().get(0).getHarmonicOrder());
    }

    @Test
    void shouldKeepRequestedHarmonicOrdersDistinctAndOrdered() {
        SteadyChecksquareInfluxQueryComponent influxQueryComponent = mock(SteadyChecksquareInfluxQueryComponent.class);
        AddLedgerService addLedgerService = mock(AddLedgerService.class);
        SteadyChecksquareServiceImpl service = new SteadyChecksquareServiceImpl(new SteadyTrendIndicatorCatalog(),
                influxQueryComponent, new SteadyChecksquareCalculator(), new AddDataTimeSlotCalculator(), addLedgerService);
        AddLedgerLinePathVO linePath = new AddLedgerLinePathVO();
        linePath.setLineId("line-001");
        linePath.setLineName("进线一");
        linePath.setLineInterval(1);
        when(addLedgerService.listLinePathByLineIds(eq(Collections.singletonList("line-001"))))
                .thenReturn(Collections.singletonMap("line-001", linePath));
        when(influxQueryComponent.queryExistingSlots(any(), any(LocalDateTime.class), any(LocalDateTime.class), eq(1)))
                .thenReturn(new HashSet<LocalDateTime>());

        SteadyChecksquareQueryParam param = new SteadyChecksquareQueryParam();
        param.setLineId("line-001");
        param.setIndicatorCodes(Collections.singletonList("V_HARMONIC"));
        param.setHarmonicOrders(Arrays.asList(7, 5, 7));
        param.setTimeStart("2026-05-01 00:00:00");
        param.setTimeEnd("2026-05-01 00:01:00");

        SteadyChecksquareQueryVO result = service.query(param);

        List<SteadyChecksquareItemVO> items = result.getItems();
        Assertions.assertEquals(2, items.size());
        Assertions.assertEquals(Integer.valueOf(7), items.get(0).getHarmonicOrder());
        Assertions.assertEquals(Integer.valueOf(5), items.get(1).getHarmonicOrder());
    }

    private void assertItemInterval(SteadyChecksquareItemVO item, String indicatorCode, int intervalMinutes, int expectedPointCount) {
        Assertions.assertEquals(indicatorCode, item.getIndicatorCode());
        Assertions.assertEquals(Integer.valueOf(intervalMinutes), item.getIntervalMinutes());
        Assertions.assertEquals(Integer.valueOf(expectedPointCount), item.getExpectedPointCount());
    }
}
