package com.gxwebsoft.common.system.controller;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.core.utils.JSONUtil;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.web.*;
import com.gxwebsoft.common.system.entity.Setting;
import com.gxwebsoft.common.system.entity.Tenant;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.param.SettingParam;
import com.gxwebsoft.common.system.param.SettingUpdateParam;
import com.gxwebsoft.common.system.service.SettingService;
import com.gxwebsoft.common.system.service.TenantService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;

/**
 * 系统设置控制器
 *
 * @author WebSoft
 * @since 2022-11-19 13:54:27
 */
@Tag(name = "系统设置")
@RestController
@RequestMapping("/api/system/setting")
public class SettingController extends BaseController {
    @Resource
    private SettingService settingService;
    @Resource
    private TenantService tenantService;
    @Resource
    private RedisUtil redisUtil;

    @PreAuthorize("hasAuthority('sys:setting:save')")
    @OperationLog
    @Operation(summary = "分页查询系统设置")
    @GetMapping("/page")
    public ApiResult<PageResult<Setting>> page(SettingParam param) {
        PageParam<Setting, SettingParam> page = new PageParam<>(param);
        page.setDefaultOrder("create_time desc");
        return success(settingService.page(page, page.getWrapper()));
        // 使用关联查询
        //return success(settingService.pageRel(param));
    }

    @PreAuthorize("hasAuthority('sys:setting:save')")
    @OperationLog
    @Operation(summary = "查询全部系统设置")
    @GetMapping()
    public ApiResult<List<Setting>> list(SettingParam param) {
        PageParam<Setting, SettingParam> page = new PageParam<>(param);
        page.setDefaultOrder("create_time desc");
        return success(settingService.list(page.getOrderWrapper()));
        // 使用关联查询
        //return success(settingService.listRel(param));
    }

    @PreAuthorize("hasAuthority('sys:setting:save')")
    @OperationLog
    @Operation(summary = "根据id查询系统设置")
    @GetMapping("/{id}")
    public ApiResult<Setting> get(@PathVariable("id") Integer id) {
        return success(settingService.getById(id));
        // 使用关联查询
        //return success(settingService.getByIdRel(id));
    }

    @PreAuthorize("hasAuthority('sys:setting:save')")
    @OperationLog
    @Operation(summary = "添加系统设置")
    @PostMapping()
    public ApiResult<?> save(@RequestBody SettingUpdateParam settingParam) {
        final User loginUser = getLoginUser();
        if(loginUser == null){
            return fail("请先登录");
        }

        // 转换为Setting对象
        Setting setting = convertToSetting(settingParam);
        setting.setTenantId(loginUser.getTenantId());

        if (settingService.save(setting)) {
            return success("添加成功");
        }
        return fail("添加失败");
    }

    @PreAuthorize("hasAuthority('sys:setting:save')")
    @OperationLog
    @Operation(summary = "修改系统设置")
    @PutMapping()
    public ApiResult<?> update(@RequestBody SettingUpdateParam settingParam) {
      final User loginUser = getLoginUser();
      if(loginUser == null){
        return fail("请先登录");
      }

      // 转换为Setting对象
      Setting setting = convertToSetting(settingParam);
      setting.setTenantId(loginUser.getTenantId());
      if (settingService.updateById(setting)) {
          // 更新系统设置信息到缓存 key = ""
          String key = setting.getSettingKey().concat(":").concat(loginUser.getTenantId().toString());
          redisUtil.set(key, JSON.parseObject(setting.getContent()));
          // 更新租户信息
          if (setting.getSettingKey().equals("setting")) {
            final String content = setting.getContent();
            final JSONObject jsonObject = JSONObject.parseObject(content);
            final String siteName = jsonObject.getString("siteName");
            final String logo = jsonObject.getString("logo");
            final Tenant tenant = new Tenant();
            tenant.setTenantName(siteName);
            tenant.setTenantId(getTenantId());
            tenant.setLogo(logo);
            tenantService.updateById(tenant);
          }
          return success("修改成功");
        }
        return fail("修改失败");
    }

