package com.jojubanking.boot.module.system.controller.admin.refundapply;

import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.data.ImageData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.jojubanking.boot.module.system.controller.admin.student.vo.StudentExcelVO;
import com.jojubanking.boot.module.system.dal.dataobject.order.OrderDO;
import com.jojubanking.boot.module.system.framework.captcha.config.CaptchaProperties;
import com.jojubanking.boot.module.system.framework.tjfiles.TjfilesProperties;
import com.jojubanking.boot.module.system.util.xytj.DateDUtil;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.annotations.*;

import javax.imageio.ImageIO;
import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.function.Consumer;

import com.jojubanking.boot.framework.common.pojo.PageResult;
import com.jojubanking.boot.framework.common.pojo.CommonResult;
import static com.jojubanking.boot.framework.common.pojo.CommonResult.success;

import com.jojubanking.boot.framework.excel.core.util.ExcelUtils;

import com.jojubanking.boot.framework.operatelog.core.annotations.OperateLog;
import static com.jojubanking.boot.framework.operatelog.core.enums.OperateTypeEnum.*;
import static com.jojubanking.boot.module.system.util.xytj.BarCodeUtils.getBarCode;
import static com.jojubanking.boot.module.system.util.xytj.BarCodeUtils.insertWords;

import com.jojubanking.boot.module.system.controller.admin.refundapply.vo.*;
import com.jojubanking.boot.module.system.dal.dataobject.refundapply.RefundApplyDO;
import com.jojubanking.boot.module.system.convert.refundapply.RefundApplyConvert;
import com.jojubanking.boot.module.system.service.refundapply.RefundApplyService;

@Slf4j
@Api(tags = "管理后台 - 就诊卡退费申请")
@RestController
@RequestMapping("/system/refund-apply")
@Validated
public class RefundApplyController {
    @Resource
    private TjfilesProperties tjfilesProperties;

    @Resource
    private RefundApplyService refundApplyService;

    @PostMapping("/create")
    @ApiOperation("创建就诊卡退费申请")
    @PreAuthorize("@ss.hasPermission('system:refund-apply:create')")
    public CommonResult<Long> createRefundApply(@Valid @RequestBody RefundApplyCreateReqVO createReqVO) {
        return success(refundApplyService.createRefundApply(createReqVO));
    }

