package com.ruoyi.web.modules.circulation.service.impl;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.io.File;
import java.nio.file.Files;

import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.web.modules.circulation.domain.BizQuarantineStation;
import com.ruoyi.web.modules.circulation.mapper.BizQuarantineStationMapper;
import com.ruoyi.web.modules.circulation.support.QuarantineStationReferenceChecker;
import com.ruoyi.web.modules.circulation.support.QuarantineStationRules;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

/**
 * ZCZX-JYZGL-UT-006、008～011
 */
@ExtendWith(MockitoExtension.class)
@DisplayName("BizQuarantineStationServiceImpl")
class BizQuarantineStationServiceImplTest
{
    private static final String VALID_PHONE = "13800138000";

    @TempDir
    File tempDir;

    @Mock
    private BizQuarantineStationMapper mapper;

    @Mock
    private QuarantineStationReferenceChecker referenceChecker;

    @InjectMocks
    private BizQuarantineStationServiceImpl service;

    @BeforeEach
    void setUp()
    {
        new RuoYiConfig().setProfile(tempDir.getAbsolutePath());
    }

    @AfterEach
    void tearDown()
    {
        new RuoYiConfig().setProfile(null);
    }

    @Test
    @DisplayName("ZCZX-JYZGL-UT-006 名称重复")
    void ut006_duplicateName()
    {
        when(mapper.countBizQuarantineStationByNameExcludeId(eq("巴青站"), isNull())).thenReturn(1);
        BizQuarantineStation row = sampleRow();
        row.setStationName("巴青站");
        ServiceException ex = assertThrows(ServiceException.class, () -> service.insertBizQuarantineStation(row));
        assertTrue(ex.getMessage().contains("检疫站名称已存在"));
        verify(mapper, never()).insertBizQuarantineStation(any());
    }

    @Test
    @DisplayName("ZCZX-JYZGL-UT-008 新增落库")
    void ut008_insert()
    {
        when(mapper.countBizQuarantineStationByNameExcludeId(any(), isNull())).thenReturn(0);
        when(mapper.insertBizQuarantineStation(any())).thenReturn(1);
        BizQuarantineStation row = sampleRow();
        row.setOperateStatus(null);
        assertEquals(1, service.insertBizQuarantineStation(row));
        verify(mapper).insertBizQuarantineStation(argThat(r ->
                QuarantineStationRules.DEL_FLAG_NORMAL.equals(r.getDelFlag())
                        && r.getOperateStatus() == QuarantineStationRules.OPERATE_STATUS_NORMAL));
    }

    @Test
    @DisplayName("ZCZX-JYZGL-UT-009 逻辑删除")
    void ut009_logicDelete()
    {
        BizQuarantineStation db = sampleRow();
        db.setId(5L);
        when(mapper.selectBizQuarantineStationByIdAny(5L)).thenReturn(db);
        when(referenceChecker.hasReference(5L)).thenReturn(false);
        when(mapper.logicDeleteBizQuarantineStationByIds(any(), eq("tester"))).thenReturn(1);
        assertEquals(1, service.deleteBizQuarantineStationByIds(new Long[] { 5L }, "tester"));
        verify(mapper).logicDeleteBizQuarantineStationByIds(any(), eq("tester"));
    }

    @Test
    @DisplayName("ZCZX-JYZGL-UT-010 删除有关联")
    void ut010_deleteBlockedByReference()
    {
        BizQuarantineStation db = sampleRow();
        db.setId(8L);
        when(mapper.selectBizQuarantineStationByIdAny(8L)).thenReturn(db);
        when(referenceChecker.hasReference(8L)).thenReturn(true);
        ServiceException ex = assertThrows(ServiceException.class,
                () -> service.deleteBizQuarantineStationByIds(new Long[] { 8L }, "tester"));
        assertTrue(ex.getMessage().contains("关联业务"));
        verify(mapper, never()).logicDeleteBizQuarantineStationByIds(any(), any());
    }

    @Test
    @DisplayName("ZCZX-JYZGL-UT-011 删除清照片")
    void ut011_deleteClearsPhoto() throws Exception
    {
        String rel = "upload/2025/station-old.jpg";
        File disk = new File(tempDir, rel.replace('/', File.separatorChar));
        Files.createDirectories(disk.getParentFile().toPath());
        Files.write(disk.toPath(), new byte[] { 1 });
        String resourcePath = Constants.RESOURCE_PREFIX + "/" + rel;

        BizQuarantineStation db = sampleRow();
        db.setId(6L);
        db.setPhotoFilePath(resourcePath);
        when(mapper.selectBizQuarantineStationByIdAny(6L)).thenReturn(db);
        when(referenceChecker.hasReference(6L)).thenReturn(false);
        when(mapper.logicDeleteBizQuarantineStationByIds(any(), eq("u"))).thenReturn(1);

        assertEquals(1, service.deleteBizQuarantineStationByIds(new Long[] { 6L }, "u"));
        assertTrue(!disk.exists());
    }

    @Test
    @DisplayName("详情填充运营状态名")
    void detailEnrichStatusName()
    {
        BizQuarantineStation db = sampleRow();
        db.setId(1L);
        db.setOperateStatus(QuarantineStationRules.OPERATE_STATUS_SUSPENDED);
        when(mapper.selectBizQuarantineStationById(1L)).thenReturn(db);
        BizQuarantineStation got = service.selectBizQuarantineStationById(1L);
        assertEquals("停业", got.getOperateStatusName());
    }

    @Test
    @DisplayName("修改不存在记录")
    void updateMissing()
    {
        when(mapper.selectBizQuarantineStationById(99L)).thenReturn(null);
        BizQuarantineStation in = sampleRow();
        in.setId(99L);
        assertThrows(ServiceException.class, () -> service.updateBizQuarantineStation(in));
        verify(mapper, never()).updateBizQuarantineStation(any());
    }

    private static BizQuarantineStation sampleRow()
    {
        BizQuarantineStation r = new BizQuarantineStation();
        r.setStationName("巴青东站");
        r.setDetailAddress("西藏那曲市巴青县某某路1号");
        r.setPersonInCharge("李四");
        r.setContactPhone(VALID_PHONE);
        r.setOperateStatus(QuarantineStationRules.OPERATE_STATUS_NORMAL);
        return r;
    }
}
