package com.qmth.themis.admin.api;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.reflect.TypeToken;
import com.qmth.themis.business.constant.SystemConstant;
import com.qmth.themis.business.dto.response.SysConfigBean;
import com.qmth.themis.business.entity.SysConfig;
import com.qmth.themis.business.enums.UploadFileEnum;
import com.qmth.themis.business.service.SysConfigService;
import com.qmth.themis.business.service.ThemisCacheService;
import com.qmth.themis.business.util.OssUtil;
import com.qmth.themis.common.exception.BusinessException;
import com.qmth.themis.common.util.GsonUtil;
import com.qmth.themis.common.util.Result;
import com.qmth.themis.common.util.ResultUtil;
import io.swagger.annotations.*;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import java.io.File;
import java.io.FileOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @Description: 系统参数 前端控制器
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2020/6/25
 */
@Api(tags = "系统参数Controller")
@RestController
@RequestMapping(SystemConstant.PREFIX_URL_ADMIN + "/sys/config")
@Validated
public class SysConfigController {
    private final static Logger log = LoggerFactory.getLogger(SysConfigController.class);

    @Resource
    SysConfigService sysConfigService;

    @Resource
    ThemisCacheService themisCacheService;

    @Resource
    OssUtil ossUtil;

    @ApiOperation(value = "系统参数查询接口")
    @RequestMapping(value = "/select", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "系统参数信息", response = SysConfigBean.class)})
    public Result select(@ApiParam(value = "分页页码", required = true) @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) int pageNumber,
                         @ApiParam(value = "分页数", required = true) @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) int pageSize) {
        return ResultUtil.ok(sysConfigService.select(new Page<>(pageNumber, pageSize)));
    }

    @ApiOperation(value = "系统参数新增/编辑接口")
    @RequestMapping(value = "/save", method = RequestMethod.POST)
    @Transactional
    @ApiResponses({@ApiResponse(code = 200, message = "常规信息", response = Result.class)})
    public Result save(@Validated @ApiParam(value = "机构信息", required = true) @RequestBody SysConfigBean sysConfigBean, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultUtil.error(bindingResult.getAllErrors().get(0).getDefaultMessage());
        }
        SysConfig sysConfig = GsonUtil.fromJson(GsonUtil.toJson(sysConfigBean), SysConfig.class);
        sysConfig.setEditor(1);
        sysConfig.setEnable(true);
        sysConfigService.saveOrUpdate(sysConfig);
        updateSysconfig(sysConfig);
        return ResultUtil.ok(true);
    }

    @ApiOperation(value = "系统参数启用/禁用接口")
    @RequestMapping(value = "/enable", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "常规信息", response = Result.class)})
    @Transactional
    public Result enable(@ApiParam(value = "系统参数id", required = true) @RequestParam Long id,
                         @ApiParam(value = "启用/禁用", required = true) @RequestParam Boolean enable) {
        SysConfig sysConfig = sysConfigService.getById(id);
        Optional.ofNullable(sysConfig).orElseThrow(() -> new BusinessException("系统参数信息为空"));

        sysConfig.setEnable(enable);
        sysConfigService.saveOrUpdate(sysConfig);
        updateSysconfig(sysConfig);
        return ResultUtil.ok(true);
    }

    /**
     * 刷新系统参数并写入json文件
     */
    public void updateSysconfig(SysConfig sysConfig) {
        File file = null;
        try {
            themisCacheService.updateSysConfigCache(sysConfig.getConfigKey());
            file = SystemConstant.getFileTempVar(SystemConstant.JSON_PREFIX);
            JSONObject jsonObject = JSONObject
                    .parseObject(new String(ossUtil.download(true, UploadFileEnum.client.name() + "/" + SystemConstant.EXAM_CONFIG_FILE_NAME), StandardCharsets.UTF_8));
            List<SysConfigBean> sysConfigBeanList = null;
            if (Objects.isNull(jsonObject) || jsonObject.size() == 0) {
                jsonObject = new JSONObject();
                sysConfigBeanList = new ArrayList<>();
            } else {
                sysConfigBeanList = (List<SysConfigBean>) jsonObject.get(SystemConstant.SYS_CONFIG_LIST);
                sysConfigBeanList = CollectionUtils.isEmpty(sysConfigBeanList) ? new ArrayList<>() : sysConfigBeanList;
                sysConfigBeanList = GsonUtil.fromJson(GsonUtil.toJson(sysConfigBeanList), new TypeToken<List<SysConfigBean>>() {
                }.getType());
            }
            SysConfigBean sysConfigBean = GsonUtil.fromJson(GsonUtil.toJson(sysConfig), SysConfigBean.class);
            sysConfigBeanList.removeIf(e -> Objects.equals(e.getConfigKey(), sysConfigBean.getConfigKey()));
            if (Objects.nonNull(sysConfigBean.getEnable()) && sysConfigBean.getEnable()) {
                sysConfigBeanList.add(sysConfigBean);
            }
            jsonObject.put(SystemConstant.SYS_CONFIG_LIST, sysConfigBeanList);

            IOUtils.write(jsonObject.toJSONString().getBytes(StandardCharsets.UTF_8), new FileOutputStream(file));
            ossUtil.upload(true, UploadFileEnum.client.name() + "/" + SystemConstant.EXAM_CONFIG_FILE_NAME, file);
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            if (e instanceof BusinessException) {
                throw new BusinessException(e.getMessage());
            } else {
                throw new RuntimeException(e);
            }
        } finally {
            if (Objects.nonNull(file)) {
                file.delete();
            }
        }
    }
}