    @PutMapping("/update")
    @ApiOperation("更新就诊卡退费申请")
    @PreAuthorize("@ss.hasPermission('system:refund-apply:update')")
    public CommonResult<Boolean> updateRefundApply(@Valid @RequestBody RefundApplyUpdateReqVO updateReqVO) {
        refundApplyService.updateRefundApply(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @ApiOperation("删除就诊卡退费申请")
    @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
    @PreAuthorize("@ss.hasPermission('system:refund-apply:delete')")
    public CommonResult<Boolean> deleteRefundApply(@RequestParam("id") Long id) {
        refundApplyService.deleteRefundApply(id);
        return success(true);
    }

    @GetMapping("/get")
    @ApiOperation("获得就诊卡退费申请")
    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
    @PreAuthorize("@ss.hasPermission('system:refund-apply:query')")
    public CommonResult<RefundApplyRespVO> getRefundApply(@RequestParam("id") Long id) {
        RefundApplyDO refundApply = refundApplyService.getRefundApply(id);
        return success(RefundApplyConvert.INSTANCE.convert(refundApply));
    }

    @GetMapping("/list")
    @ApiOperation("获得就诊卡退费申请列表")
    @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
    @PreAuthorize("@ss.hasPermission('system:refund-apply:query')")
    public CommonResult<List<RefundApplyRespVO>> getRefundApplyList(@RequestParam("ids") Collection<Long> ids) {
        List<RefundApplyDO> list = refundApplyService.getRefundApplyList(ids);
        return success(RefundApplyConvert.INSTANCE.convertList(list));
    }

    @GetMapping("/page")
    @ApiOperation("获得就诊卡退费申请分页")
    @PreAuthorize("@ss.hasPermission('system:refund-apply:query')")
    public CommonResult<PageResult<RefundApplyRespVO>> getRefundApplyPage(@Valid RefundApplyPageReqVO pageVO) {
        PageResult<RefundApplyDO> pageResult = refundApplyService.getRefundApplyPage(pageVO);
        return success(RefundApplyConvert.INSTANCE.convertPage(pageResult));
    }

    public static String[] extractFileNameAndType(String url) {
        String[] parts = url.split("/");
        String fullFileName = parts[parts.length - 1];
        String[] nameParts = fullFileName.split("\\.");
        if (nameParts.length > 1) {
            String fileName = "";
            for (int i = 0; i < nameParts.length - 1; i++) {
                if (i > 0) {
                    fileName += ".";
                }
                fileName += nameParts[i];
            }
            String fileType = nameParts[nameParts.length - 1];
            return new String[]{fileName, fileType};
        }
        return null;
    }

    @GetMapping("/export-excel")
    @ApiOperation("导出就诊卡退费申请 Excel")
    @PreAuthorize("@ss.hasPermission('system:refund-apply:export')")
    @OperateLog(type = EXPORT)
    public void exportRefundApplyExcel(@Valid RefundApplyExportReqVO exportReqVO,
              HttpServletResponse response) throws IOException {
        List<RefundApplyDO> list = refundApplyService.getRefundApplyList(exportReqVO);
        List<RefundApplyExcelVO> datas = RefundApplyConvert.INSTANCE.convertList02(list);

        for (RefundApplyExcelVO data : datas) {
            processImage(data.getZidcardimg(), data::setWriteCellDataFileIdcard);
            processImage(data.getChildidcardimg(), data::setWriteCellDataFileChild);
            processImage(data.getZbankcardimg(), data::setWriteCellDataFileBank);
        }

//            ExcelUtils.write(response, "就诊卡退费申请.xls", "数据", RefundApplyExcelVO.class, datas);

            String tjpath = tjfilesProperties.getTjfilespath();

            String filename = tjpath + DateDUtil.getCurrentDateTime() + "就诊卡退费申请";
//            String filename = tjpath + DateDUtil.getCurrentDateTime() + "就诊卡退费申请";
            String srcFilePath = filename + ".xlsx";
            ExcelUtils.write(response, srcFilePath, "数据", RefundApplyExcelVO.class, datas);
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
//        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8");
        response.setContentType("application/vnd.ms-excel;charset=UTF-8");
        // 创建缓冲输入流
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFilePath));
             OutputStream os = response.getOutputStream()) {
            byte[] buffer = new byte[4096];
            int bytesRead;

            // 读取并写入文件
            while ((bytesRead = bis.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
        }

        log.info("end export");

    }
    private void processImage(String imageUrl, Consumer<WriteCellData<Void>> consumer) {
        if (imageUrl != null && !imageUrl.isEmpty()) {
            String[] result = extractFileNameAndType(imageUrl);
            if (result == null) {
                log.error("未找到有效的文件类型，URL: {}", imageUrl);
                return;
            }

            String tjpath = tjfilesProperties.getTjfilespath();

            String filePath = tjpath + result[0] + "." + result[1];
//            String filePath = tjpath + result[0] + "." + result[1];
            String fileType = result[1];
            log.info("处理图片文件，路径: {}", filePath);


            try {
                    // 压缩图片
                    byte[] compressedImageBytes = compressImage(filePath, fileType);
//                    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//                 FileInputStream inputStream = new FileInputStream(filePath)) {
//
//                byte[] buffer = new byte[1024 * 10];
//                int bytesRead;
//                while ((bytesRead = inputStream.read(buffer)) != -1) {
//                    outputStream.write(buffer, 0, bytesRead);
//                }
//
//                byte[] fileBytes = outputStream.toByteArray();
//                log.info("文件读取成功，字节数组长度: {}", fileBytes.length);

                WriteCellData<Void> writeCellData = new WriteCellData<>();
                consumer.accept(writeCellData);

                writeCellData.setType(CellDataTypeEnum.EMPTY);
                List<ImageData> imageDataList = new ArrayList<>();
                ImageData imageData = new ImageData();
                imageDataList.add(imageData);
                writeCellData.setImageDataList(imageDataList);

                imageData.setImage(compressedImageBytes);
                if ("jpg".equalsIgnoreCase(fileType) || "jpeg".equalsIgnoreCase(fileType)) {
                    imageData.setImageType(ImageData.ImageType.PICTURE_TYPE_JPEG);
                } else if ("png".equalsIgnoreCase(fileType)) {
                    imageData.setImageType(ImageData.ImageType.PICTURE_TYPE_PNG);
                }

                imageData.setTop(2);
                imageData.setRight(2);
                imageData.setBottom(2);
                imageData.setLeft(2);

            } catch (IOException e) {
                log.error("处理图片文件时发生错误，URL: {}", imageUrl, e);
                throw new RuntimeException("处理图片文件失败", e);
            }
        }

    }
    private byte[] compressImage(String filePath, String fileType) throws IOException {
        File originalFile = new File(filePath);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        if ("jpg".equalsIgnoreCase(fileType) || "jpeg".equalsIgnoreCase(fileType)) {
            Thumbnails.of(originalFile)
                    .scale(0.5) // 缩放比例为 0.5，可以根据需要调整
                    .outputQuality(0.5) // 输出质量为 0.5，可以根据需要调整
                    .outputFormat("jpg")
                    .toOutputStream(outputStream);
        } else if ("png".equalsIgnoreCase(fileType)) {
            Thumbnails.of(originalFile)
                    .scale(0.5) // 缩放比例为 0.5，可以根据需要调整
                    .outputFormat("png")
                    .toOutputStream(outputStream);
        }

        return outputStream.toByteArray();
    }
}
