package org.jeecg.modules.system.app.service.impl;


import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.DictAnnotationUtil;
import org.jeecg.common.util.idCard.ChineseIdCard18Utils;
import org.jeecg.common.util.idCard.Gender;
import org.jeecg.modules.system.app.dto.insureOrder.FindInsureOrderPageRequestDTO;
import org.jeecg.modules.system.app.dto.insureOrder.FindInsureOrderPageResponseDTO;
import org.jeecg.modules.system.app.entity.AppInsure;
import org.jeecg.modules.system.app.entity.InsureOrderInfo;
import org.jeecg.modules.system.app.mapper.AppInsureMapper;
import org.jeecg.modules.system.app.mapper.InsureOrderInfoMapper;
import org.jeecg.modules.system.app.service.IInsureOrderInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;

/**
 * @Description: 保险订单
 * @Author: jeecg-boot
 * @Date:   2025-07-29
 * @Version: V1.0
 */
@Service
public class InsureOrderInfoServiceImpl extends ServiceImpl<InsureOrderInfoMapper, InsureOrderInfo> implements IInsureOrderInfoService {


    @Autowired
    InsureOrderInfoMapper insureOrderInfoMapper;

    @Autowired
    AppInsureMapper appInsureMapper;

    @Override
    public Result<IPage<FindInsureOrderPageResponseDTO>> findPage(FindInsureOrderPageRequestDTO findInsureOrderPageRequestDTO) {
        getFindInsureOrderPageRequestDTO(findInsureOrderPageRequestDTO);
        DictAnnotationUtil.translateDict(findInsureOrderPageRequestDTO);
        Page<FindInsureOrderPageResponseDTO> page = new Page<FindInsureOrderPageResponseDTO>(findInsureOrderPageRequestDTO.getPageNo(), findInsureOrderPageRequestDTO.getPageSize());
        IPage<FindInsureOrderPageResponseDTO> findInsureOrderPageResponseDTOIPage = insureOrderInfoMapper.findPage(page, findInsureOrderPageRequestDTO);
        if (findInsureOrderPageResponseDTOIPage!=null&&findInsureOrderPageResponseDTOIPage.getRecords()!=null){
            for (FindInsureOrderPageResponseDTO record : findInsureOrderPageResponseDTOIPage.getRecords()) {
                String desensitization = ChineseIdCard18Utils.getDesensitization(record.getIdentityCard(), 3, 4);
                record.setIdentityCard(desensitization);
            }
        }
        return Result.ok(findInsureOrderPageResponseDTOIPage);
    }

    @Override
    @Transactional
    public Result<String> updateBatch(FindInsureOrderPageRequestDTO findInsureOrderPageRequestDTO) {

        if (StringUtils.isEmpty(findInsureOrderPageRequestDTO.getId())) {
            if (StringUtils.isEmpty(findInsureOrderPageRequestDTO.getInsureCompany_dictText())
                    && StringUtils.isEmpty(findInsureOrderPageRequestDTO.getEndTime())
                    && StringUtils.isEmpty(findInsureOrderPageRequestDTO.getStartTime())) {
                return Result.error("查询参数保险公司和付款时间不能为空");
            }
        }

        if (ObjectUtils.isEmpty(findInsureOrderPageRequestDTO.getUpdateIsEnterSystem())){
            return Result.error("修改状态不能为空");
        }
        getFindInsureOrderPageRequestDTO(findInsureOrderPageRequestDTO);
        insureOrderInfoMapper.updateBatch(findInsureOrderPageRequestDTO);
        return Result.ok("批量修改录入系统成功");
    }

    @Override
    public void exportXls(HttpServletRequest request, HttpServletResponse response, FindInsureOrderPageRequestDTO findInsureOrderPageRequestDTO) {
        if (StringUtils.isEmpty(findInsureOrderPageRequestDTO.getId())) {
            if (StringUtils.isEmpty(findInsureOrderPageRequestDTO.getInsureCompany_dictText())
                    && StringUtils.isEmpty(findInsureOrderPageRequestDTO.getEndTime())
                    && StringUtils.isEmpty(findInsureOrderPageRequestDTO.getStartTime())) {
                throw new JeecgBootException("查询参数保险公司和付款时间不能为空");
            }
        }
        String timestamp = String.valueOf(System.currentTimeMillis());
        DictAnnotationUtil.translateDict(findInsureOrderPageRequestDTO);
        String outputFilename = findInsureOrderPageRequestDTO.getInsureCompany_dictText() +"保险订单_被保险人清单_" + timestamp ;
        List<FindInsureOrderPageResponseDTO> byList = insureOrderInfoMapper.findByList(findInsureOrderPageRequestDTO);
        writeToExcel(byList,response,outputFilename,findInsureOrderPageRequestDTO.getInsureCompany());
    }


    private void getFindInsureOrderPageRequestDTO(FindInsureOrderPageRequestDTO findInsureOrderPageRequestDTO){
        if (StringUtils.isNotEmpty(findInsureOrderPageRequestDTO.getInsureId())){
            AppInsure appInsure = appInsureMapper.selectById(findInsureOrderPageRequestDTO.getInsureId());
            if (appInsure!=null){
                findInsureOrderPageRequestDTO.setInsureName(appInsure.getName());
            }
        }
    }

