package com.openhis.web.reportmanage.utils;

import com.core.common.core.domain.R;
import com.openhis.common.constant.CommonConstants;
import com.openhis.web.reportmanage.dto.InpatientMedicalRecordHomePageCollectionDto;
import org.apache.logging.log4j.util.Supplier;
import org.dom4j.DocumentException;

import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.List;

/**
 * 住院病案csv做成
 *
 * @author yuxj
 * @date 2025-08-25
 */
public final class CsvFillerUtil {

    // 表头
    public static final String headers =
        "A01,A02,A48,A49,B12,B15,A47,A46C,A11,A12C,A13,A14,A15C,A21C,A38C,A19C,A20N,A20,A22,A23C,A24,A25C,A26,A27,A28C,A29,A30,A31C,A32,A33C,A34,A35,B38,B11C,B13C,B14,B21C,B16C,B17,B20,C01C,C02N,F01,F02C,F03N,F04,C03C,C04N,C05C,F05,C06x01C,C07x01N,C08x01C,F06x01,C06x02C,C07x02N,C08x02C,F06x02,C06x03C,C07x03N,C08x03C,F06x03,C06x04C,C07x04N,C08x04C,F06x04,C06x05C,C07x05N,C08x05C,F06x05,C06x06C,C07x06N,C08x06C,F06x06,C06x07C,C07x07N,C08x07C,F06x07,C06x08C,C07x08N,C08x08C,F06x08,C06x09C,C07x09N,C08x09C,F06x09,C06x10C,C07x10N,C08x10C,F06x10,C06x11C,C07x11N,C08x11C,F06x11,C06x12C,C07x12N,C08x12C,F06x12,C06x13C,C07x13N,C08x13C,F06x13,C06x14C,C07x14N,C08x14C,F06x14,C06x15C,C07x15N,C08x15C,F06x15,C06x16C,C07x16N,C08x16C,F06x16,C06x17C,C07x17N,C08x17C,F06x17,C06x18C,C07x18N,C08x18C,F06x18,C06x19C,C07x19N,C08x19C,F06x19,C06x20C,C07x20N,C08x20C,F06x20,C06x21C,C07x21N,C08x21C,F06x21,C06x22C,C07x22N,C08x22C,F06x22,C06x23C,C07x23N,C08x23C,F06x23,C06x24C,C07x24N,C08x24C,F06x24,C06x25C,C07x25N,C08x25C,F06x25,C06x26C,C07x26N,C08x26C,F06x26,C06x27C,C07x27N,C08x27C,F06x27,C06x28C,C07x28N,C08x28C,F06x28,C06x29C,C07x29N,C08x29C,F06x29,C06x30C,C07x30N,C08x30C,F06x30,C06x31C,C07x31N,C08x31C,F06x31,C06x32C,C07x32N,C08x32C,F06x32,C06x33C,C07x33N,C08x33C,F06x33,C06x34C,C07x34N,C08x34C,F06x34,C06x35C,C07x35N,C08x35C,F06x35,C06x36C,C07x36N,C08x36C,F06x36,C06x37C,C07x37N,C08x37C,F06x37,C06x38C,C07x38N,C08x38C,F06x38,C06x39C,C07x39N,C08x39C,F06x39,C06x40C,C07x40N,C08x40C,F06x40,C09C,C10N,C11,F07x01C,F08x01N,F09x01,F07x02C,F08x02N,F09x02,C12C,C13N,C24C,C25,F10,F11,F12,B22C,B22,B23C,B23,B24C,B24,B25C,B25,B26C,B26,B27,B28,B29,B30C,B31,B32,B33,C34C,C26C,C27C,C14x01C,C15x01N,C16x01,C17x01,F13,C18x01,C19x01,C20x01,C21x01C,C22x01C,F15,C23x01,C35x01C,C36x01N,C37x01,C38x01,F14x01,C39x01,C40x01,C41x01,C42x01C,C43x01C,F16x01,C44x01,C35x02C,C36x02N,C37x02,C38x02,F14x02,C39x02,C40x02,C41x02,C42x02C,C43x02C,F16x02,C44x02,C35x03C,C36x03N,C37x03,C38x03,F14x03,C39x03,C40x03,C41x03,C42x03C,C43x03C,F16x03,C44x03,C35x04C,C36x04N,C37x04,C38x04,F14x04,C39x04,C40x04,C41x04,C42x04C,C43x04C,F16x04,C44x04,C35x05C,C36x05N,C37x05,C38x05,F14x05,C39x05,C40x05,C41x05,C42x05C,C43x05C,F16x05,C44x05,C35x06C,C36x06N,C37x06,C38x06,F14x06,C39x06,C40x06,C41x06,C42x06C,C43x06C,F16x06,C44x06,C35x07C,C36x07N,C37x07,C38x07,F14x07,C39x07,C40x07,C41x07,C42x07C,C43x07C,F16x07,C44x07,C35x08C,C36x08N,C37x08,C38x08,F14x08,C39x08,C40x08,C41x08,C42x08C,C43x08C,F16x08,C44x08,C35x09C,C36x09N,C37x09,C38x09,F14x09,C39x09,C40x09,C41x09,C42x09C,C43x09C,F16x09,C44x09,C35x10C,C36x10N,C37x10,C38x10,F14x10,C39x10,C40x10,C41x10,C42x10C,C43x10C,F16x10,C44x10,C35x11C,C36x11N,C37x11,C38x11,F14x11,C39x11,C40x11,C41x11,C42x11C,C43x11C,F16x11,C44x11,C35x12C,C36x12N,C37x12,C38x12,F14x12,C39x12,C40x12,C41x12,C42x12C,C43x12C,F16x12,C44x12,C35x13C,C36x13N,C37x13,C38x13,F14x13,C39x13,C40x13,C41x13,C42x13C,C43x13C,F16x13,C44x13,C35x14C,C36x14N,C37x14,C38x14,F14x14,C39x14,C40x14,C41x14,C42x14C,C43x14C,F16x14,C44x14,C35x15C,C36x15N,C37x15,C38x15,F14x15,C39x15,C40x15,C41x15,C42x15C,C43x15C,F16x15,C44x15,C35x16C,C36x16N,C37x16,C38x16,F14x16,C39x16,C40x16,C41x16,C42x16C,C43x16C,F16x16,C44x16,C35x17C,C36x17N,C37x17,C38x17,F14x17,C39x17,C40x17,C41x17,C42x17C,C43x17C,F16x17,C44x17,C35x18C,C36x18N,C37x18,C38x18,F14x18,C39x18,C40x18,C41x18,C42x18C,C43x18C,F16x18,C44x18,C35x19C,C36x19N,C37x19,C38x19,F14x19,C39x19,C40x19,C41x19,C42x19C,C43x19C,F16x19,C44x19,C35x20C,C36x20N,C37x20,C38x20,F14x20,C39x20,C40x20,C41x20,C42x20C,C43x20C,F16x20,C44x20,C35x21C,C36x21N,C37x21,C38x21,F14x21,C39x21,C40x21,C41x21,C42x21C,C43x21C,F16x21,C44x21,C35x22C,C36x22N,C37x22,C38x22,F14x22,C39x22,C40x22,C41x22,C42x22C,C43x22C,F16x22,C44x22,C35x23C,C36x23N,C37x23,C38x23,F14x23,C39x23,C40x23,C41x23,C42x23C,C43x23C,F16x23,C44x23,C35x24C,C36x24N,C37x24,C38x24,F14x24,C39x24,C40x24,C41x24,C42x24C,C43x24C,F16x24,C44x24,C35x25C,C36x25N,C37x25,C38x25,F14x25,C39x25,C40x25,C41x25,C42x25C,C43x25C,F16x25,C44x25,C35x26C,C36x26N,C37x26,C38x26,F14x26,C39x26,C40x26,C41x26,C42x26C,C43x26C,F16x26,C44x26,C35x27C,C36x27N,C37x27,C38x27,F14x27,C39x27,C40x27,C41x27,C42x27C,C43x27C,F16x27,C44x27,C35x28C,C36x28N,C37x28,C38x28,F14x28,C39x28,C40x28,C41x28,C42x28C,C43x28C,F16x28,C44x28,C35x29C,C36x29N,C37x29,C38x29,F14x29,C39x29,C40x29,C41x29,C42x29C,C43x29C,F16x29,C44x29,C35x30C,C36x30N,C37x30,C38x30,F14x30,C39x30,C40x30,C41x30,C42x30C,C43x30C,F16x30,C44x30,C35x31C,C36x31N,C37x31,C38x31,F14x31,C39x31,C40x31,C41x31,C42x31C,C43x31C,F16x31,C44x31,C35x32C,C36x32N,C37x32,C38x32,F14x32,C39x32,C40x32,C41x32,C42x32C,C43x32C,F16x32,C44x32,C35x33C,C36x33N,C37x33,C38x33,F14x33,C39x33,C40x33,C41x33,C42x33C,C43x33C,F16x33,C44x33,C35x34C,C36x34N,C37x34,C38x34,F14x34,C39x34,C40x34,C41x34,C42x34C,C43x34C,F16x34,C44x34,C35x35C,C36x35N,C37x35,C38x35,F14x35,C39x35,C40x35,C41x35,C42x35C,C43x35C,F16x35,C44x35,C35x36C,C36x36N,C37x36,C38x36,F14x36,C39x36,C40x36,C41x36,C42x36C,C43x36C,F16x36,C44x36,C35x37C,C36x37N,C37x37,C38x37,F14x37,C39x37,C40x37,C41x37,C42x37C,C43x37C,F16x37,C44x37,C35x38C,C36x38N,C37x38,C38x38,F14x38,C39x38,C40x38,C41x38,C42x38C,C43x38C,F16x38,C44x38,C35x39C,C36x39N,C37x39,C38x39,F14x39,C39x39,C40x39,C41x39,C42x39C,C43x39C,F16x39,C44x39,C35x40C,C36x40N,C37x40,C38x40,F14x40,C39x40,C40x40,C41x40,C42x40C,C43x40C,F16x40,C44x40,F17,F18,F19,F20,F21,F22,F23,F24,F25,F26,A16,A18x01,A18x02,A18x03,A18x04,A18x05,A17,C28,C29,C30,C31,C32,C33,C47,C48x01C,C49x01,C50x01,C48x02C,C49x02,C50x02,C48x03C,C49x03,C50x03,C48x04C,C49x04,C50x04,C48x05C,C49x05,C50x05,B36C,B37,B34C,B35,D01,D09,D11,D12,D13,D14,D15,D16,D17,D18,D19,D19x01,D20,D20x01,D20x02,D21,D22,D23,D23x01,D24,D25,D26,D27,D28,D29,D30,D31,D32,D33,D34";

