package cn.exploring.engine.server.wx.web;

import cn.exploring.engine.server.core.qcode.QCodeService;
import cn.exploring.engine.server.core.storage.StorageService;
import cn.exploring.engine.server.core.tencent.TencentCloudService;
import cn.exploring.engine.server.core.util.CharUtil;
import cn.exploring.engine.server.core.util.ImageUtil;
import cn.exploring.engine.server.core.util.ResponseUtil;
import cn.exploring.engine.server.db.domain.WxStorage;
import cn.exploring.engine.server.db.domain.WxUser;
import cn.exploring.engine.server.db.service.WxStorageService;
import cn.exploring.engine.server.db.service.WxUserService;
import cn.exploring.engine.server.db.util.RedisUtil;
import cn.exploring.engine.server.wx.annotation.LoginUser;
import cn.exploring.engine.server.wx.util.WxResponseCode;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * 对象存储服务
 */
@RestController
@RequestMapping("/wx/storage")
@Validated
public class WxStorageController {
    private final Log logger = LogFactory.getLog(WxStorageController.class);

    @Autowired
    private StorageService storageService;
    @Autowired
    private WxStorageService wxStorageService;
    @Autowired
    private WxUserService userService;
    @Autowired
    private QCodeService qCodeService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private TencentCloudService tencentCloudService;

    @Value("${projectRedis.keyPrefix.share}")
    private String projectRedisKeyShare;

    private String generateKey(String originalFilename) {
        int index = originalFilename.lastIndexOf('.');
        String suffix = originalFilename.substring(index);

        String key = null;
        WxStorage storageInfo = null;

        do {
            key = CharUtil.getRandomString(20) + suffix;
            storageInfo = wxStorageService.findByKey(key);
        }
        while (storageInfo != null);

        return key;
    }



    @PostMapping("/upload")
    public Object upload(@RequestParam("file") MultipartFile file) throws IOException {
        String url = ImageUtil.storeSrcAndCompress(storageService, file, true);
        if (url == null) {
            return ResponseUtil.badArgumentValue();
        }

        Map<String, Object> data = new HashMap<>();
        data.put("url", url);
        return ResponseUtil.ok(data);
    }


    //通过身份证照片识别 身份证上的信息
    @PostMapping("/upload/idcard/discern")
    public Object upload(@LoginUser Integer userId,@RequestParam("file") MultipartFile file) throws IOException {
        if(userId == null || userId.intValue() == 0) {
            return ResponseUtil.unlogin();
        }

        String url = ImageUtil.storeSrcAndCompress(storageService, file, true);
        if (url == null) {
            return ResponseUtil.badArgumentValue();
        }

        return tencentCloudService.checkIdCardImg(url);
    }


    @PostMapping("/head/portrait/upload")
    public Object uploadHeadPortrait(@RequestParam("file") MultipartFile file,@LoginUser Integer userId) throws IOException {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }

        WxUser user = userService.findById(userId);
        Map<String, Object> data = new HashMap<>();
        if(null != file && !file.isEmpty() && null != user){
            String url = ImageUtil.storeSrcAndCompress(storageService, file, true);
            if (url == null) {
                return ResponseUtil.badArgumentValue();
            }

            //修改用户表
            user.setAvatar(url);
            userService.updateById(user);

            //返回
            data.put("avatar", url);
            return ResponseUtil.ok(data);
        }
        return ResponseUtil.fail(WxResponseCode.AUTH_HEAD_PORTRAILT_FAIL,"文件上传失败，原因：文件为空或用户不存在");
    }

    @GetMapping("/fetch/{path}/{key:.+}")
    public ResponseEntity<Resource> fetch(@PathVariable String path, @PathVariable String key) throws UnsupportedEncodingException {
        String filePathAndName = path + "/" + key;

        if (filePathAndName == null) {
            return ResponseEntity.notFound().build();
        }
        WxStorage storage = wxStorageService.findByKey(filePathAndName);
        if (storage == null) {
            return ResponseEntity.notFound().build();
        }

        String type = storage.getType();
        MediaType mediaType = MediaType.parseMediaType(type);

        Resource file = storageService.getLocalStorage().loadAsResource(filePathAndName);
        if (file == null) {
            return ResponseEntity.notFound().build();
        }

        HttpHeaders headers = new HttpHeaders();
        headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
        headers.add("Content-Disposition", String.format("attachment; filename=%s",  java.net.URLEncoder.encode(key, "UTF-8")));

        return ResponseEntity.ok().headers(headers).contentType(mediaType).body(file);
    }

    /**
     * 访问存储对象
     *
     * @param key 存储对象key
     * @return
     */
    @GetMapping("/fetch/{key:.+}")
    public ResponseEntity<Resource> fetch(@PathVariable String key) throws UnsupportedEncodingException {
        if (key == null) {
            return ResponseEntity.notFound().build();
        }
        if (key.contains("../")) {
            return ResponseEntity.badRequest().build();
        }
        WxStorage storage = wxStorageService.findByKey(key);
        if (storage == null) {
            return ResponseEntity.notFound().build();
        }

        String type = storage.getType();
        MediaType mediaType = MediaType.parseMediaType(type);

        if(type.equals("application/x-zip-compressed")){
            Resource file = storageService.loadAsResource(key);
            if(file == null) {
                ResponseEntity.notFound();
            }
            return ResponseEntity.ok().contentType(mediaType).header(HttpHeaders.CONTENT_DISPOSITION,
                    "attachment; filename=\"" + file.getFilename() + "\"").body(file);
        } else if (type.equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) {
            Resource file = storageService.loadAsResource(key);
            if(file == null) {
                ResponseEntity.notFound();
            }
            return ResponseEntity.ok().contentType(mediaType).header(HttpHeaders.CONTENT_DISPOSITION,
                    "attachment; filename=\"" + URLEncoder.encode(storage.getName(), "UTF-8") + "\"").body(file);
        }

        Resource file = storageService.getLocalStorage().loadAsResource(key);
        if (file == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok().contentType(mediaType).body(file);
    }


    /**
     * 访问存储对象
     *
     * @param key 存储对象key
     * @return
     */
    @GetMapping("/download/{key:.+}")
    public ResponseEntity<Resource> download(@PathVariable String key) {
        WxStorage storage = wxStorageService.findByKey(key);
        if (key == null) {
            return ResponseEntity.notFound().build();
        }
        if (key.contains("../")) {
            return ResponseEntity.badRequest().build();
        }

        String type = storage.getType();
        MediaType mediaType = MediaType.parseMediaType(type);

        Resource file = storageService.loadAsResource(key);
        if (file == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok().contentType(mediaType).header(HttpHeaders.CONTENT_DISPOSITION,
                "attachment; filename=\"" + file.getFilename() + "\"").body(file);
    }

}
