package com.gxwebsoft.credit.controller;

import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditAdministrativeLicense;
import com.gxwebsoft.credit.param.CreditAdministrativeLicenseImportParam;
import com.gxwebsoft.credit.param.CreditAdministrativeLicenseParam;
import com.gxwebsoft.credit.service.CreditCompanyService;
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
import com.gxwebsoft.credit.service.CreditAdministrativeLicenseService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 行政许可控制器
 *
 * @author 科技小王子
 * @since 2026-01-07 13:52:14
 */
@Tag(name = "行政许可管理")
@RestController
@RequestMapping("/api/credit/credit-administrative-license")
public class CreditAdministrativeLicenseController extends BaseController {
    @Resource
    private CreditAdministrativeLicenseService creditAdministrativeLicenseService;

    @Resource
    private BatchImportSupport batchImportSupport;

    @Resource
    private CreditCompanyService creditCompanyService;

    @Resource
    private CreditCompanyRecordCountService creditCompanyRecordCountService;

    @Operation(summary = "分页查询行政许可")
    @GetMapping("/page")
    public ApiResult<PageResult<CreditAdministrativeLicense>> page(CreditAdministrativeLicenseParam param) {
        // 使用关联查询
        return success(creditAdministrativeLicenseService.pageRel(param));
    }

    @Operation(summary = "查询全部行政许可")
    @GetMapping()
    public ApiResult<List<CreditAdministrativeLicense>> list(CreditAdministrativeLicenseParam param) {
        // 使用关联查询
        return success(creditAdministrativeLicenseService.listRel(param));
    }

    @Operation(summary = "根据id查询行政许可")
    @GetMapping("/{id}")
    public ApiResult<CreditAdministrativeLicense> get(@PathVariable("id") Integer id) {
        // 使用关联查询
        return success(creditAdministrativeLicenseService.getByIdRel(id));
    }

    @PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:save')")
    @OperationLog
    @Operation(summary = "添加行政许可")
    @PostMapping()
    public ApiResult<?> save(@RequestBody CreditAdministrativeLicense creditAdministrativeLicense) {
        // 记录当前登录用户id
        // User loginUser = getLoginUser();
        // if (loginUser != null) {
        // creditAdministrativeLicense.setUserId(loginUser.getUserId());
        // }
        if (creditAdministrativeLicenseService.save(creditAdministrativeLicense)) {
            return success("添加成功");
        }
        return fail("添加失败");
    }

