package com.gxwebsoft.common.system.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.security.JwtSubject;
import com.gxwebsoft.common.core.security.JwtUtil;
import com.gxwebsoft.common.core.utils.CommonUtil;
import com.gxwebsoft.common.core.utils.FileServerUtil;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.AccessKey;
import com.gxwebsoft.common.system.entity.FileRecord;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.result.LoginResult;
import com.gxwebsoft.common.system.service.*;
import com.gxwebsoft.oa.service.AppService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

import static com.gxwebsoft.common.core.constants.RedisConstants.ACCESS_TOKEN_KEY;

/**
 * 文件上传下载控制器
 *
 * @author WebSoft
 * @since 2018-12-24 16:10:24
 */
@Api(tags = "文件服务器-文件预览")
@RestController
@RequestMapping("/api/file-preview")
public class FilePreviewController extends BaseController {
    private final StringRedisTemplate redisTemplate;
    @Resource
    private SettingService settingService;
    @Resource
    private ConfigProperties configProperties;
    @Resource
    private ConfigProperties config;
    @Resource
    private FileRecordService fileRecordService;
    @Resource
    private AccessKeyService accessKeyService;
    @Resource
    private UserService userService;
    @Resource
    private AppService appService;
    @Resource
    private CompanyService companyService;

    public FilePreviewController(StringRedisTemplate redisTemplate) {
      this.redisTemplate = redisTemplate;
    }

  @ApiOperation("查看原文件")
    @GetMapping("/{dir}/{name:.+}")
    public void preview(@PathVariable("dir") String dir, @PathVariable("name") String name,
                        HttpServletResponse response, HttpServletRequest request) {
      File file = new File(getUploadDir(), dir + "/" + name);
      FileServerUtil.preview(file, getPdfOutDir(), config.getOpenOfficeHome(), response, request);
    }

    @ApiOperation("下载原文件")
    @GetMapping("/download/{dir}/{name:.+}")
    public void download(@PathVariable("dir") String dir, @PathVariable("name") String name,
                         HttpServletResponse response, HttpServletRequest request) {
      String path = dir + "/" + name;
      FileRecord record = fileRecordService.getByIdPath(path);
      File file = new File(getUploadDir(), path);
      String fileName = record == null ? file.getName() : record.getName();
      FileServerUtil.preview(file, true, fileName, null, null, response, request);
    }

    @ApiOperation("查看缩略图")
    @GetMapping("/thumbnail/{dir}/{name:.+}")
    public void thumbnail(@PathVariable("dir") String dir, @PathVariable("name") String name,
                          HttpServletResponse response, HttpServletRequest request) {
      File file = new File(getUploadDir(), dir + "/" + name);
      File thumbnail = new File(getUploadSmDir(), dir + "/" + name);
      FileServerUtil.previewThumbnail(file, thumbnail, config.getThumbnailSize(), response, request);
    }

    @ApiOperation("查看缩略图")
    @GetMapping("/thumb/{dir}/{name:.+}")
    public void thumb(@PathVariable("dir") String dir, @PathVariable("name") String name,
                      HttpServletResponse response, HttpServletRequest request) {
      File file = new File(getUploadDir(), dir + "/" + name);
      File thumbnail = new File(getUploadSmDir2(), dir + "/" + name);
      FileServerUtil.previewThumbnail(file, thumbnail, config.getThumbnailSize(), response, request);
    }

    @ApiOperation("免密登录")
    @GetMapping("/token/{userId}/{accessKey}")
    public ApiResult<LoginResult> getToken(@PathVariable("userId") Integer userId, @PathVariable("accessKey") String accessKey) {
      // 免密登录 传指定的userId和AccessKey，请给指定的userId分配好角色和权限
      if (accessKeyService.count(new LambdaQueryWrapper<AccessKey>().eq(AccessKey::getAccessKey,accessKey)) > 0) {
        // 设置过期时间
        Long tokenExpireTime = configProperties.getTokenExpireTime();
        // 查询用户信息
        final User byId = userService.getById(userId);
        // 登录账号|手机号码|邮箱登录
        User user = userService.getByUsername(byId.getUsername(), byId.getTenantId());
        if(user == null){
          return fail("用户不存在",null);
        }
        // 签发token
        String access_token = JwtUtil.buildToken(new JwtSubject(user.getUsername(), user.getTenantId()),
          tokenExpireTime, configProperties.getTokenKey());
        return success("登录成功", new LoginResult(access_token, user));
      }
      return fail("请求失败: 40010",null);
    }