    @PreAuthorize("hasAuthority('sys:setting:remove')")
    @OperationLog
    @Operation(summary = "删除系统设置")
    @DeleteMapping("/{id}")
    public ApiResult<?> remove(@PathVariable("id") Integer id) {
        if (settingService.removeById(id)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }

    @PreAuthorize("hasAuthority('sys:setting:save')")
    @OperationLog
    @Operation(summary = "批量添加系统设置")
    @PostMapping("/batch")
    public ApiResult<?> saveBatch(@RequestBody List<Setting> list) {
        if (settingService.saveBatch(list)) {
            return success("添加成功");
        }
        return fail("添加失败");
    }

    @PreAuthorize("hasAuthority('sys:setting:update')")
    @OperationLog
    @Operation(summary = "批量修改系统设置")
    @PutMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody BatchParam<Setting> batchParam) {
        if (batchParam.update(settingService, "setting_id")) {
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @PreAuthorize("hasAuthority('sys:setting:remove')")
    @OperationLog
    @Operation(summary = "批量删除系统设置")
    @DeleteMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
        if (settingService.removeByIds(ids)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }

    @PreAuthorize("hasAuthority('sys:setting:data')")
    @OperationLog
    @Operation(summary = "查询租户设置信息")
    @GetMapping("/data")
    public ApiResult<?> data() {
      return success(settingService.getData("setting"));
    }

    @Operation(summary = "根据key查询系统设置")
    @GetMapping("/getByKey/{key}")
    public ApiResult<JSONObject> getByKey(@PathVariable("key") String key) {
      final User loginUser = getLoginUser();
      if(loginUser != null){
        return success(settingService.getBySettingKey(key));
      }
      return fail("请先登录", null);
    }

    @Operation(summary = "根据key更新系统设置")
    @OperationLog
    @PutMapping("/updateByKey")
    public ApiResult<?> updateByKey(@RequestBody SettingUpdateParam settingParam) {
      final User loginUser = getLoginUser();
      if(loginUser == null){
        return fail("请先登录");
      }
      // getIsSuperAdmin() is a Boolean and may be null; avoid NPE from auto-unboxing.
      if(!"superAdmin".equals(loginUser.getUsername())){
        return fail("权限不足！");
      }

      // 转换为Setting对象
      Setting setting = convertToSetting(settingParam);
      setting.setTenantId(loginUser.getTenantId());

      return success(settingService.updateByKey(setting));
    }

    @PreAuthorize("hasAuthority('sys:setting:save')")
    @OperationLog
    @Operation(summary = "更新主题皮肤")
    @PutMapping("/theme")
    public ApiResult<?> theme(@RequestBody SettingUpdateParam settingParam) {
      // 转换为Setting对象
      Setting setting = convertToSetting(settingParam);
      setting.setTenantId(getTenantId());
      String key = "theme:".concat(getTenantId().toString());
      // 新增
      final Setting one = settingService.getOne(new LambdaQueryWrapper<Setting>().eq(Setting::getSettingKey, setting.getSettingKey()));
      if(one == null){
        settingService.save(setting);
        redisUtil.set(key,setting.getContent());
        return success("保存成功");
      }
      // 更新
      final Setting update = settingService.getOne(new LambdaQueryWrapper<Setting>().eq(Setting::getSettingKey, setting.getSettingKey()));
      update.setContent(setting.getContent());
      if (settingService.updateById(update)) {
        redisUtil.set(key,setting.getContent());
        return success("更新成功");
      }
      return fail("更新失败");
    }

    @Operation(summary = "更新主题皮肤")
    @GetMapping("/getTheme")
    public ApiResult<?> getTheme() {
      String key = "theme:".concat(getTenantId().toString());
      return success("获取成功",redisUtil.get(key));
    }

    /**
     * 将SettingUpdateParam转换为Setting对象
     * 根据settingKey的不同，将相应的字段组装成JSON格式的content
     */
    private Setting convertToSetting(SettingUpdateParam param) {
      Setting setting = new Setting();
      setting.setSettingKey(param.getSettingKey());
      setting.setSortNumber(param.getSortNumber());
      setting.setComments(param.getComments());
      setting.setTenantId(param.getTenantId());

      // 如果直接提供了content，则使用content
      if (StrUtil.isNotBlank(param.getContent())) {
        setting.setContent(param.getContent());
        return setting;
      }

      // 根据settingKey构建相应的JSON content
      JSONObject contentJson = new JSONObject();

      switch (param.getSettingKey()) {
        case "mp-weixin":
          // 微信小程序配置
          if (StrUtil.isNotBlank(param.getAppId())) {
            contentJson.put("appId", param.getAppId());
          }
          if (StrUtil.isNotBlank(param.getAppSecret())) {
            contentJson.put("appSecret", param.getAppSecret());
          }
          break;

        case "payment":
          // 支付配置
          if (StrUtil.isNotBlank(param.getMchId())) {
            contentJson.put("mchId", param.getMchId());
          }
          if (StrUtil.isNotBlank(param.getApiKey())) {
            contentJson.put("apiKey", param.getApiKey());
          }
          if (StrUtil.isNotBlank(param.getWechatApiKey())) {
            contentJson.put("wechatApiKey", param.getWechatApiKey());
          }
          if (StrUtil.isNotBlank(param.getMerchantSerialNumber())) {
            contentJson.put("merchantSerialNumber", param.getMerchantSerialNumber());
          }
          if (StrUtil.isNotBlank(param.getApiclientCert())) {
            contentJson.put("apiclientCert", param.getApiclientCert());
          }
          if (StrUtil.isNotBlank(param.getApiclientKey())) {
            contentJson.put("apiclientKey", param.getApiclientKey());
          }
          break;

        case "sms":
          // 短信配置
          if (StrUtil.isNotBlank(param.getAccessKeyId())) {
            contentJson.put("accessKeyId", param.getAccessKeyId());
          }
          if (StrUtil.isNotBlank(param.getAccessKeySecret())) {
            contentJson.put("accessKeySecret", param.getAccessKeySecret());
          }
          if (StrUtil.isNotBlank(param.getSignName())) {
            contentJson.put("signName", param.getSignName());
          }
          if (StrUtil.isNotBlank(param.getTemplateCode())) {
            contentJson.put("templateCode", param.getTemplateCode());
          }
          break;

        case "wx-work":
          // 企业微信配置
          if (StrUtil.isNotBlank(param.getCorpId())) {
            contentJson.put("corpId", param.getCorpId());
          }
          if (StrUtil.isNotBlank(param.getSecret())) {
            contentJson.put("secret", param.getSecret());
          }
          break;

        case "wx-official":
          // 微信公众号配置
          if (StrUtil.isNotBlank(param.getAppId())) {
            contentJson.put("appId", param.getAppId());
          }
          if (StrUtil.isNotBlank(param.getAppSecret())) {
            contentJson.put("appSecret", param.getAppSecret());
          }
          if (StrUtil.isNotBlank(param.getToken())) {
            contentJson.put("token", param.getToken());
          }
          if (StrUtil.isNotBlank(param.getEncodingAESKey())) {
            contentJson.put("encodingAESKey", param.getEncodingAESKey());
          }
          break;

        case "setting":
          // 基本设置
          if (StrUtil.isNotBlank(param.getSiteName())) {
            contentJson.put("siteName", param.getSiteName());
          }
          if (StrUtil.isNotBlank(param.getLogo())) {
            contentJson.put("logo", param.getLogo());
          }
          if (StrUtil.isNotBlank(param.getDescription())) {
            contentJson.put("description", param.getDescription());
          }
          if (StrUtil.isNotBlank(param.getKeywords())) {
            contentJson.put("keywords", param.getKeywords());
          }
          break;

        case "upload":
          // 上传配置
          if (StrUtil.isNotBlank(param.getBucketName())) {
            contentJson.put("bucketName", param.getBucketName());
          }
          if (StrUtil.isNotBlank(param.getBucketDomain())) {
            contentJson.put("bucketDomain", param.getBucketDomain());
          }
          if (StrUtil.isNotBlank(param.getBucketEndpoint())) {
            contentJson.put("bucketEndpoint", param.getBucketEndpoint());
          }
          if (StrUtil.isNotBlank(param.getAccessKeyId())) {
            contentJson.put("accessKeyId", param.getAccessKeyId());
          }
          if (StrUtil.isNotBlank(param.getAccessKeySecret())) {
            contentJson.put("accessKeySecret", param.getAccessKeySecret());
          }
          break;

        case "printer":
          // 打印机配置
          if (StrUtil.isNotBlank(param.getDeviceNo())) {
            contentJson.put("deviceNo", param.getDeviceNo());
          }
          if (StrUtil.isNotBlank(param.getPrinterKey())) {
            contentJson.put("printerKey", param.getPrinterKey());
          }
          break;

        default:
          // 处理其他配置或动态字段
          if (param.getAdditionalProperties() != null) {
            contentJson.putAll(param.getAdditionalProperties());
          }
          break;
      }

      setting.setContent(contentJson.toJSONString());
      return setting;
    }
}