    @PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:update')")
    @OperationLog
    @Operation(summary = "修改行政许可")
    @PutMapping()
    public ApiResult<?> update(@RequestBody CreditAdministrativeLicense creditAdministrativeLicense) {
        if (creditAdministrativeLicenseService.updateById(creditAdministrativeLicense)) {
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:remove')")
    @OperationLog
    @Operation(summary = "删除行政许可")
    @DeleteMapping("/{id}")
    public ApiResult<?> remove(@PathVariable("id") Integer id) {
        if (creditAdministrativeLicenseService.removeById(id)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }

    @PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:save')")
    @OperationLog
    @Operation(summary = "批量添加行政许可")
    @PostMapping("/batch")
    public ApiResult<?> saveBatch(@RequestBody List<CreditAdministrativeLicense> list) {
        if (creditAdministrativeLicenseService.saveBatch(list)) {
            return success("添加成功");
        }
        return fail("添加失败");
    }

    @PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:update')")
    @OperationLog
    @Operation(summary = "批量修改行政许可")
    @PutMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditAdministrativeLicense> batchParam) {
        if (batchParam.update(creditAdministrativeLicenseService, "id")) {
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:remove')")
    @OperationLog
    @Operation(summary = "批量删除行政许可")
    @DeleteMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
        if (creditAdministrativeLicenseService.removeByIds(ids)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }

    /**
     * 根据企业名称匹配企业并更新 companyId（匹配 CreditCompany.name / CreditCompany.matchName）
     *
     * <p>默认仅更新 companyId=0 的记录；如需覆盖更新，传 onlyNull=false。</p>
     */
    @PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:update')")
    @OperationLog
    @Operation(summary = "根据企业名称匹配并更新companyId")
    @PostMapping("/company-id/refresh")
    public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
        @RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
        @RequestParam(value = "limit", required = false) Integer limit
    ) {
        User loginUser = getLoginUser();
        Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;

        BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
            creditAdministrativeLicenseService,
            creditCompanyService,
            currentTenantId,
            onlyNull,
            limit,
            CreditAdministrativeLicense::getId,
            CreditAdministrativeLicense::setId,
            CreditAdministrativeLicense::getName,
            CreditAdministrativeLicense::getCompanyId,
            CreditAdministrativeLicense::setCompanyId,
            CreditAdministrativeLicense::getHasData,
            CreditAdministrativeLicense::setHasData,
            CreditAdministrativeLicense::getTenantId,
            CreditAdministrativeLicense::new
        );

        if (!stats.anyDataRead) {
            return success("无可更新数据", stats.toMap());
        }
        return success("更新完成，更新" + stats.updated + "条", stats.toMap());
    }

    /**
     * 批量导入行政许可
     */
    @PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:save')")
    @Operation(summary = "批量导入行政许可")
    @PostMapping("/import")
    public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
                                               @RequestParam(value = "companyId", required = false) Integer companyId) {
        List<String> errorMessages = new ArrayList<>();
        int successCount = 0;
        Set<Integer> touchedCompanyIds = new HashSet<>();

        try {
            ExcelImportSupport.ImportResult<CreditAdministrativeLicenseImportParam> importResult = ExcelImportSupport.readAnySheet(
                file, CreditAdministrativeLicenseImportParam.class, this::isEmptyImportRow);
            List<CreditAdministrativeLicenseImportParam> list = importResult.getData();
            int usedTitleRows = importResult.getTitleRows();
            int usedHeadRows = importResult.getHeadRows();
            int usedSheetIndex = importResult.getSheetIndex();

            if (CollectionUtils.isEmpty(list)) {
                return fail("未读取到数据，请确认模板表头与示例格式一致", null);
            }

            User loginUser = getLoginUser();
            Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
            Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
            Map<String, String> urlByCode = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "决定文书/许可编号");
            Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "决定文书/许可证名称");

            final int chunkSize = 500;
            final int mpBatchSize = 500;
            List<CreditAdministrativeLicense> chunkItems = new ArrayList<>(chunkSize);
            List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);

