package com.ruoyi.loanpricing.service;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.loanpricing.domain.dto.ModelInvokeDTO;
import com.ruoyi.loanpricing.domain.entity.LoanPricingWorkflow;
import com.ruoyi.loanpricing.mapper.LoanPricingWorkflowMapper;
import com.ruoyi.loanpricing.mapper.ModelCorpOutputFieldsMapper;
import com.ruoyi.loanpricing.mapper.ModelRetailOutputFieldsMapper;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.Objects;

@ExtendWith(MockitoExtension.class)
class LoanPricingModelServiceTest
{
    @Mock
    private ModelService modelService;

    @Mock
    private LoanPricingWorkflowMapper loanPricingWorkflowMapper;

    @Mock
    private ModelRetailOutputFieldsMapper modelRetailOutputFieldsMapper;

    @Mock
    private ModelCorpOutputFieldsMapper modelCorpOutputFieldsMapper;

    @Mock
    private SensitiveFieldCryptoService sensitiveFieldCryptoService;

    @InjectMocks
    private LoanPricingModelService loanPricingModelService;

    @Test
    void shouldDecryptCustNameAndIdNumBeforeInvokeModel()
    {
        LoanPricingWorkflow workflow = new LoanPricingWorkflow();
        workflow.setId(1L);
        workflow.setCustType("个人");
        workflow.setCustName("cipher-name");
        workflow.setIdNum("cipher-id");

        JSONObject response = new JSONObject();
        response.put("calculateRate", "6.15");

        when(loanPricingWorkflowMapper.selectById(1L)).thenReturn(workflow);
        when(sensitiveFieldCryptoService.decrypt("cipher-name")).thenReturn("张三");
        when(sensitiveFieldCryptoService.decrypt("cipher-id")).thenReturn("110101199001011234");
        when(modelService.invokeModel(any())).thenReturn(response);

        loanPricingModelService.invokeModelAsync(1L);

        verify(modelService).invokeModel(argThat((ModelInvokeDTO dto) ->
                Objects.equals("张三", dto.getCustName())
                        && Objects.equals("110101199001011234", dto.getIdNum())));
    }

    @Test
    void shouldNotWritePlainCustNameAndIdNumBackWhenUpdatingWorkflow()
    {
        LoanPricingWorkflow workflow = new LoanPricingWorkflow();
        workflow.setId(2L);
        workflow.setCustType("个人");
        workflow.setCustName("cipher-name");
        workflow.setIdNum("cipher-id");

        JSONObject response = new JSONObject();
        response.put("calculateRate", "6.15");

        when(loanPricingWorkflowMapper.selectById(2L)).thenReturn(workflow);
        when(sensitiveFieldCryptoService.decrypt("cipher-name")).thenReturn("张三");
        when(sensitiveFieldCryptoService.decrypt("cipher-id")).thenReturn("110101199001011234");
        when(modelService.invokeModel(any())).thenReturn(response);

        loanPricingModelService.invokeModelAsync(2L);

        verify(loanPricingWorkflowMapper).updateById(argThat((LoanPricingWorkflow entity) ->
                !Objects.equals("张三", entity.getCustName())
                        && !Objects.equals("110101199001011234", entity.getIdNum())));
    }
}
