package com.zcloud.personnel.positioning.command;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zcloud.personnel.positioning.integration.finds.FindsOpenApiClient;
import com.zcloud.personnel.positioning.persistence.dataobject.AlarmRecordDO;
import com.zcloud.personnel.positioning.persistence.dataobject.AlarmRecordTargetDO;
import com.zcloud.personnel.positioning.persistence.dataobject.OpenapiConfigDO;
import com.zcloud.personnel.positioning.persistence.repository.AlarmRecordRepository;
import com.zcloud.personnel.positioning.persistence.repository.AlarmRecordTargetRepository;
import com.zcloud.personnel.positioning.persistence.repository.OpenapiConfigRepository;
import com.zcloud.personnel.positioning.persistence.repository.SyncTaskRepository;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.transaction.support.TransactionTemplate;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

class AlarmRecordFindsPullServiceTest {
    private final ObjectMapper objectMapper = new ObjectMapper();
    private AlarmRecordRepository alarmRecordRepository;
    private AlarmRecordTargetRepository alarmRecordTargetRepository;
    private FindsPersonCorpResolver personCorpResolver;
    private AlarmRecordFindsPullService service;

    @BeforeEach
    void setUp() {
        alarmRecordRepository = mock(AlarmRecordRepository.class);
        alarmRecordTargetRepository = mock(AlarmRecordTargetRepository.class);
        personCorpResolver = mock(FindsPersonCorpResolver.class);
        service = new AlarmRecordFindsPullService(
                mock(FindsOpenApiClient.class),
                mock(OpenapiConfigRepository.class),
                alarmRecordRepository,
                alarmRecordTargetRepository,
                mock(SyncTaskRepository.class),
                objectMapper,
                mock(TransactionTemplate.class),
                mock(FindsCorpMappingService.class),
                personCorpResolver);
    }

    @Test
    void existingAlarmIsFoundWithoutCompanyConditionAndTargetUsesResolvedCompany() throws Exception {
        AlarmRecordDO existing = new AlarmRecordDO();
        existing.setId(100L);
        when(alarmRecordRepository.getOne(any(QueryWrapper.class), eq(false))).thenReturn(existing);
        FindsCorpMappingService.CorpMatch company = new FindsCorpMappingService.CorpMatch(
                "LOCAL-9", "本平台九公司", null, null, "PERSONNEL_MATCH");
        when(personCorpResolver.resolve(any(), any(), any(), any())).thenReturn(company);
        OpenapiConfigDO config = new OpenapiConfigDO();
        config.setConfigCode("FINDS");
        config.setCorpinfoId("0");
        JsonNode row = objectMapper.readTree("{\"id\":9001,\"alarmNo\":\"A9001\","
                + "\"trackInfoList\":[{\"trackType\":\"STAFF\",\"trackNo\":\"F009\","
                + "\"trackName\":\"测试人员\",\"idCardNo\":\"ID009\"}],"
                + "\"terminalNoList\":[\"T009\"]}");

        AlarmRecordDO result = service.upsertRecord(config, row);

        assertEquals("LOCAL-9", result.getCorpinfoId());
        verify(alarmRecordRepository).updateById(existing);
        ArgumentCaptor<QueryWrapper<AlarmRecordDO>> queryCaptor = ArgumentCaptor.forClass(QueryWrapper.class);
        verify(alarmRecordRepository).getOne(queryCaptor.capture(), eq(false));
        assertFalse(queryCaptor.getValue().getParamNameValuePairs().containsValue("0"));
        assertTrue(queryCaptor.getValue().getCustomSqlSegment().contains("finds_alarm_id"));

        ArgumentCaptor<AlarmRecordTargetDO> targetCaptor = ArgumentCaptor.forClass(AlarmRecordTargetDO.class);
        verify(alarmRecordTargetRepository).save(targetCaptor.capture());
        assertEquals("LOCAL-9", targetCaptor.getValue().getCorpinfoId());
        assertEquals("本平台九公司", targetCaptor.getValue().getCorpinfoName());
    }
}