            for (int i = 0; i < list.size(); i++) {
                CreditAdministrativeLicenseImportParam param = list.get(i);
                try {
                    CreditAdministrativeLicense item = convertImportParamToEntity(param);
                    String link = null;
                    if (!ImportHelper.isBlank(item.getCode())) {
                        link = urlByCode.get(item.getCode().trim());
                    }
                    if ((link == null || link.isEmpty()) && !ImportHelper.isBlank(item.getName())) {
                        link = urlByName.get(item.getName().trim());
                    }
                    if (link != null && !link.isEmpty()) {
                        item.setUrl(link);
                    }

                    if (item.getCompanyId() == null && companyId != null) {
                        item.setCompanyId(companyId);
                    }
                    if (item.getCompanyId() != null && item.getCompanyId() > 0) {
                        touchedCompanyIds.add(item.getCompanyId());
                    }
                    if (item.getUserId() == null && currentUserId != null) {
                        item.setUserId(currentUserId);
                    }
                    if (item.getTenantId() == null && currentTenantId != null) {
                        item.setTenantId(currentTenantId);
                    }
                    if (item.getStatus() == null) {
                        item.setStatus(0);
                    }
                    if (item.getRecommend() == null) {
                        item.setRecommend(0);
                    }
                    if (item.getDeleted() == null) {
                        item.setDeleted(0);
                    }

                    int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
                    if (ImportHelper.isBlank(item.getName())) {
                        errorMessages.add("第" + excelRowNumber + "行：决定文书/许可证名称不能为空");
                        continue;
                    }

                    if (item.getCompanyId() != null && item.getCompanyId() > 0) {
                        touchedCompanyIds.add(item.getCompanyId());
                    }

                    chunkItems.add(item);
                    chunkRowNumbers.add(excelRowNumber);
                    if (chunkItems.size() >= chunkSize) {
                        successCount += batchImportSupport.persistChunkWithFallback(
                            chunkItems,
                            chunkRowNumbers,
                            () -> batchImportSupport.upsertByCodeOrName(
                                creditAdministrativeLicenseService,
                                chunkItems,
                                CreditAdministrativeLicense::getId,
                                CreditAdministrativeLicense::setId,
                                CreditAdministrativeLicense::getCode,
                                CreditAdministrativeLicense::getCode,
                                CreditAdministrativeLicense::getName,
                                CreditAdministrativeLicense::getName,
                                null,
                                mpBatchSize
                            ),
                            (rowItem, rowNumber) -> {
                                boolean saved = creditAdministrativeLicenseService.save(rowItem);
                                if (!saved) {
                                    CreditAdministrativeLicense existing = null;
                                    if (!ImportHelper.isBlank(rowItem.getCode())) {
                                        existing = creditAdministrativeLicenseService.lambdaQuery()
                                            .eq(CreditAdministrativeLicense::getCode, rowItem.getCode())
                                            .one();
                                    }
                                    if (existing == null) {
                                        existing = creditAdministrativeLicenseService.lambdaQuery()
                                            .eq(CreditAdministrativeLicense::getName, rowItem.getName())
                                            .one();
                                    }
                                    if (existing != null) {
                                        rowItem.setId(existing.getId());
                                        if (creditAdministrativeLicenseService.updateById(rowItem)) {
                                            return true;
                                        }
                                    }
                                } else {
                                    return true;
                                }
                                String prefix = rowNumber > 0 ? ("第" + rowNumber + "行：") : "";
                                errorMessages.add(prefix + "保存失败");
                                return false;
                            },
                            errorMessages
                        );
                        chunkItems.clear();
                        chunkRowNumbers.clear();
                    }
                } catch (Exception e) {
                    int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
                    errorMessages.add("第" + excelRowNumber + "行：" + e.getMessage());
                    e.printStackTrace();
                }
            }

            if (!chunkItems.isEmpty()) {
                successCount += batchImportSupport.persistChunkWithFallback(
                    chunkItems,
                    chunkRowNumbers,
                    () -> batchImportSupport.upsertByCodeOrName(
                        creditAdministrativeLicenseService,
                        chunkItems,
                        CreditAdministrativeLicense::getId,
                        CreditAdministrativeLicense::setId,
                        CreditAdministrativeLicense::getCode,
                        CreditAdministrativeLicense::getCode,
                        CreditAdministrativeLicense::getName,
                        CreditAdministrativeLicense::getName,
                        null,
                        mpBatchSize
                    ),
                    (rowItem, rowNumber) -> {
                        boolean saved = creditAdministrativeLicenseService.save(rowItem);
                        if (!saved) {
                            CreditAdministrativeLicense existing = null;
                            if (!ImportHelper.isBlank(rowItem.getCode())) {
                                existing = creditAdministrativeLicenseService.lambdaQuery()
                                    .eq(CreditAdministrativeLicense::getCode, rowItem.getCode())
                                    .one();
                            }
                            if (existing == null) {
                                existing = creditAdministrativeLicenseService.lambdaQuery()
                                    .eq(CreditAdministrativeLicense::getName, rowItem.getName())
                                    .one();
                            }
                            if (existing != null) {
                                rowItem.setId(existing.getId());
                                if (creditAdministrativeLicenseService.updateById(rowItem)) {
                                    return true;
                                }
                            }
                        } else {
                            return true;
                        }
                        String prefix = rowNumber > 0 ? ("第" + rowNumber + "行：") : "";
                        errorMessages.add(prefix + "保存失败");
                        return false;
                    },
                    errorMessages
                );
            }

            creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.ADMINISTRATIVE_LICENSE, touchedCompanyIds);

            if (errorMessages.isEmpty()) {
                return success("成功导入" + successCount + "条数据", null);
            } else {
                return success("导入完成，成功" + successCount + "条，失败" + errorMessages.size() + "条", errorMessages);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return fail("导入失败：" + e.getMessage(), null);
        }
    }

    /**
     * 批量导入历史行政许可（仅解析“历史行政许可”选项卡）
     * 规则：优先按编号(code)匹配；code 为空时按名称(name)匹配；匹配到则覆盖更新（recommend++ 记录更新次数）。
     */
    @PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:save')")
    @Operation(summary = "批量导入历史行政许可")
    @PostMapping("/import/history")
    public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
                                                      @RequestParam(value = "companyId", required = false) Integer companyId) {
        List<String> errorMessages = new ArrayList<>();
        int successCount = 0;
        Set<Integer> touchedCompanyIds = new HashSet<>();

        try {
            int sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史行政许可");
            if (sheetIndex < 0) {
                return fail("未读取到数据，请确认文件中存在“历史行政许可”选项卡且表头与示例格式一致", null);
            }

            ExcelImportSupport.ImportResult<CreditAdministrativeLicenseImportParam> importResult = ExcelImportSupport.read(
                file, CreditAdministrativeLicenseImportParam.class, this::isEmptyImportRow, sheetIndex);
            List<CreditAdministrativeLicenseImportParam> list = importResult.getData();
            int usedTitleRows = importResult.getTitleRows();
            int usedHeadRows = importResult.getHeadRows();
            int usedSheetIndex = importResult.getSheetIndex();

            if (CollectionUtils.isEmpty(list)) {
                return fail("未读取到数据，请确认模板表头与示例格式一致", null);
            }

            User loginUser = getLoginUser();
            Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
            Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
            Map<String, String> urlByCode = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "决定文书/许可编号");
            Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "决定文书/许可证名称");

            LinkedHashMap<String, CreditAdministrativeLicense> latestByKey = new LinkedHashMap<>();
            LinkedHashMap<String, Integer> latestRowByKey = new LinkedHashMap<>();

            for (int i = 0; i < list.size(); i++) {
                CreditAdministrativeLicenseImportParam param = list.get(i);
                int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
                try {
                    CreditAdministrativeLicense item = convertImportParamToEntity(param);
                    if (item.getCode() != null) {
                        item.setCode(item.getCode().trim());
                    }
                    if (item.getName() != null) {
                        item.setName(item.getName().trim());
                    }

                    if (ImportHelper.isBlank(item.getName())) {
                        errorMessages.add("第" + excelRowNumber + "行：决定文书/许可证名称不能为空");
                        continue;
                    }

                    String link = null;
                    if (!ImportHelper.isBlank(item.getCode())) {
                        link = urlByCode.get(item.getCode());
                    }
                    if ((link == null || link.isEmpty()) && !ImportHelper.isBlank(item.getName())) {
                        link = urlByName.get(item.getName());
                    }
                    if (!ImportHelper.isBlank(link)) {
                        item.setUrl(link.trim());
                    }

                    if (item.getCompanyId() == null && companyId != null) {
                        item.setCompanyId(companyId);
                    }
                    if (item.getUserId() == null && currentUserId != null) {
                        item.setUserId(currentUserId);
                    }
                    if (item.getTenantId() == null && currentTenantId != null) {
                        item.setTenantId(currentTenantId);
                    }
                    if (item.getStatus() == null) {
                        item.setStatus(0);
                    }
                    if (item.getDeleted() == null) {
                        item.setDeleted(0);
                    }

                    String dedupKey = !ImportHelper.isBlank(item.getCode()) ? ("CODE:" + item.getCode()) : ("NAME:" + item.getName());
                    latestByKey.put(dedupKey, item);
                    latestRowByKey.put(dedupKey, excelRowNumber);
                } catch (Exception e) {
                    errorMessages.add("第" + excelRowNumber + "行：" + e.getMessage());
                    e.printStackTrace();
                }
            }

            if (latestByKey.isEmpty()) {
                if (errorMessages.isEmpty()) {
                    return fail("未读取到数据，请确认模板表头与示例格式一致", null);
                }
                return success("导入完成，成功0条，失败" + errorMessages.size() + "条", errorMessages);
            }

            final int chunkSize = 500;
            final int mpBatchSize = 500;
            List<CreditAdministrativeLicense> chunkItems = new ArrayList<>(chunkSize);
            List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);

            for (Map.Entry<String, CreditAdministrativeLicense> entry : latestByKey.entrySet()) {
                String dedupKey = entry.getKey();
                CreditAdministrativeLicense item = entry.getValue();
                Integer rowNo = latestRowByKey.get(dedupKey);
                chunkItems.add(item);
                chunkRowNumbers.add(rowNo != null ? rowNo : -1);
                if (chunkItems.size() >= chunkSize) {
                    successCount += batchImportSupport.persistChunkWithFallback(
                        chunkItems,
                        chunkRowNumbers,
                        () -> batchImportSupport.upsertByCodeOrNameAndIncrementCounterOnUpdate(
                            creditAdministrativeLicenseService,
                            chunkItems,
                            CreditAdministrativeLicense::getId,
                            CreditAdministrativeLicense::setId,
                            CreditAdministrativeLicense::getCode,
                            CreditAdministrativeLicense::getCode,
                            CreditAdministrativeLicense::getName,
                            CreditAdministrativeLicense::getName,
                            CreditAdministrativeLicense::getRecommend,
                            CreditAdministrativeLicense::setRecommend,
                            null,
                            mpBatchSize
                        ),
                        (rowItem, rowNumber) -> {
                            if (rowItem.getRecommend() == null) {
                                rowItem.setRecommend(0);
                            }
                            boolean saved = creditAdministrativeLicenseService.save(rowItem);
                            if (!saved) {
                                CreditAdministrativeLicense existing = null;
                                if (!ImportHelper.isBlank(rowItem.getCode())) {
                                    existing = creditAdministrativeLicenseService.lambdaQuery()
                                        .eq(CreditAdministrativeLicense::getCode, rowItem.getCode())
                                        .select(CreditAdministrativeLicense::getId, CreditAdministrativeLicense::getRecommend)
                                        .one();
                                }
                                if (existing == null && !ImportHelper.isBlank(rowItem.getName())) {
                                    existing = creditAdministrativeLicenseService.lambdaQuery()
                                        .eq(CreditAdministrativeLicense::getName, rowItem.getName())
                                        .select(CreditAdministrativeLicense::getId, CreditAdministrativeLicense::getRecommend)
                                        .one();
                                }
                                if (existing != null) {
                                    rowItem.setId(existing.getId());
                                    Integer old = existing.getRecommend();
                                    rowItem.setRecommend(old == null ? 1 : old + 1);
                                    if (creditAdministrativeLicenseService.updateById(rowItem)) {
                                        return true;
                                    }
                                }
                            } else {
                                return true;
                            }
                            String prefix = rowNumber > 0 ? ("第" + rowNumber + "行：") : "";
                            errorMessages.add(prefix + "保存失败");
                            return false;
                        },
                        errorMessages
                    );
                    chunkItems.clear();
                    chunkRowNumbers.clear();
                }
            }

            if (!chunkItems.isEmpty()) {
                successCount += batchImportSupport.persistChunkWithFallback(
                    chunkItems,
                    chunkRowNumbers,
                    () -> batchImportSupport.upsertByCodeOrNameAndIncrementCounterOnUpdate(
                        creditAdministrativeLicenseService,
                        chunkItems,
                        CreditAdministrativeLicense::getId,
                        CreditAdministrativeLicense::setId,
                        CreditAdministrativeLicense::getCode,
                        CreditAdministrativeLicense::getCode,
                        CreditAdministrativeLicense::getName,
                        CreditAdministrativeLicense::getName,
                        CreditAdministrativeLicense::getRecommend,
                        CreditAdministrativeLicense::setRecommend,
                        null,
                        mpBatchSize
                    ),
                    (rowItem, rowNumber) -> {
                        if (rowItem.getRecommend() == null) {
                            rowItem.setRecommend(0);
                        }
                        boolean saved = creditAdministrativeLicenseService.save(rowItem);
                        if (!saved) {
                            CreditAdministrativeLicense existing = null;
                            if (!ImportHelper.isBlank(rowItem.getCode())) {
                                existing = creditAdministrativeLicenseService.lambdaQuery()
                                    .eq(CreditAdministrativeLicense::getCode, rowItem.getCode())
                                    .select(CreditAdministrativeLicense::getId, CreditAdministrativeLicense::getRecommend)
                                    .one();
                            }
                            if (existing == null && !ImportHelper.isBlank(rowItem.getName())) {
                                existing = creditAdministrativeLicenseService.lambdaQuery()
                                    .eq(CreditAdministrativeLicense::getName, rowItem.getName())
                                    .select(CreditAdministrativeLicense::getId, CreditAdministrativeLicense::getRecommend)
                                    .one();
                            }
                            if (existing != null) {
                                rowItem.setId(existing.getId());
                                Integer old = existing.getRecommend();
                                rowItem.setRecommend(old == null ? 1 : old + 1);
                                if (creditAdministrativeLicenseService.updateById(rowItem)) {
                                    return true;
                                }
                            }
                        } else {
                            return true;
                        }
                        String prefix = rowNumber > 0 ? ("第" + rowNumber + "行：") : "";
                        errorMessages.add(prefix + "保存失败");
                        return false;
                    },
                    errorMessages
                );
            }

            creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.ADMINISTRATIVE_LICENSE, touchedCompanyIds);

            if (errorMessages.isEmpty()) {
                return success("成功导入" + successCount + "条数据", null);
            }
            return success("导入完成，成功" + successCount + "条，失败" + errorMessages.size() + "条", errorMessages);
        } catch (Exception e) {
            e.printStackTrace();
            return fail("导入失败：" + e.getMessage(), null);
        }
    }

    /**
     * 下载行政许可导入模板
     */
    @Operation(summary = "下载行政许可导入模板")
    @GetMapping("/import/template")
    public void downloadTemplate(HttpServletResponse response) throws IOException {
        List<CreditAdministrativeLicenseImportParam> templateList = new ArrayList<>();

        CreditAdministrativeLicenseImportParam example = new CreditAdministrativeLicenseImportParam();
        example.setCode("（2024）示例许可编号");
        example.setName("示例行政许可名称");
        example.setStatusText("有效");
        example.setType("行政许可");
        example.setValidityStart("2024-01-01");
        example.setValidityEnd("2029-01-01");
        example.setLicensingAuthority("某某许可机关");
        example.setLicenseContent("许可内容示例");
        example.setDataSourceUnit("数据来源单位示例");
        example.setComments("备注信息");
        templateList.add(example);

        Workbook workbook = ExcelImportSupport.buildTemplate("行政许可导入模板", "行政许可", CreditAdministrativeLicenseImportParam.class, templateList);

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=credit_administrative_license_import_template.xlsx");

        workbook.write(response.getOutputStream());
        workbook.close();
    }

    private boolean isEmptyImportRow(CreditAdministrativeLicenseImportParam param) {
        if (param == null) {
            return true;
        }
        if (isImportHeaderRow(param)) {
            return true;
        }
        return ImportHelper.isBlank(param.getCode())
            && ImportHelper.isBlank(param.getName())
            && ImportHelper.isBlank(param.getStatusText());
    }

    private boolean isImportHeaderRow(CreditAdministrativeLicenseImportParam param) {
        return isHeaderValue(param.getCode(), "决定文书/许可编号")
            || isHeaderValue(param.getName(), "决定文书/许可证名称")
            || isHeaderValue(param.getStatusText(), "许可状态");
    }

    private static boolean isHeaderValue(String value, String headerText) {
        if (value == null) {
            return false;
        }
        return headerText.equals(value.trim());
    }

    private CreditAdministrativeLicense convertImportParamToEntity(CreditAdministrativeLicenseImportParam param) {
        CreditAdministrativeLicense entity = new CreditAdministrativeLicense();

        entity.setCode(param.getCode());
        entity.setName(param.getName());
        entity.setStatusText(param.getStatusText());
        entity.setType(param.getType());
        entity.setValidityStart(param.getValidityStart());
        entity.setValidityEnd(param.getValidityEnd());
        entity.setLicensingAuthority(param.getLicensingAuthority());
        entity.setLicenseContent(param.getLicenseContent());
        entity.setDataSourceUnit(param.getDataSourceUnit());
        entity.setComments(param.getComments());

        return entity;
    }

}