    // 时间戳格式：年月日时分秒（确保文件名唯一）
    private static final SimpleDateFormat TIME_FORMATTER = new SimpleDateFormat("yyyyMMddHHmmss");

    /**
     * 住院病案csv做成
     *
     * @param response
     * @param dto 文件内容
     *
     */
    public static void makeCsvFile(HttpServletResponse response, List<InpatientMedicalRecordHomePageCollectionDto> dto)
        throws IOException {

        // 时间戳日期
        String timestamp = TIME_FORMATTER.format(new Date());

        // 生成的pdf模板文件全路径
        String fileName = "\\hqmsts_" + timestamp + ".csv";
        //设置响应头信息
        response.setContentType("text/csv");
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");

        try (BufferedWriter writer =
            new BufferedWriter(new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8))) {
            // 写入UTF-8 BOM，解决Excel打开乱码问题
            writer.write('\ufeff');

            // 写入表头
            writer.write(headers);
            writer.newLine();

            int totalCount = 0;
            // 写入数据行
            if (dto != null && !dto.isEmpty()) {
                for (InpatientMedicalRecordHomePageCollectionDto row : dto) {
                    writer.write(convert(row));
                    writer.newLine();

                    totalCount++;
                }
            }
            writer.flush();
            System.out.printf("CSV文件生成完成，共写入 %d 条记录%n", totalCount);
        } catch (IOException e) {
            System.out.printf("做成csv时发生错误：" + e.getMessage());
        }

    }

    /**
     * 处理已存在的文件：重命名为原文件名+时间戳
     * 
     * @param targetFile 目标文件
     */
    private static void handleExistingFile(File targetFile) {
        if (targetFile.exists()) {
            // 获取文件路径和名称
            String parentPath = targetFile.getParent();
            String fileName = targetFile.getName();

            // 分离文件名和扩展名
            int dotIndex = fileName.lastIndexOf(".");
            String baseName = (dotIndex > 0) ? fileName.substring(0, dotIndex) : fileName;
            String extension = (dotIndex > 0) ? fileName.substring(dotIndex) : "";

            // 生成带时间戳的新文件名
            String timestamp = TIME_FORMATTER.format(new Date());
            String newFileName = baseName + "_" + timestamp + extension;
            File renamedFile = new File(parentPath, newFileName);

            // 重命名文件
            boolean renamed = targetFile.renameTo(renamedFile);
            if (renamed) {
                System.out.println("文件已存在，已重命名为：" + renamedFile.getAbsolutePath());
            } else {
                throw new RuntimeException("无法重命名已存在的文件：" + targetFile.getAbsolutePath());
            }
        }
    }

    /**
     * 将DTO对象转换为逗号分隔的字符串（适用于无嵌套结构的DTO）
     * 
     * @param dto 要转换的DTO对象
     * @return 逗号分隔的字符串
     */
    public static String convert(Object dto) {
        if (dto == null) {
            return "";
        }

        List<String> fieldValues = new ArrayList<>();
        // 获取当前类的所有声明字段（不包含父类，如需包含可修改）
        Field[] fields = dto.getClass().getDeclaredFields();

        for (Field field : fields) {
            try {
                // 设置可访问私有字段
                field.setAccessible(true);
                Object value = field.get(dto);

                // 转换为字符串并处理特殊字符
                String strValue = value != null ? value.toString() : "";

                // 处理CSV中的特殊字符
                // 如果包含逗号、引号或换行符，需要用引号包裹
                if (strValue.contains(",") || strValue.contains("\"") || strValue.contains("\n")
                    || strValue.contains("\r")) {
                    // 转义双引号为两个双引号
                    fieldValues.add("\"" + strValue.replace("\"", "\"\"") + "\"");
                } else {
                    fieldValues.add(strValue);
                }
            } catch (IllegalAccessException e) {
                // 处理访问异常，可根据需要调整
                fieldValues.add("");
            }
        }

        // 用逗号连接所有字段值
        return String.join(CommonConstants.Common.COMMA, fieldValues);
    }
}