package cn.newfeifan.mall.module.infra.controller.admin.file;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import cn.newfeifan.mall.framework.common.pojo.CommonResult;
import cn.newfeifan.mall.framework.common.pojo.PageResult;
import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
import cn.newfeifan.mall.framework.common.util.servlet.ServletUtils;
import cn.newfeifan.mall.framework.operatelog.core.annotations.OperateLog;
import cn.newfeifan.mall.module.infra.controller.admin.file.vo.file.FilePageReqVO;
import cn.newfeifan.mall.module.infra.controller.admin.file.vo.file.FileRespVO;
import cn.newfeifan.mall.module.infra.controller.admin.file.vo.file.FileUploadReqVO;
import cn.newfeifan.mall.module.infra.dal.dataobject.file.FileDO;
import cn.newfeifan.mall.module.infra.service.file.FileService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import java.io.File;
import java.io.IOException;
import java.util.Map;

import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

import static cn.newfeifan.mall.framework.common.pojo.CommonResult.success;

@Tag(name = "管理后台 - 文件存储")
@RestController
@RequestMapping("/infra/file")
@Validated
@Slf4j
public class FileController {

    @Resource
    private FileService fileService;

    @PostMapping("/upload")
    @Operation(summary = "上传文件")
    @OperateLog(logArgs = false) // 上传文件，没有记录操作日志的必要
    public CommonResult<String> uploadFile(FileUploadReqVO uploadReqVO) throws Exception {
        MultipartFile file = uploadReqVO.getFile();
        String path = uploadReqVO.getPath();
        return success(fileService.createFile(file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream())));
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除文件")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('infra:file:delete')")
    public CommonResult<Boolean> deleteFile(@RequestParam("id") Long id) throws Exception {
        fileService.deleteFile(id);
        return success(true);
    }

    @GetMapping("/{configId}/get/**")
    @PermitAll
    @Operation(summary = "下载文件")
    @Parameter(name = "configId", description = "配置编号", required = true)
    public void getFileContent(HttpServletRequest request,
                               HttpServletResponse response,
                               @PathVariable("configId") Long configId) throws Exception {
        // 获取请求的路径
        String path = StrUtil.subAfter(request.getRequestURI(), "/get/", false);
        if (StrUtil.isEmpty(path)) {
            throw new IllegalArgumentException("结尾的 path 路径必须传递");
        }
        // 解码，解决中文路径的问题 https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/807/
        path = URLUtil.decode(path);
        log.info("=====path:{}", path);

        // 读取内容
        byte[] content = fileService.getFileContent(configId, path);
        if (content == null) {
            log.warn("[getFileContent][configId({}) path({}) 文件不存在]", configId, path);
            response.setStatus(HttpStatus.NOT_FOUND.value());
            return;
        }
        if (path.contains("mp4")) {
            String range = request.getHeader("Range");
            log.info("========Range:{}", range);
            ServletUtils.transfer(content, range, response, "/data/file/" + path);
        } else {
            log.info("===============开始获取文件");
            ServletUtils.writeAttachment(response, path, content, request);
        }
    }

    @GetMapping("/page")
    @Operation(summary = "获得文件分页")
    @PreAuthorize("@ss.hasPermission('infra:file:query')")
    public CommonResult<PageResult<FileRespVO>> getFilePage(@Valid FilePageReqVO pageVO) {
        PageResult<FileDO> pageResult = fileService.getFilePage(pageVO);
        return success(BeanUtils.toBean(pageResult, FileRespVO.class));
    }

    @GetMapping("/getCarNumber")
    @Operation(summary = "获取识别的车牌号")
    @PreAuthorize("@ss.hasPermission('infra:file:delete')")
    public CommonResult<String> getCarNumber(@RequestParam("image_path") MultipartFile file) throws IOException {
        OkHttpClient client = new OkHttpClient().newBuilder()
                .build();
        MediaType mediaType = MediaType.parse("application/octet-stream");
        RequestBody fileRequestBody = RequestBody.create(mediaType, file.getBytes());

        RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
                .addFormDataPart("image_path", file.getOriginalFilename(), fileRequestBody)
                .build();
        Request request = new Request.Builder()
                .url("http://127.0.0.1:5000/recognize_plate")
                .method("POST", body)
                .addHeader("Accept", "*/*")
                .addHeader("Host", "127.0.0.1:5000")
                .addHeader("Connection", "keep-alive")
                .addHeader("Content-Type", "multipart/form-data; boundary=--------------------------174769765109986170531912")
                .build();
        Response response = client.newCall(request).execute();
        if (response.isSuccessful()) {
            ObjectMapper objectMapper = new ObjectMapper();
            // 直接将响应体的字符串内容解析为Map（简单示例，如果有对应Java POJO类，可以解析为具体的POJO对象）
            @SuppressWarnings("unchecked")
            Map<String, Object> resultMap = objectMapper.readValue(response.body().string(), Map.class);
            resultMap.forEach((k, v) -> {
                log.info("=====k:{},v:{}",k,v);
            });
            Object data = resultMap.get("data");
            log.info("=====data:{}",data);
            if (data.equals("success")) {
                System.out.println("解析后的plate_number值: " + resultMap.get("plate_number"));
                return success(resultMap.get("plate_number").toString());
            }
        }
        return success("error");
    }
}
