package com.taais.biz.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.collection.CollectionUtil;
import com.taais.biz.domain.vo.BatchDataResult;
import cn.hutool.core.util.IdUtil;
import com.taais.biz.domain.Data;
import com.taais.biz.domain.bo.DataBo;
import com.taais.biz.domain.dto.DataAmplifyDto;
import com.taais.biz.domain.vo.DataExcelVo;
import com.taais.biz.domain.vo.DataSelectVo;
import com.taais.biz.domain.vo.DataVo;
import com.taais.biz.service.IDataService;
import com.taais.common.core.config.TaaisConfig;
import com.taais.common.core.core.domain.CommonResult;
import com.taais.common.core.core.page.PageResult;
import com.taais.common.excel.utils.ExcelUtil;
import com.taais.common.log.annotation.Log;
import com.taais.common.log.enums.BusinessType;
import com.taais.common.web.annotation.RepeatSubmit;
import com.taais.common.web.core.BaseController;
import com.taais.system.config.ServerConfig;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 数据管理Controller
 *
 * @author km
 * 2024-04-22
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/data")
public class DataController extends BaseController {
    private static final Logger log = LoggerFactory.getLogger(DataController.class);
    @Resource
    private IDataService dataService;
    @Autowired
    private ServerConfig serverConfig;

    /**
     * 查询数据管理列表
     */
    @SaCheckPermission("demo:data:list")
    @GetMapping("/list")
    public CommonResult<PageResult<DataVo>> list(DataBo dataBo) {
        return CommonResult.success(dataService.selectPage(dataBo));
    }

    /**
     * 获取 查询数据管理列表 搜索条目下拉列表
     *
     * @param field 查询的字段名称
     * @return {@link CommonResult }<{@link List }<{@link String }>>查询的字段名称 的所有种类
     */
    @SaCheckPermission("demo:data:list")
    @GetMapping("/getFromSelects")
    public CommonResult<List<DataSelectVo>> getFromSelects(String field) {
        return CommonResult.success(dataService.getFormSelects(field));
    }

    @GetMapping("/batchList")
    public CommonResult<List<BatchDataResult>> list() {
        return CommonResult.success(dataService.batchSelect());
    }