    public void writeToExcel(List<FindInsureOrderPageResponseDTO> persons,HttpServletResponse response, String outputFilename,Integer insureCompany ) throws JeecgBootException {

        setResponseHeaders(response, outputFilename);
        // 参数校验
        if (persons == null || persons.isEmpty()) {
            throw new JeecgBootException("被保险人列表不能为空");
        }
        String fileName="D:\\test/好运保体育意外险被保险人清单.xls";
        try (FileInputStream fis = new FileInputStream(fileName);
             Workbook workbook = new HSSFWorkbook(fis);
             OutputStream out = response.getOutputStream()) {

            Sheet sheet = validateTemplate(workbook);
            int startRowNum = 4; // 从第5行开始写入（0-based）
            Row styleRow = sheet.getRow(startRowNum+1);
            CellStyle[] cellStyles = getTemplateStyles(styleRow);
            // 写入数据
            for (int i = 0; i < persons.size(); i++) {
                FindInsureOrderPageResponseDTO person = persons.get(i);
                validatePersonData(person);
                Row row = sheet.createRow( startRowNum+ i);
                if (insureCompany==1){
                    writePersonRow(row, person, i + 1,cellStyles); // 序号从1开始
                } else if (false) {

                }else {
                    writePersonRow(row, person, i + 1,cellStyles); // 序号从1开始
                }

            }
            workbook.write(out);
            out.flush();
        } catch (Exception e) {
            throw new JeecgBootException("Excel操作失败: " + e.getMessage(), e);
        }
    }
    private CellStyle[] getTemplateStyles(Row templateRow) {
        if (templateRow == null) {
            return new CellStyle[0];
        }

        int cellCount = templateRow.getLastCellNum();
        CellStyle[] styles = new CellStyle[cellCount];

        for (int i = 0; i < cellCount; i++) {
            Cell cell = templateRow.getCell(i);
            if (cell != null) {
                styles[i] = cell.getCellStyle();
            }
        }
        return styles;
    }
    private void setResponseHeaders(HttpServletResponse response, String fileName) {
        try {
            String encodedFileName = URLEncoder.encode(fileName, "UTF-8")
                    .replaceAll("\\+", "%20");

            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-Disposition",
                    "attachment; filename=\"" + encodedFileName + ".xlsx\"");
            response.setCharacterEncoding("UTF-8");

            // 禁用缓存确保每次下载都是最新数据
            response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Expires", "0");

        } catch (Exception e) {
            throw new RuntimeException("设置响应头失败", e);
        }
    }

    private Sheet validateTemplate(Workbook workbook) throws JeecgBootException {
        if (workbook.getNumberOfSheets() == 0) {
            throw new JeecgBootException("模板文件中没有工作表");
        }

        Sheet sheet = workbook.getSheetAt(0);
        if (sheet.getPhysicalNumberOfRows() < 4) {
            throw new JeecgBootException("模板文件格式不正确，缺少表头行");
        }

        return sheet;
    }

    private void validatePersonData(FindInsureOrderPageResponseDTO person) throws JeecgBootException {
        if (person == null) {
            throw new JeecgBootException("被保险人信息不能为null");
        }

        if (person.getIdentityCard() == null || person.getIdentityCard().length() != 18) {
            throw new JeecgBootException("身份证号必须为18位");
        }
    }

    private  void writePersonRow(Row row, FindInsureOrderPageResponseDTO person, int serialNumber, CellStyle[] styles) {
        // Excel日期转换（1900年基准）
        String  birthday= ChineseIdCard18Utils.extractBirthDate(person.getIdentityCard());
        Gender sex = ChineseIdCard18Utils.extractGender(person.getIdentityCard());

        // 按模板顺序写入数据
        createCell(row, 0, serialNumber,styles); // 序号
        createCell(row, 1, person.getFullName(),styles);
        createCell(row, 2, "",styles);
        createCell(row, 3, "身份证",styles);
        createCell(row, 4, person.getIdentityCard(),styles);
        createCell(row, 5, "",styles);
        createCell(row, 6, "",styles);
        createCell(row, 7, sex.getDisplayName(),styles);
        createCell(row, 8, birthday,styles);
        createCell(row, 9, "其他",styles); // 运动类别
        createCell(row, 10, "其他",styles); // 人员类别
        createCell(row, 11, person.getPhone(),styles); // 手机号
        if (StringUtils.isNotEmpty( person.getPhone())){
            createCell(row, 12, "是",styles); // 手机号
        }else {
            createCell(row, 12, "否",styles); // 手机号
        }
        createCell(row, 13, "",styles);
        createCell(row, 14,"其他",styles);
        createCell(row, 15, "法定受益人",styles);
        createCell(row, 16, "",styles);
        createCell(row, 17, "",styles);
        createCell(row, 18, "",styles);
        createCell(row, 19, "",styles);
        createCell(row, 20, "",styles);
        createCell(row, 21, "",styles);
        createCell(row, 22, "",styles);
        createCell(row, 23, "",styles);
        createCell(row, 24, "",styles);
        createCell(row, 25, "",styles);
        createCell(row, 26, "",styles);


    }

    private  void createCell(Row row, int columnIndex, Object value, CellStyle[] styles) {
        Cell cell = row.createCell(columnIndex);

        if (value instanceof String) {
            cell.setCellValue((String) value);
        } else if (value instanceof Number) {
            cell.setCellValue(((Number) value).doubleValue());
        }
        // 应用样式（如果存在）
        if (styles != null && columnIndex < styles.length && styles[columnIndex] != null) {
            cell.setCellStyle(styles[columnIndex]);
        }
    }
}
