package com.fuyuanshen.equipment.excel;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.fastjson2.JSON;
import com.fuyuanshen.common.core.domain.model.LoginUser;
import com.fuyuanshen.common.satoken.utils.LoginHelper;
import com.fuyuanshen.equipment.constants.DeviceConstants;
import com.fuyuanshen.equipment.domain.Device;
import com.fuyuanshen.equipment.domain.DeviceType;
import com.fuyuanshen.equipment.domain.dto.DeviceExcelImportDTO;
import com.fuyuanshen.equipment.domain.dto.ImportResult;
import com.fuyuanshen.equipment.domain.form.DeviceForm;
import com.fuyuanshen.equipment.handler.ImageWriteHandler;
import com.fuyuanshen.system.domain.vo.SysOssVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.apache.poi.xssf.usermodel.*;

import java.io.File;
import java.util.*;


@Slf4j
public class UploadDeviceDataListener implements ReadListener<DeviceExcelImportDTO> {

    // 存储图片数据的映射
    private Map<Integer, byte[]> rowImageMap = new HashMap<>();

    private DeviceImportParams params;

    private Map<Integer, Device> rowDeviceMap = new HashMap<>();
    private Map<Integer, DeviceExcelImportDTO> rowDtoMap = new HashMap<>();
    private List<Integer> rowIndexList = new ArrayList<>();

    private int successCount = 0;
    private int failureCount = 0;
    private final List<DeviceExcelImportDTO> failedRecords = new ArrayList<>();


    public UploadDeviceDataListener(DeviceImportParams params) {
        this.params = params;
    }


    public ImportResult getImportResult() {
        ImportResult result = new ImportResult();
        result.setSuccessCount(successCount);
        result.setFailureCount(failureCount);

        // 准备失败记录（包含图片数据）
        List<DeviceExcelImportDTO> failedRecordsWithImages = new ArrayList<>();

        for (DeviceExcelImportDTO failedRecord : failedRecords) {
            // 获取原始行号
            Integer rowIndex = null;
            for (Map.Entry<Integer, DeviceExcelImportDTO> entry : rowDtoMap.entrySet()) {
                if (entry.getValue() == failedRecord) {
                    rowIndex = entry.getKey();
                    break;
                }
            }

            if (rowIndex != null) {
                // 创建副本，避免修改原始数据
                DeviceExcelImportDTO recordWithImage = new DeviceExcelImportDTO();
                BeanUtil.copyProperties(failedRecord, recordWithImage);

                // 设置图片数据
                byte[] imageData = rowImageMap.get(rowIndex);
                if (imageData != null) {
                    recordWithImage.setDevicePicFromBytes(imageData);
                }

                failedRecordsWithImages.add(recordWithImage);
            } else {
                failedRecordsWithImages.add(failedRecord);
            }
        }

        result.setFailedRecords(failedRecordsWithImages);

        // 生成错误报告
        if (!failedRecordsWithImages.isEmpty()) {
            try {
                // 生成唯一的文件名
                String fileName = "import_errors_" + System.currentTimeMillis() + ".xlsx";

                // 创建错误报告目录
                String errorDirPath = params.getFilePath() + DeviceConstants.ERROR_REPORT_DIR;
                File errorDir = new File(errorDirPath);
                if (!errorDir.exists() && !errorDir.mkdirs()) {
                    log.error("无法创建错误报告目录: {}", errorDirPath);
                    return result;
                }

                // 保存错误报告到文件（包含图片）
                File errorFile = new File(errorDir, fileName);
                EasyExcel.write(errorFile, DeviceExcelImportDTO.class).registerWriteHandler(new ImageWriteHandler()) // 添加图片处理
                        .sheet("失败数据").doWrite(failedRecordsWithImages);

                // 生成访问URL
                SysOssVo upload = params.getOssService().upload(errorFile);
                result.setErrorExcelUrl(upload.getUrl());
                log.info("错误报告已保存: {}", errorFile.getAbsolutePath());
            } catch (Exception e) {
                log.error("生成错误报告失败", e);
            }
        }

        return result;
    }


