package com.ruoyi.info.collection.service;

import com.ruoyi.info.collection.domain.CcdiStaffEnterpriseRelation;
import com.ruoyi.info.collection.domain.CcdiStaffFmyRelation;
import com.ruoyi.info.collection.domain.excel.CcdiStaffEnterpriseRelationExcel;
import com.ruoyi.info.collection.service.impl.CcdiStaffEnterpriseRelationImportServiceImpl;
import org.junit.jupiter.api.Test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

class CcdiStaffEnterpriseRelationImportServiceImplTest {

    private final CcdiStaffEnterpriseRelationImportServiceImpl service = new CcdiStaffEnterpriseRelationImportServiceImpl();

    @Test
    void validateAndBuildEntity_shouldBuildImportEntityForValidFamily() throws Exception {
        CcdiStaffEnterpriseRelationExcel excel = buildExcel();
        CcdiStaffFmyRelation familyRelation = buildFamily();

        CcdiStaffEnterpriseRelation entity = invokeValidateAndBuildEntity(
                excel,
                familyRelation,
                Set.of(excel.getPersonId()),
                Set.of(),
                new HashSet<>(),
                "admin"
        );

        assertEquals("IMPORT", entity.getDataSource());
        assertEquals(1, entity.getStatus());
        assertEquals(1, entity.getIsEmpFamily());
        assertEquals("admin", entity.getCreatedBy());
    }

    @Test
    void validateAndBuildEntity_shouldRejectWhenFamilyDoesNotExist() throws Exception {
        CcdiStaffEnterpriseRelationExcel excel = buildExcel();

        RuntimeException exception = assertThrows(RuntimeException.class,
                () -> invokeValidateAndBuildEntity(excel, null, Set.of(), Set.of(), new HashSet<>(), "admin"));

        assertEquals("亲属身份证号[" + excel.getPersonId() + "]不存在，请先维护员工亲属关系", exception.getMessage());
    }

    @Test
    void validateAndBuildEntity_shouldRejectWhenFamilyIsInvalid() throws Exception {
        CcdiStaffEnterpriseRelationExcel excel = buildExcel();

        RuntimeException exception = assertThrows(RuntimeException.class,
                () -> invokeValidateAndBuildEntity(excel, null, Set.of(excel.getPersonId()), Set.of(), new HashSet<>(), "admin"));

        assertEquals("亲属身份证号[" + excel.getPersonId() + "]不是有效员工亲属，请先维护有效的员工亲属关系", exception.getMessage());
    }

    @Test
    void validateAndBuildEntity_shouldRejectWhenCombinationAlreadyExistsInDatabase() throws Exception {
        CcdiStaffEnterpriseRelationExcel excel = buildExcel();
        CcdiStaffFmyRelation familyRelation = buildFamily();
        String combination = excel.getPersonId() + "|" + excel.getSocialCreditCode();

        RuntimeException exception = assertThrows(RuntimeException.class,
                () -> invokeValidateAndBuildEntity(excel, familyRelation, Set.of(excel.getPersonId()), Set.of(combination), new HashSet<>(), "admin"));

        assertEquals("亲属身份证号[" + excel.getPersonId() + "]和统一社会信用代码[" + excel.getSocialCreditCode() + "]的组合已存在，请勿重复导入", exception.getMessage());
    }

    @Test
    void validateAndBuildEntity_shouldRejectWhenCombinationAlreadyExistsInExcel() throws Exception {
        CcdiStaffEnterpriseRelationExcel excel = buildExcel();
        CcdiStaffFmyRelation familyRelation = buildFamily();
        String combination = excel.getPersonId() + "|" + excel.getSocialCreditCode();

        RuntimeException exception = assertThrows(RuntimeException.class,
                () -> invokeValidateAndBuildEntity(excel, familyRelation, Set.of(excel.getPersonId()), Set.of(), new HashSet<>(Set.of(combination)), "admin"));

        assertEquals("亲属身份证号[" + excel.getPersonId() + "]和统一社会信用代码[" + excel.getSocialCreditCode() + "]的组合在导入文件中重复,已跳过此条记录", exception.getMessage());
    }

    private CcdiStaffEnterpriseRelation invokeValidateAndBuildEntity(CcdiStaffEnterpriseRelationExcel excel,
                                                                     CcdiStaffFmyRelation familyRelation,
                                                                     Set<String> knownFamilyCertNos,
                                                                     Set<String> existingCombinations,
                                                                     Set<String> processedCombinations,
                                                                     String userName) throws Exception {
        Method method = CcdiStaffEnterpriseRelationImportServiceImpl.class.getDeclaredMethod(
                "validateAndBuildEntity",
                CcdiStaffEnterpriseRelationExcel.class,
                CcdiStaffFmyRelation.class,
                Set.class,
                Set.class,
                Set.class,
                String.class
        );
        method.setAccessible(true);
        try {
            return (CcdiStaffEnterpriseRelation) method.invoke(
                    service,
                    excel,
                    familyRelation,
                    knownFamilyCertNos,
                    existingCombinations,
                    processedCombinations,
                    userName
            );
        } catch (InvocationTargetException ex) {
            Throwable targetException = ex.getTargetException();
            if (targetException instanceof RuntimeException runtimeException) {
                throw runtimeException;
            }
            throw ex;
        }
    }

    private CcdiStaffEnterpriseRelationExcel buildExcel() {
        CcdiStaffEnterpriseRelationExcel excel = new CcdiStaffEnterpriseRelationExcel();
        excel.setPersonId("320101199001010022");
        excel.setSocialCreditCode("91310000123456789A");
        excel.setEnterpriseName("测试企业");
        excel.setRelationPersonPost("董事");
        return excel;
    }

    private CcdiStaffFmyRelation buildFamily() {
        CcdiStaffFmyRelation familyRelation = new CcdiStaffFmyRelation();
        familyRelation.setPersonId("320101199001010011");
        familyRelation.setRelationCertNo("320101199001010022");
        familyRelation.setRelationName("李四");
        familyRelation.setStatus(1);
        familyRelation.setIsEmpFamily(true);
        return familyRelation;
    }
}
