package cn.cslg.pas.controller;

import cn.cslg.pas.common.core.annotation.Permission;
import cn.cslg.pas.common.core.base.Constants;
import cn.cslg.pas.common.model.vo.PoiVO;
import cn.cslg.pas.common.utils.*;
import cn.cslg.pas.common.utils.auth.checkAuth;
import cn.cslg.pas.domain.SystemDict;
import cn.cslg.pas.domain.SystemDictAssociate;
import cn.cslg.pas.service.AreaService;
import cn.cslg.pas.service.PoiService;
import cn.cslg.pas.service.SystemDictAssociateService;
import cn.cslg.pas.service.SystemDictService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

@Tag(name = "通用功能")
@CrossOrigin
@RestController
@RequestMapping(Constants.API_VERSION_V2 + "/common")
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
public class CommonController {
    private final AreaService areaService;
    private final SystemDictService systemDictService;
    private final SystemDictAssociateService systemDictAssociateService;
    private final FileUtils fileUtils;
    private final PoiService poiService;

    @GetMapping("area")
    @Operation(summary = "获取区域")
    public String getAreaList() {
        return Response.success(areaService.getAreaList());
    }

    @GetMapping("data")
    @Operation(summary = "通用数据")
    public Object getCommonData(String keys) {
        List<String> typeList = StringUtils.changeStringToString(keys, ",");
        List<SystemDict> systemDictList = systemDictService.getSystemDictListByType(typeList);
        Map<String, Object> map = new HashMap<>();
        for (String type : typeList) {
            map.put(type, systemDictList.stream().filter(item -> item.getType().equals(type)).collect(Collectors.toList()));
        }
        return Response.success(map);
    }


    @GetMapping("/getDictMessage")
    @Operation(summary = "获取字典项信息")
    public String getDictMessage() {
        return systemDictService.getDictMessage();
    }

    @GetMapping("getDictTreeByParentDictValue")
    @Operation(summary = "获取字典项之间的级联关系")
    public String getDictTreeByParentDictValue(@RequestParam(value = "value") List<String> value, String type, Integer flag) {
        List<SystemDictAssociate> systemDictAssociates = systemDictAssociateService.getDictTreeByParentDictValue(value, type, flag);
        return Response.success(systemDictAssociates);
    }

    @GetMapping("static")
    @Operation(summary = "获取静态文件")
    public String getStaticFile(String path, String type, HttpServletResponse response, HttpServletRequest request) {
        String str = ResourceUtil.readUtf8Str(new ClassPathResource("/static/" + path).getPath());
        return Response.success(JsonUtils.jsonToMap(str));
    }