    /**
     * 导出数据管理列表
     */
    @SaCheckPermission("demo:data:export")
    @Log(title = "数据管理", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, @RequestBody DataBo dataBo) {
        // 查询数据列表
        List<DataVo> list = dataService.selectList(dataBo);
        if (CollectionUtil.isNotEmpty(dataBo.getSelectedIds())) {
            list = list.stream().filter(item -> dataBo.getSelectedIds().contains(item.getId())).collect(Collectors.toList());
        }

        // 创建一个临时目录用于存放文件
        String tempDirPath = System.getProperty("java.io.tmpdir") + "/export_" + System.currentTimeMillis();
        File tempDir = new File(tempDirPath);
        if (!tempDir.exists()) {
            log.info("创建临时目录:{}", tempDir.mkdirs());
        }
        String profile = TaaisConfig.getProfile();
        // 拷贝文件到临时目录
        for (DataVo dataVo : list) {
            File srcFile = new File(profile + dataVo.getUrl());
            File destFile = new File(tempDir, srcFile.getName());
            try {
                if (srcFile.exists()) {
                    FileUtils.copyFile(srcFile, destFile);
                } else {
                    log.error("图片源文件不存在：{}", srcFile.getName());
                }
                if (!StringUtils.isEmpty(dataVo.getLabelurl())) {
                    File labelurlFile = new File(profile + dataVo.getLabelurl());
                    File labelurlDestFile = new File(tempDir, labelurlFile.getName());
                    if (labelurlFile.exists()) {
                        FileUtils.copyFile(labelurlFile, labelurlDestFile);
                    } else {
                        log.error("标注源文件不存在：{}", labelurlFile.getName());
                    }
                }
            } catch (IOException e) {
                throw new RuntimeException("文件拷贝失败：" + srcFile.getName(), e);
            }
        }

        List<DataExcelVo> dataExcelVoList = new ArrayList<>();
        if (!list.isEmpty()) {
            dataExcelVoList = list.stream().map(info -> DataExcelVo.builder().id(info.getId()).name(info.getName())
                            .dataType(info.getDataType()).fileType(info.getFileType()).objectType(info.getObjectType())
                            .objectSubtype(info.getObjectSubtype()).batchNum(info.getBatchNum()).scene(info.getScene())
                            .dataSource(info.getDataSource()).gatherTime(info.getGatherTime()).gatherSpot(info.getGatherSpot())
                            .increment(info.getIncrement()).build())
                    .toList();
        }
        // 生成 Excel 文件并保存到临时目录
        File excelFile = new File(tempDir, "数据管理.xlsx");
        try (FileOutputStream fos = new FileOutputStream(excelFile)) {
            ExcelUtil.exportExcel(dataExcelVoList, "数据管理", DataExcelVo.class, fos);
        } catch (IOException e) {
            throw new RuntimeException("生成Excel文件失败", e);
        }
        // 将临时目录打包为ZIP文件C:\Users\10418\AppData\Local\Temp\/export_1726842007326
        File zipFile = new File(tempDir.getParent(), "export_" + System.currentTimeMillis() + ".zip");
        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile))) {
            for (File file : Objects.requireNonNull(tempDir.listFiles())) {
                zos.putNextEntry(new ZipEntry(file.getName()));
                try (FileInputStream fis = new FileInputStream(file)) {
                    IOUtils.copy(fis, zos);
                }
                zos.closeEntry();
            }
        } catch (IOException e) {
            throw new RuntimeException("打包ZIP文件失败", e);
        }

        // 设置响应头，返回ZIP文件给客户端
        response.setContentType("application/zip");
        response.setHeader("Content-Disposition", "attachment; filename=" + zipFile.getName());

        try (ServletOutputStream os = response.getOutputStream()) {
            FileUtils.copyFile(zipFile, os);
            os.flush();
        } catch (IOException e) {
            throw new RuntimeException("返回ZIP文件失败", e);
        } finally {
            // 删除临时文件
            FileUtils.deleteQuietly(tempDir);
            FileUtils.deleteQuietly(zipFile);
        }
    }

    /**
     * 获取数据管理详细信息
     */
    @SaCheckPermission("demo:data:query")
    @GetMapping(value = "/{id}")
    public CommonResult<DataVo> getInfo(@PathVariable Long id) {

        return CommonResult.success(dataService.selectById(id));
    }

    /**
     * 新增数据管理
     */
    @SaCheckPermission("demo:data:add")
    @Log(title = "数据管理", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping
    public CommonResult<Void> add(@Validated @RequestBody DataBo dataBo) {
        boolean inserted = dataService.insert(dataBo);
        if (!inserted) {
            return CommonResult.fail("新增数据管理记录失败！");
        }
        return CommonResult.success();
    }

    /**
     * 修改数据管理
     */
    @SaCheckPermission("demo:data:edit")
    @Log(title = "数据管理", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping
    public CommonResult<Void> edit(@Validated @RequestBody DataBo dataBo) {
        Boolean updated = dataService.update(dataBo);
        if (!updated) {
            return CommonResult.fail("修改数据管理记录失败!");
        }
        return CommonResult.success();
    }

    /**
     * 删除数据管理
     */
    @SaCheckPermission("demo:data:remove")
    @Log(title = "数据管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public CommonResult<Void> remove(@PathVariable Long[] ids) {
        boolean deleted = dataService.deleteByIds(ids);
        if (!deleted) {
            return CommonResult.fail("删除数据管理记录失败!");
        }
        return CommonResult.success();
    }

    @PostMapping("/importTemplate")
    public void importTemplate(HttpServletResponse response) {
        ExcelUtil.exportExcel(new ArrayList<>(), "用户数据", DataVo.class, response);
    }

    @PostMapping("/zip/upload")
    public CommonResult<Boolean> uploadZipFile(@RequestParam("file") MultipartFile file, Data dataInfo) throws Exception {
        if (file == null) {
            return CommonResult.fail("请上传.zip、.rar压缩文件。");
        }
        return dataService.uploadDataInfo(file, dataInfo);
    }

    @PostMapping("/amplify")
    public CommonResult<Boolean> dataAmplify(@RequestBody DataAmplifyDto dataAmplifyDto) {
        return dataService.dataAmplify(dataAmplifyDto);
    }

    @PostMapping("/amplifyForData")
    public CommonResult<Boolean> amplifyForData(@RequestParam("id") String id) {
        return dataService.amplifyForData(id);
    }
}
