package com.fuyuanshen.equipment.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.util.DateUtils;
import com.fuyuanshen.equipment.domain.Device;
import com.fuyuanshen.equipment.domain.DeviceType;
import com.fuyuanshen.equipment.domain.dto.DeviceExcelExportDTO;
import com.fuyuanshen.equipment.domain.dto.DeviceWithTypeExcelExportDTO;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @author: 默苍璃
 * @date: 2025-06-0618:22
 */
@Service
@Slf4j
public class DeviceExportService {

    public void export(List<Device> devices, HttpServletResponse response) {
        long startTime = System.currentTimeMillis();
        log.info("开始导出设备列表，设备数量: {}", devices.size());

        try {
            String fileName = "设备列表_" + System.currentTimeMillis() + ".xlsx";
            // 使用URLEncoder进行RFC 5987编码
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name()).replaceAll("\\+", "%20");

            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 使用RFC 5987标准编码文件名
            response.setHeader("Content-disposition", "attachment;filename*=UTF-8''" + encodedFileName);

            // 转换为DTO列表，使用并行流加速处理
            List<DeviceExcelExportDTO> dtoList = devices.parallelStream().map(device -> {
                long deviceProcessStartTime = System.currentTimeMillis();
                DeviceExcelExportDTO dto = new DeviceExcelExportDTO();
                dto.setDeviceName(device.getDeviceName());
                dto.setDeviceMac(device.getDeviceMac());
                // 设备IMEI
                dto.setDeviceImei(device.getDeviceImei());
                // 蓝牙名称
                dto.setBluetoothName(device.getBluetoothName());
                dto.setRemark(device.getRemark());
                dto.setTypeName(device.getTypeName());
                dto.setCreateBy(device.getCreateByName());
                Integer bindingStatus = device.getBindingStatus();
                dto.setBindingStatus(bindingStatus == 1 ? "已绑定" : "未绑定");
                // 时间戳转换
                dto.setCreateTime(DateUtils.format(device.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));

                // 处理图片URL转换
                handleDevicePic(device, dto);

                long deviceProcessEndTime = System.currentTimeMillis();
                log.info("单个设备处理耗时: {} ms, 设备ID: {}", (deviceProcessEndTime - deviceProcessStartTime), device.getId());
                return dto;
            }).collect(Collectors.toList());

            // 写入Excel
            long excelWriteStartTime = System.currentTimeMillis();
            EasyExcel.write(response.getOutputStream(), DeviceExcelExportDTO.class).sheet("设备数据").doWrite(dtoList);
            long excelWriteEndTime = System.currentTimeMillis();

            long endTime = System.currentTimeMillis();
            log.info("设备列表导出完成，总耗时: {} ms，设备数量: {}，Excel写入耗时: {} ms",
                    (endTime - startTime), devices.size(), (excelWriteEndTime - excelWriteStartTime));

        } catch (IOException e) {
            log.error("导出Excel失败", e);
            throw new RuntimeException("导出Excel失败", e);
        }
    }



    /**
     * 导出设备数据（包含完整设备类型信息）
     *
     * @param devices
     * @param deviceTypes
     * @param response
     */
    public void exportWithTypeInfo(List<Device> devices, List<DeviceType> deviceTypes, HttpServletResponse response) {
        long startTime = System.currentTimeMillis();
        log.info("开始导出设备列表（含类型详情），设备数量: {}", devices.size());

        try {
            String fileName = "设备列表_含类型详情_" + System.currentTimeMillis() + ".xlsx";
            // 使用URLEncoder进行RFC 5987编码
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name()).replaceAll("\\+", "%20");

            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 使用RFC 5987标准编码文件名
            response.setHeader("Content-disposition", "attachment;filename*=UTF-8''" + encodedFileName);

            // 构建设备类型映射
            Map<Long, DeviceType> deviceTypeMap = deviceTypes.stream()
                    .collect(Collectors.toMap(DeviceType::getId, deviceType -> deviceType));

            // 转换为DTO列表，使用并行流加速处理
            List<DeviceWithTypeExcelExportDTO> dtoList = devices.parallelStream().map(device -> {
                long deviceProcessStartTime = System.currentTimeMillis();
                DeviceWithTypeExcelExportDTO dto = new DeviceWithTypeExcelExportDTO();
                dto.setDeviceName(device.getDeviceName());
                dto.setDeviceMac(device.getDeviceMac());
                // 设备IMEI
                dto.setDeviceImei(device.getDeviceImei());
                // 蓝牙名称
                dto.setBluetoothName(device.getBluetoothName());
                dto.setRemark(device.getRemark());
                dto.setTypeName(device.getTypeName());
                dto.setCreateBy(device.getCreateByName());
                Integer bindingStatus = device.getBindingStatus();
                dto.setBindingStatus(bindingStatus == 1 ? "已绑定" : "未绑定");
                // 时间戳转换
                dto.setCreateTime(DateUtils.format(device.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));

                // 获取设备类型详细信息
                DeviceType deviceType = deviceTypeMap.get(device.getDeviceType());
                if (deviceType != null) {
                    // 处理是否支持蓝牙
                    if (deviceType.getIsSupportBle() != null) {
                        dto.setIsSupportBle(deviceType.getIsSupportBle() ? "是" : "否");
                    } else {
                        dto.setIsSupportBle("未知");
                    }

                    // 处理定位方式
                    if (deviceType.getLocateMode() != null) {
                        dto.setLocateMode(convertLocateMode(deviceType.getLocateMode()));
                    } else {
                        dto.setLocateMode("");
                    }

                    // 处理通讯方式
                    if (deviceType.getCommunicationMode() != null) {
                        dto.setCommunicationMode(convertCommunicationMode(deviceType.getCommunicationMode()));
                    } else {
                        dto.setCommunicationMode("");
                    }

                    // 处理APP页面跳转字典
                    dto.setAppModelDictionary(deviceType.getAppModelDictionary() != null ? deviceType.getAppModelDictionary() : "");

                    // 处理PC页面跳转字典
                    dto.setPcModelDictionary(deviceType.getPcModelDictionary() != null ? deviceType.getPcModelDictionary() : "");
                } else {
                    dto.setIsSupportBle("未知");
                    dto.setLocateMode("");
                    dto.setCommunicationMode("");
                    dto.setAppModelDictionary("");
                    dto.setPcModelDictionary("");
                }

                // 处理图片URL转换
                handleDevicePicForTypeExport(device, dto);
                return dto;
            }).collect(Collectors.toList());

            // 写入Excel
            long excelWriteStartTime = System.currentTimeMillis();
            EasyExcel.write(response.getOutputStream(), DeviceWithTypeExcelExportDTO.class).sheet("设备数据含类型详情").doWrite(dtoList);
            long excelWriteEndTime = System.currentTimeMillis();

            long endTime = System.currentTimeMillis();
            log.info("设备列表（含类型详情）导出完成，总耗时: {} ms，设备数量: {}，Excel写入耗时: {} ms",
                    (endTime - startTime), devices.size(), (excelWriteEndTime - excelWriteStartTime));

        } catch (IOException e) {
            log.error("导出Excel失败", e);
            throw new RuntimeException("导出Excel失败", e);
        }
    }


    /**
     * 转换定位方式代码为中文描述
     *
     * @param locateMode 定位方式代码 (0:无;1:GPS;2:基站;3:wifi;4:北斗)
     * @return 中文描述
     */
    private String convertLocateMode(String locateMode) {
        switch (locateMode) {
            case "0":
                return "无";
            case "1":
                return "GPS";
            case "2":
                return "基站";
            case "3":
                return "wifi";
            case "4":
                return "北斗";
            default:
                return locateMode;
        }
    }

    /**
     * 转换联网方式代码为中文描述
     *
     * @param networkWay 联网方式代码 (0:无;1:4G;2:WIFI)
     * @return 中文描述
     */
    private String convertNetworkWay(String networkWay) {
        switch (networkWay) {
            case "0":
                return "无";
            case "1":
                return "4G";
            case "2":
                return "WIFI";
            default:
                return networkWay;
        }
    }

    /**
     * 转换通讯方式代码为中文描述
     *
     * @param communicationMode 通讯方式代码 (0:4G;1:蓝牙)
     * @return 中文描述
     */
    private String convertCommunicationMode(String communicationMode) {
        switch (communicationMode) {
            case "0":
                return "4G";
            case "1":
                return "蓝牙";
            case "2":
                return "4G&蓝牙";
            default:
                return communicationMode;
        }
    }


    // 在DeviceExportService中添加并发控制
    private static final Semaphore imageLoadSemaphore = new Semaphore(10); // 增加到最多同时加载10张图片

    private void handleDevicePic(Device device, DeviceExcelExportDTO dto) {
        String picUrl = device.getDevicePic();

        if (picUrl != null && !picUrl.trim().isEmpty()) {
            try {
                // 获取加载图片的许可，带超时控制
                if (!imageLoadSemaphore.tryAcquire(5, TimeUnit.SECONDS)) {
                    dto.setDevicePic(null);
                    return;
                }

                try {
                    // 自动将HTTP转换为HTTPS以避免重定向问题
                    if (picUrl.startsWith("http://")) {
                        picUrl = "https://" + picUrl.substring(7);
                    }

                    // 尝试创建URL对象（会自动验证格式）
                    URL url = new URL(picUrl);
                    dto.setDevicePic(url);
                } finally {
                    // 释放许可
                    imageLoadSemaphore.release();
                }
            } catch (Exception e) {
                dto.setDevicePic(null);
            }
        } else {
            dto.setDevicePic(null);
        }
    }


    private void handleDevicePicForTypeExport(Device device, DeviceWithTypeExcelExportDTO dto) {
        String picUrl = device.getDevicePic();

        if (picUrl != null && !picUrl.trim().isEmpty()) {
            try {
                // 获取加载图片的许可，带超时控制
                if (!imageLoadSemaphore.tryAcquire(5, TimeUnit.SECONDS)) {
                    dto.setDevicePic(null);
                    return;
                }

                try {
                    picUrl = convertUrl(picUrl);

                    // 尝试创建URL对象（会自动验证格式）
                    URL url = new URL(picUrl);
                    dto.setDevicePic(url);

                } finally {
                    // 释放许可
                    imageLoadSemaphore.release();
                }
            } catch (Exception e) {
                dto.setDevicePic(null);
            }
        } else {
            dto.setDevicePic(null);
        }
    }

    /**
     * 转换图片URL为HTTP
     * 转回minio格式
     *
     * @param originalUrl 原始URL
     * @return 转换后的URL
     */

    public String convertUrl(String originalUrl) {
        String result = originalUrl.replace("https://fuyuanshen.com", "http://120.79.224.186:9000");
        result = result.replace("http://fuyuanshen.com", "http://120.79.224.186:9000");
        return result;
    }


}