    @Permission(roles = {1, 2, 4})
    @checkAuth(FunId = "/workspace/folder/analyticSystem/chartAnalysis/moreMenu/export")
    @PostMapping("export")
    @Operation(summary = "导出分析结果")
    public void export(@RequestBody Map<String, Object> count, Integer type, String xAxis, HttpServletResponse response, HttpServletRequest request) {
        try {
            ExcelWriter writer;
            if (type != 3) {
                List<List<String>> rows = CollUtil.newArrayList(this.getRowsData(count, type, xAxis));
                writer = ExcelUtil.getWriter();
                writer.write(rows, true);
            } else {
                Set<String> rs = new HashSet<>(count.keySet());
                writer = new ExcelWriter();
                int i = 0;
                for (String key : rs) {
                    writer.setSheet(i);
                    writer.renameSheet(i, key);
                    List<List<String>> rows = CollUtil.newArrayList(this.getRowsData(JsonUtils.jsonToMap(count.get(key).toString()), 1, xAxis));
                    writer.write(rows, true);
                    i++;
                }
            }
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + DateUtil.format(new Date(), "yyyyMMddHHmmss") + ".xls");
            ServletOutputStream out = response.getOutputStream();
            writer.flush(out, true);
            writer.close();
            IoUtil.close(out);
        } catch (Exception e) {
//            e.printStackTrace();
        }
    }

    private List<List<String>> getRowsData(Map<String, Object> count, Integer type, String xAxis) {
        List<List<String>> row = new ArrayList<>();
        switch (type) {
            case 1:
                row.add(CollUtil.newArrayList(xAxis, "数量"));
                for (String key : count.keySet()) {
                    row.add(CollUtil.newArrayList(key, this.getValue(count.get(key))));
                }
                break;
            case 2:
                Set<String> cols = new HashSet<>();
                for (String x : count.keySet()) {
                    Map<String, Object> map = JsonUtils.objectToMap(count.get(x));
                    cols.addAll(map.keySet());
                }
                List<String> cs = new ArrayList<>();
                cs.add(xAxis);
                cs.addAll(cols);
                row.add(CollUtil.newArrayList(cs));
                for (String x : count.keySet()) {
                    List<String> rs = new ArrayList<>();
                    Map<String, Object> map = JsonUtils.objectToMap(count.get(x));
                    rs.add(x);
                    for (String y : cols) {
                        rs.add(this.getValue(map.get(y)));
                    }
                    row.add(CollUtil.newArrayList(rs));
                }
                break;
        }
        return row;
    }

    private String getValue(Object value) {
        if (StringUtils.isNotNull(value)) {
            return NumberUtil.roundStr(value.toString(), 0);
        } else {
            return "0";
        }
    }

    @GetMapping("download")
    @Operation(summary = "下载文件")
    public ResponseEntity<FileSystemResource> downloadSystemFile2(String url) throws IOException {
        File file = new File(fileUtils.getSystemPath() + url);
        HttpHeaders headers = new HttpHeaders();
        String fileName = DateUtils.getNowTimeFormat(DateUtils.YYYYMMDDHHMMSS) + "." + FileUtil.extName(file.getName());
        headers.add("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
        HttpStatus status = HttpStatus.OK;
        return new ResponseEntity<>(new FileSystemResource(file), headers, status);
    }

    @PostMapping("/upload/chunks")
    @Operation(summary = "上传分片")
    public String uploadChunks(MultipartFile file, String md5, Integer index) throws IOException {
        String tempPath = fileUtils.getTempPath(md5);
        File tempDirectory = new File(tempPath);
        if (!tempDirectory.exists()) {
            tempDirectory.mkdir();
        }
        String savePath = tempPath + FileUtils.FILE_SEPARATOR + md5 + "-" + index;
        file.transferTo(new File(savePath));
        return Response.success(true);
    }

    @PostMapping("/upload/chunks/merge")
    @Operation(summary = "合并分片")
    public String uploadChunksMerge(String md5, String fileName) {
        String tempPath = fileUtils.getTempPath(md5);
        List<File> fileList = FileUtil.loopFiles(tempPath);
        String tempFileName = IdUtil.simpleUUID() + "." + FileUtil.extName(fileName);
        String saveTempPath = fileUtils.getTempPath(tempFileName);
        String saveUrl = fileUtils.getDirectory(tempFileName);
        String savePath = fileUtils.getSystemPath(saveUrl);
        try (RandomAccessFile raf = new RandomAccessFile(new File(saveTempPath), "rw")) {
            for (int i = 0; i < fileList.size(); i++) {
                RandomAccessFile reader = new RandomAccessFile(new File(tempPath + FileUtils.FILE_SEPARATOR + md5 + "-" + i), "r");
                byte[] b = new byte[1024];
                int n = 0;
                while ((n = reader.read(b)) != -1) {
                    raf.write(b, 0, n);
                }
                reader.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        FileUtil.copy(saveTempPath, savePath, true);
        FileUtil.del(tempPath);
        FileUtil.del(saveTempPath);
        return Response.success(saveUrl);
    }

    @GetMapping("downloadPoi")
    @Operation(summary = "下载word文件")
    public void downloadPoi(@RequestBody PoiVO poiVO) throws IOException, InvalidFormatException {

        poiService.writeFile(poiVO);
    }

    @GetMapping("readPoi")
    @Operation(summary = "回显word文件")
    public PoiVO readPoi() throws IOException {

        return poiService.readWordFile();
    }
}
