/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

package com.yami.shop.sys.controller;

import jakarta.validation.Valid;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.sys.model.SysConfig;
import org.springframework.beans.factory.annotation.Autowired;
import com.yami.shop.common.response.ServerResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.common.util.PageParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.sys.service.SysConfigService;
import com.yami.shop.common.annotation.SysLog;
import cn.hutool.core.util.StrUtil;

/**
 * SysConfigController类，用于处理系统配置相关的HTTP请求，是一个基于Spring RESTful风格的控制器。
 * 它提供了对系统配置信息的增删改查等一系列操作接口，并且在各个方法上通过权限控制注解来保障操作的安全性。
 * @author lgh
 */
@RestController
@RequestMapping("/sys/config")
public class SysConfigController {

    /**
     * 通过Spring的依赖注入自动装配SysConfigService，用于调用业务逻辑层的相关方法来处理系统配置业务。
     */
    @Autowired
    private SysConfigService sysConfigService;

    /**
     * 获取系统配置列表的分页数据的方法。
     * 根据传入的参数键（paramKey）进行模糊查询，获取符合条件的系统配置信息列表，并以分页形式返回。
     * 此方法需要有'sys:config:page'权限才能访问。
     *
     * @param paramKey 用于模糊查询系统配置的参数键，可传入部分关键字来筛选配置信息，若为空字符串则查询所有配置，非空时会按照此键进行模糊匹配查询。
     * @param page 封装了分页相关信息（如页码、每页数量等）以及用于接收查询结果的SysConfig类型对象的PageParam对象，用于传递分页查询参数和接收查询结果。
     * @return 返回一个ServerResponseEntity<IPage<SysConfig>>类型的响应实体，其中包含了查询到的系统配置信息分页数据，若查询成功则响应状态码为成功，数据封装在实体中；若出现异常等情况则会返回相应的错误信息。
     */
    @GetMapping("/page")
    @PreAuthorize("@pms.hasPermission('sys:config:page')")
    public ServerResponseEntity<IPage<SysConfig>> page(String paramKey, PageParam<SysConfig> page) {
        // 使用LambdaQueryWrapper根据传入的参数键进行模糊查询，构建查询条件，若参数键不为空则按照参数键模糊匹配系统配置的paramKey字段
        IPage<SysConfig> sysConfigs = sysConfigService.page(page, new LambdaQueryWrapper<SysConfig>().like(StrUtil.isNotBlank(paramKey), SysConfig::getParamKey, paramKey));
        return ServerResponseEntity.success(sysConfigs);
    }

    /**
     * 根据配置的唯一标识符（id）获取单个系统配置信息的方法。
     * 此方法需要有'sys:config:info'权限才能访问。
     *
     * @param id 要查询的系统配置的唯一标识符，通过路径变量的方式传入，用于在数据库中精准查找对应的配置信息。
     * @return 返回一个ServerResponseEntity<SysConfig>类型的响应实体，若查询到对应的配置信息则将其封装在实体中返回，响应状态码为成功；若未找到则返回相应的表示未找到的信息（如null等情况，具体取决于业务逻辑层的实现），同样封装在响应实体中。
     */
    @GetMapping("/info/{id}")
    @PreAuthorize("@pms.hasPermission('sys:config:info')")
    public ServerResponseEntity<SysConfig> info(@PathVariable("id") Long id) {
        SysConfig config = sysConfigService.getById(id);
        return ServerResponseEntity.success(config);
    }

    /**
     * 保存新的系统配置信息的方法。
     * 在保存操作前会进行数据合法性校验（通过@Valid注解结合相关验证逻辑），保存成功后会记录相应的操作日志（通过@SysLog注解）。
     * 此方法需要有'sys:config:save'权限才能访问。
     *
     * @param config 要保存的SysConfig类型的系统配置信息对象，通过请求体的方式传入，包含了配置的各项详细信息，如参数键、参数值等内容。
     * @return 返回一个ServerResponseEntity<Void>类型的响应实体，若保存操作成功则响应状态码为成功，实体中无具体数据返回（表示操作成功执行，无额外返回数据）；若出现验证失败等异常情况则会返回相应的错误信息。
     */
    @SysLog("保存配置")
    @PostMapping
    @PreAuthorize("@pms.hasPermission('sys:config:save')")
    public ServerResponseEntity<Void> save(@RequestBody @Valid SysConfig config) {
        sysConfigService.save(config);
        return ServerResponseEntity.success();
    }

    /**
     * 修改已存在的系统配置信息的方法。
     * 同样会进行数据合法性校验（通过@Valid注解结合相关验证逻辑），修改成功后会记录相应的操作日志（通过@SysLog注解）。
     * 此方法需要有'sys:config:update'权限才能访问。
     *
     * @param config 要修改的SysConfig类型的系统配置信息对象，通过请求体的方式传入，包含了修改后的配置各项详细信息，如参数键、参数值等内容。
     * @return 返回一个ServerResponseEntity<Void>类型的响应实体，若修改操作成功则响应状态码为成功，实体中无具体数据返回（表示操作成功执行，无额外返回数据）；若出现验证失败等异常情况则会返回相应的错误信息。
     */
    @SysLog("修改配置")
    @PutMapping
    @PreAuthorize("@pms.hasPermission('sys:config:update')")
    public ServerResponseEntity<Void> update(@RequestBody @Valid SysConfig config) {
        sysConfigService.updateById(config);
        return ServerResponseEntity.success();
    }

    /**
     * 删除指定的系统配置信息的方法。
     * 可以批量删除配置信息，传入的是要删除的配置信息的唯一标识符数组（configIds），删除成功后会记录相应的操作日志（通过@SysLog注解）。
     * 此方法需要有'sys:config:delete'权限才能访问。
     *
     * @param configIds 要删除的系统配置信息的唯一标识符数组，通过请求体的方式传入，用于在数据库中精准定位要删除的配置记录。
     * @return 返回一个ServerResponseEntity<Void>类型的响应实体，若删除操作成功则响应状态码为成功，实体中无具体数据返回（表示操作成功执行，无额外返回数据）；若出现异常情况则会返回相应的错误信息。
     */
    @SysLog("删除配置")
    @DeleteMapping
    @PreAuthorize("@pms.hasPermission('sys:config:delete')")
    public ServerResponseEntity<Void> delete(@RequestBody Long[] configIds) {
        sysConfigService.deleteBatch(configIds);
        return ServerResponseEntity.success();
    }
}