    @Override
    public void invoke(DeviceExcelImportDTO data, AnalysisContext context) {
        log.info("解析到一条数据: {}", JSON.toJSONString(data));
        int rowIndex = context.readRowHolder().getRowIndex();

        Device device = new Device();
        BeanUtil.copyProperties(data, device, true);
        rowDeviceMap.put(rowIndex, device);
        rowDtoMap.put(rowIndex, data);
        rowIndexList.add(rowIndex);

    }


    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        try {
            processImages();
            processDataRowByRow();
            log.info("数据处理完成！成功：{}条，失败：{}条", successCount, failureCount);
        } catch (Exception e) {
            log.error("数据处理失败：{}", e.getMessage(), e);
            throw new RuntimeException("导入失败", e);
        }
    }


    private void processDataRowByRow() {
        LoginUser loginUser = LoginHelper.getLoginUser();
        for (Integer rowIndex : rowIndexList) {
            Device device = rowDeviceMap.get(rowIndex);
            DeviceExcelImportDTO originalDto = rowDtoMap.get(rowIndex);
            try {
                // 设备类型
                DeviceType deviceType = params.getDeviceTypeService().queryByName(device.getTypeName());
                // params.getDeviceService().save(device);
                DeviceForm deviceForm = new DeviceForm();
                deviceForm.setDeviceName(device.getDeviceName());
                deviceForm.setDeviceType(deviceType.getId());
                deviceForm.setRemark(device.getRemark());
                deviceForm.setDeviceMac(device.getDeviceMac());
                deviceForm.setDeviceImei(device.getDeviceImei());
                deviceForm.setBluetoothName(device.getBluetoothName());
                deviceForm.setDevicePic(device.getDevicePic());
                params.getDeviceService().addDevice(deviceForm);
                successCount++;
                log.info("行 {} 数据插入成功", rowIndex);
            } catch (Exception e) {
                failureCount++;
                failedRecords.add(originalDto);
                log.error("行 {} 数据插入失败: {}", rowIndex, e.getMessage());
            }
        }
    }

    private void processImages() {
        try (OPCPackage opcPackage = OPCPackage.open(params.getFile().getInputStream())) {
            ZipSecureFile.setMinInflateRatio(-1.0d);
            XSSFWorkbook workbook = new XSSFWorkbook(opcPackage);
            XSSFSheet sheet = workbook.getSheetAt(0);

            XSSFDrawing drawing = sheet.getDrawingPatriarch();
            if (drawing == null) return;

            for (XSSFShape shape : drawing.getShapes()) {
                if (shape instanceof XSSFPicture) {
                    XSSFPicture picture = (XSSFPicture) shape;
                    XSSFClientAnchor anchor = picture.getPreferredSize();
                    int rowIndex = anchor.getRow1();
                    int colIndex = anchor.getCol1();

                    if (colIndex == 2) {
                        Device device = rowDeviceMap.get(rowIndex);
                        if (device != null) {
                            try {
                                byte[] imageData = picture.getPictureData().getData();
                                String extraValue = getCellValue(sheet, rowIndex, 4);
                                String imageUrl = uploadAndGenerateUrl(imageData, extraValue);
                                device.setDevicePic(imageUrl);

                                // 2. 保存图片数据到DTO，用于错误报告
                                rowImageMap.put(rowIndex, imageData);
                            } catch (Exception e) {
                                log.error("行 {} 图片处理失败: {}", rowIndex, e.getMessage());
                                device.setDevicePic(null); // 设置为空，让插入继续
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("图片处理失败：{}", e.getMessage(), e);
        }
    }

    private String getCellValue(XSSFSheet sheet, int rowIndex, int colIndex) {
        XSSFRow row = sheet.getRow(rowIndex);
        if (row == null) return null;
        XSSFCell cell = row.getCell(colIndex);
        if (cell == null) return null;
        return cell.toString();
    }

    private String uploadAndGenerateUrl(byte[] imageData, String deviceMac) {
        if (imageData == null || imageData.length == 0) {
            log.warn("图片数据为空");
            return null;
        }
        try {
            String fileExtension = "jpg";
            String newFileName = "PS_" + new Random(8) + "." + fileExtension;
            SysOssVo upload = params.getOssService().upload(imageData, newFileName);
            return upload.getUrl();
        } catch (Exception e) {
            log.error("保存图片失败", e);
            return null;
        }
    }

}