package com.ruoyi.ccdi.project.service.impl;

import com.ruoyi.ccdi.project.domain.excel.CcdiProjectAbnormalAccountExcel;
import com.ruoyi.ccdi.project.domain.excel.CcdiProjectEmployeeCreditNegativeExcel;
import com.ruoyi.ccdi.project.domain.excel.CcdiProjectSuspiciousTransactionExcel;
import com.ruoyi.ccdi.project.domain.excel.CcdiProjectUnsubmittedAccountFlowExcel;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockHttpServletResponse;

import java.io.ByteArrayInputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.List;

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

class CcdiProjectRiskDetailWorkbookExporterTest {

    @Test
    void shouldExportWorkbookWithFourOrderedSheets() throws Exception {
        CcdiProjectRiskDetailWorkbookExporter exporter = new CcdiProjectRiskDetailWorkbookExporter();
        MockHttpServletResponse response = new MockHttpServletResponse();

        CcdiProjectSuspiciousTransactionExcel suspiciousRow = new CcdiProjectSuspiciousTransactionExcel();
        suspiciousRow.setTrxDate("2026-03-20 10:00:00");
        suspiciousRow.setLeAccountNo("6222000000000000");
        suspiciousRow.setLeAccountName("张三");
        suspiciousRow.setCustomerAccountName("测试对手方");
        suspiciousRow.setCustomerAccountNo("6222000000000001");
        suspiciousRow.setRelatedStaffDisplay("张三(1001)");
        suspiciousRow.setUserMemo("转账");
        suspiciousRow.setCashType("转账");
        suspiciousRow.setHitTags("异常标签");
        suspiciousRow.setDisplayAmount(new BigDecimal("100.00"));

        CcdiProjectEmployeeCreditNegativeExcel creditRow = new CcdiProjectEmployeeCreditNegativeExcel();
        creditRow.setPersonName("李四");
        creditRow.setPersonId("330000000000000001");
        creditRow.setQueryDate("2026-03-20");
        creditRow.setCivilCnt(1);
        creditRow.setCivilLmt(new BigDecimal("20000.00"));

        CcdiProjectAbnormalAccountExcel abnormalRow = new CcdiProjectAbnormalAccountExcel();
        abnormalRow.setAccountNo("6222000000000001");
        abnormalRow.setAccountName("李四");
        abnormalRow.setBankName("中国农业银行");
        abnormalRow.setAbnormalType("突然销户");
        abnormalRow.setAbnormalTime("2026-03-20");
        abnormalRow.setStatus("已销户");
        abnormalRow.setReasonDetail("账户6222000000000001销户前存在异常交易");
        abnormalRow.setInvolvedAmount(new BigDecimal("120000.00"));

        CcdiProjectUnsubmittedAccountFlowExcel unsubmittedRow = new CcdiProjectUnsubmittedAccountFlowExcel();
        unsubmittedRow.setSubjectName("测试主体");
        unsubmittedRow.setAccountNo("330001000000000001");
        unsubmittedRow.setTrxDate("2026-03-21");
        unsubmittedRow.setLeAccountNo("330001000000000002");
        unsubmittedRow.setLeAccountName("测试主体");
        unsubmittedRow.setCustomerAccountName("测试主体");
        unsubmittedRow.setCustomerAccountNo("330001000000000001");
        unsubmittedRow.setUserMemo("往来款");
        unsubmittedRow.setCashType("转账");
        unsubmittedRow.setAmountCr(new BigDecimal("30000.00"));
        unsubmittedRow.setAmountDr(BigDecimal.ZERO);

        exporter.export(
            response,
            40L,
            List.of(suspiciousRow),
            List.of(creditRow),
            List.of(abnormalRow),
            List.of(unsubmittedRow)
        );

        assertTrue(response.getContentType().startsWith(
            "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
        ));

        try (var workbook = WorkbookFactory.create(new ByteArrayInputStream(response.getContentAsByteArray()))) {
            assertEquals(4, workbook.getNumberOfSheets());
            assertEquals("涉疑交易明细", workbook.getSheetAt(0).getSheetName());
            assertEquals("员工负面征信信息", workbook.getSheetAt(1).getSheetName());
            assertEquals("异常账户人员信息", workbook.getSheetAt(2).getSheetName());
            assertEquals("未提交账户流水", workbook.getSheetAt(3).getSheetName());
            assertEquals("交易时间", workbook.getSheetAt(0).getRow(0).getCell(0).getStringCellValue());
            assertEquals("本方账户", workbook.getSheetAt(0).getRow(0).getCell(1).getStringCellValue());
            assertEquals("本方主体", workbook.getSheetAt(0).getRow(0).getCell(2).getStringCellValue());
            assertEquals("对方名称", workbook.getSheetAt(0).getRow(0).getCell(3).getStringCellValue());
            assertEquals("对方账户", workbook.getSheetAt(0).getRow(0).getCell(4).getStringCellValue());
            assertEquals("关联员工", workbook.getSheetAt(0).getRow(0).getCell(5).getStringCellValue());
            assertEquals("摘要", workbook.getSheetAt(0).getRow(0).getCell(6).getStringCellValue());
            assertEquals("交易类型", workbook.getSheetAt(0).getRow(0).getCell(7).getStringCellValue());
            assertEquals("交易金额", workbook.getSheetAt(0).getRow(0).getCell(8).getStringCellValue());
            assertEquals("异常标签", workbook.getSheetAt(0).getRow(0).getCell(9).getStringCellValue());
            assertEquals("测试对手方", workbook.getSheetAt(0).getRow(1).getCell(3).getStringCellValue());
            assertEquals("6222000000000001", workbook.getSheetAt(0).getRow(1).getCell(4).getStringCellValue());
            assertEquals(100D, workbook.getSheetAt(0).getRow(1).getCell(8).getNumericCellValue());
            assertEquals("异常标签", workbook.getSheetAt(0).getRow(1).getCell(9).getStringCellValue());
            assertEquals("账号", workbook.getSheetAt(2).getRow(0).getCell(0).getStringCellValue());
            assertEquals("开户人", workbook.getSheetAt(2).getRow(0).getCell(1).getStringCellValue());
            assertEquals("银行", workbook.getSheetAt(2).getRow(0).getCell(2).getStringCellValue());
            assertEquals("异常类型", workbook.getSheetAt(2).getRow(0).getCell(3).getStringCellValue());
            assertEquals("异常发生时间", workbook.getSheetAt(2).getRow(0).getCell(4).getStringCellValue());
            assertEquals("状态", workbook.getSheetAt(2).getRow(0).getCell(5).getStringCellValue());
            assertEquals("命中原因", workbook.getSheetAt(2).getRow(0).getCell(6).getStringCellValue());
            assertEquals("涉及金额", workbook.getSheetAt(2).getRow(0).getCell(7).getStringCellValue());
            assertEquals("6222000000000001", workbook.getSheetAt(2).getRow(1).getCell(0).getStringCellValue());
            assertEquals("李四", workbook.getSheetAt(2).getRow(1).getCell(1).getStringCellValue());
            assertEquals("中国农业银行", workbook.getSheetAt(2).getRow(1).getCell(2).getStringCellValue());
            assertEquals("突然销户", workbook.getSheetAt(2).getRow(1).getCell(3).getStringCellValue());
            assertEquals("2026-03-20", workbook.getSheetAt(2).getRow(1).getCell(4).getStringCellValue());
            assertEquals("已销户", workbook.getSheetAt(2).getRow(1).getCell(5).getStringCellValue());
            assertEquals("账户6222000000000001销户前存在异常交易", workbook.getSheetAt(2).getRow(1).getCell(6).getStringCellValue());
            assertEquals(120000D, workbook.getSheetAt(2).getRow(1).getCell(7).getNumericCellValue());
            assertEquals(2, workbook.getSheetAt(2).getPhysicalNumberOfRows());
            assertEquals("主体名称", workbook.getSheetAt(3).getRow(0).getCell(0).getStringCellValue());
            assertEquals("未提交账号", workbook.getSheetAt(3).getRow(0).getCell(1).getStringCellValue());
            assertEquals("交易时间", workbook.getSheetAt(3).getRow(0).getCell(2).getStringCellValue());
            assertEquals("流入金额", workbook.getSheetAt(3).getRow(0).getCell(9).getStringCellValue());
            assertEquals("测试主体", workbook.getSheetAt(3).getRow(1).getCell(0).getStringCellValue());
            assertEquals("330001000000000001", workbook.getSheetAt(3).getRow(1).getCell(1).getStringCellValue());
            assertEquals(30000D, workbook.getSheetAt(3).getRow(1).getCell(9).getNumericCellValue());
        }
    }

    @Test
    void shouldKeepSuspiciousTransactionExcelAmountBeforeHitTags() {
        Field[] fields = CcdiProjectSuspiciousTransactionExcel.class.getDeclaredFields();

        int amountIndex = findFieldIndex(fields, "displayAmount");
        int hitTagsIndex = findFieldIndex(fields, "hitTags");

        assertTrue(amountIndex >= 0);
        assertTrue(hitTagsIndex >= 0);
        assertTrue(amountIndex < hitTagsIndex);
    }

    private int findFieldIndex(Field[] fields, String fieldName) {
        for (int i = 0; i < fields.length; i++) {
            if (fieldName.equals(fields[i].getName())) {
                return i;
            }
        }
        return -1;
    }
}
