package com.ylx.massage.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.ylx.address.service.impl.TAddressServiceImpl;
import com.ylx.address.domain.TAddress;
import com.ylx.massage.domain.vo.MerchantCurrentAddressVO;
import com.ylx.address.mapper.TAddressMapper;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.apache.ibatis.session.Configuration;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.test.util.ReflectionTestUtils;

import java.math.BigDecimal;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class TAddressServiceImplTest {

    @Test
    public void getCurrentMerchantAddressRejectsBlankMerchantId() {
        TAddressServiceImpl service = new TAddressServiceImpl();

        RuntimeException exception = assertThrows(RuntimeException.class,
                () -> service.getCurrentMerchantAddress(null));

        assertEquals("商户id不能为空", exception.getMessage());
    }

    @Test
    public void getCurrentMerchantAddressDelegatesToMapper() {
        TAddressMapper mapper = mock(TAddressMapper.class);
        MerchantCurrentAddressVO address = new MerchantCurrentAddressVO();
        when(mapper.selectCurrentMerchantRealAddress(11)).thenReturn(address);
        TAddressServiceImpl service = new TAddressServiceImpl();
        ReflectionTestUtils.setField(service, "baseMapper", mapper);

        MerchantCurrentAddressVO result = service.getCurrentMerchantAddress(11);

        assertSame(address, result);
        verify(mapper).selectCurrentMerchantRealAddress(11);
    }

    @Test
    public void insertAddressRejectsBlankMerchantId() {
        TAddressServiceImpl service = new TAddressServiceImpl();
        TAddress address = new TAddress();

        RuntimeException exception = assertThrows(RuntimeException.class,
                () -> service.insertAddress(address));

        assertEquals("商户id不能为空", exception.getMessage());
    }

    @Test
    public void insertAddressSavesMerchantRealAddressWithDefaults() {
        initTableInfo();
        TAddressMapper mapper = mock(TAddressMapper.class);
        when(mapper.selectOne(any(Wrapper.class))).thenReturn(null);
        when(mapper.insert(any(TAddress.class))).thenReturn(1);
        TAddressServiceImpl service = new TAddressServiceImpl();
        ReflectionTestUtils.setField(service, "baseMapper", mapper);
        TAddress address = buildMerchantAddress();
        address.setType(2);
        address.setUserType(1);
        address.setIsDelete(1);

        service.insertAddress(address);

        ArgumentCaptor<TAddress> captor = ArgumentCaptor.forClass(TAddress.class);
        verify(mapper).insert(captor.capture());
        TAddress saved = captor.getValue();
        assertEquals(2, saved.getUserType());
        assertEquals(1, saved.getType());
        assertEquals(0, saved.getIsDelete());
        assertEquals(1, saved.getIsDefault());
        assertEquals("上海市浦东新区 8号楼", saved.getDetailAddress());
    }

    @Test
    public void insertAddressClearsOldDefaultWhenNewAddressIsDefault() {
        initTableInfo();
        TAddressMapper mapper = mock(TAddressMapper.class);
        TAddress oldDefault = new TAddress();
        oldDefault.setId("old-address");
        oldDefault.setIsDefault(1);
        when(mapper.selectOne(any(Wrapper.class))).thenReturn(oldDefault);
        when(mapper.updateById(any(TAddress.class))).thenReturn(1);
        when(mapper.insert(any(TAddress.class))).thenReturn(1);
        TAddressServiceImpl service = new TAddressServiceImpl();
        ReflectionTestUtils.setField(service, "baseMapper", mapper);
        TAddress address = buildMerchantAddress();
        address.setIsDefault(1);

        service.insertAddress(address);

        ArgumentCaptor<TAddress> updateCaptor = ArgumentCaptor.forClass(TAddress.class);
        ArgumentCaptor<TAddress> insertCaptor = ArgumentCaptor.forClass(TAddress.class);
        verify(mapper).updateById(updateCaptor.capture());
        verify(mapper).insert(insertCaptor.capture());
        assertEquals("old-address", updateCaptor.getValue().getId());
        assertEquals(0, updateCaptor.getValue().getIsDefault());
        assertEquals(1, insertCaptor.getValue().getIsDefault());
    }

    private TAddress buildMerchantAddress() {
        TAddress address = new TAddress();
        address.setMerchantId(11L);
        address.setOpenid("merchant-openid");
        address.setPhone("13800000000");
        address.setUserName("商户");
        address.setCityCode("310000");
        address.setLongitude(new BigDecimal("121.500000"));
        address.setLatitude(new BigDecimal("31.200000"));
        address.setAddress("上海市浦东新区");
        address.setRoomNumber("8号楼");
        return address;
    }

    private void initTableInfo() {
        if (TableInfoHelper.getTableInfo(TAddress.class) == null) {
            MapperBuilderAssistant assistant = new MapperBuilderAssistant(new Configuration(), "");
            TableInfoHelper.initTableInfo(assistant, TAddress.class);
        }
    }
}