    @ApiOperation("APP应用信息")
    @GetMapping("/app-info2/{appid}/{accessKey}")
    public ApiResult<?> appInfo(@PathVariable("appid") Integer appId, @PathVariable("accessKey") String accessKey) {
      // 免密登录
      if (accessKeyService.count(new LambdaQueryWrapper<AccessKey>().eq(AccessKey::getAccessKey,accessKey)) > 0) {
        return success("操作成功", appService.getById(appId));
      }
      return fail("请求失败: 40011");
    }

    @ApiOperation("获取企业信息")
    @GetMapping("/company-info2/{companyId}/{accessKey}")
    public ApiResult<?> companyInfo(@PathVariable("companyId") Integer companyId, @PathVariable("accessKey") String accessKey) {
      // 免密登录
      if (accessKeyService.count(new LambdaQueryWrapper<AccessKey>().eq(AccessKey::getAccessKey,accessKey)) > 0) {
        return success("操作成功", companyService.getById(companyId));
      }
      return fail("请求失败: 40012");
    }

  @ApiOperation("获取微信小程序码")
  @GetMapping("/getQRCode")
  public ApiResult<?> getQRCode() {
    String apiUrl = "https://api.weixin.qq.com/wxa/getwxacode?access_token=" + getAccessToken();
    final HashMap<String, Object> map = new HashMap<>();
    map.put("path","pages/flash/index?user_id="+getLoginUserId());
//    map.put("env_version","release");
    map.put("env_version","trial");
    System.out.println("获取微信小程序码 = " + map);
    // 获取图片 Buffer
    byte[] qrCode = HttpRequest.post(apiUrl)
      .body(JSON.toJSONString(map))
      .execute().bodyBytes();

    // 保存的文件名称
    final String fileName = CommonUtil.randomUUID8().concat(".png");
    // 保存路径
    String filePath = getUploadDir().concat("qrcode/") + fileName;
    File file = FileUtil.writeBytes(qrCode, filePath);
    if(file != null){
      return success("".concat("/qrcode/").concat(fileName));
    }
    return fail("获取失败",null);
  }

  /**
   * 获取接口调用凭据AccessToken
   * https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getAccessToken.html
   */
  private String getAccessToken() {
    String key = ACCESS_TOKEN_KEY.concat(":").concat(getTenantId().toString());
    // 获取微信小程序配置信息
    JSONObject setting = settingService.getBySettingKey("mp-weixin");
    // 从缓存获取access_token
    String value = redisTemplate.opsForValue().get(key);
    if (value != null) {
      // 解析access_token
      JSONObject response = JSON.parseObject(value);
      return response.getString("access_token");
    }
    // 微信获取凭证接口
    String apiUrl = "https://api.weixin.qq.com/cgi-bin/token";
    // 组装url参数
    String url = apiUrl.concat("?grant_type=client_credential").concat("&appid=").concat(setting.getString("appId")).concat("&secret=").concat(setting.getString("appSecret"));
    // 执行get请求
    String result = HttpUtil.get(url);
    // 解析access_token
    JSONObject response = JSON.parseObject(result);
    if (response.getString("access_token") != null) {
      // 存入缓存
      redisTemplate.opsForValue().set(key, result,7000L, TimeUnit.SECONDS);
      return response.getString("access_token");
    }
    return null;
  }

    /**
     * 文件上传基目录
     */
    private String getUploadBaseDir() {
      return config.getUploadPath() + "file/";
    }

    /**
     * office转pdf输出位置
     */
    private String getPdfOutDir() {
      return getUploadBaseDir() + "pdf/";
    }

    /**
     * 文件上传位置(服务器)
     */
    private String getUploadDir() {
      return config.getUploadPath() + "file/";
    }

    /**
     * 缩略图生成位置
     */
    private String getUploadSmDir() {
      return getUploadBaseDir() + "thumbnail/";
    }

    /**
     * 缩略图生成位置
     */
    private String getUploadSmDir2() {
      return getUploadBaseDir() + "thumb/";
    }


}
