package cn.iocoder.yudao.module.system.service.config;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.system.controller.admin.config.vo.CommonConfigPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.config.vo.CommonConfigSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.config.vo.CommonConfigVO;
import cn.iocoder.yudao.module.system.controller.admin.log.vo.UserOperationLogSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.config.CommonConfigDO;
import cn.iocoder.yudao.module.system.dal.mysql.config.CommonConfigMapper;
import cn.iocoder.yudao.module.system.enums.common.ZeroOneEnum;
import cn.iocoder.yudao.module.system.enums.config.CommandConfigTypeEnum;
import cn.iocoder.yudao.module.system.service.log.UserOperationLogService;
import cn.iocoder.yudao.module.system.service.tool.ToolsService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.lang.reflect.Type;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.CONFIG_NOT_EXISTS;

/**
 * 通用配置 Service 实现类
 *
 * @author 陈宾顺
 */
@Service
@Validated
public class CommonConfigServiceImpl implements CommonConfigService {

    @Resource
    private CommonConfigMapper configMapper;

    @Resource
    @Lazy
    private ToolsService toolsService;

    @Resource
    private UserOperationLogService userOperationLogService;

    @Override
    public Long createConfig(CommonConfigSaveReqVO createReqVO) {
        // 插入
        CommonConfigDO config = BeanUtils.toBean(createReqVO, CommonConfigDO.class);

        if (CommandConfigTypeEnum.CHARG_CONFIG.getType().equals(config.getConfigType())) {
            CommonConfigVO chargeConfig = JSONUtil.toBean(config.getConfigStr(), CommonConfigVO.class);
            //一次
            if (ZeroOneEnum.ZERO.getType().equals(chargeConfig.getEveryDay())
                    && ObjectUtil.isNotEmpty(chargeConfig.getScheduleChargeStartTime())) {
                setOnceStartTimeConfig(config, chargeConfig);
            }
        }

        configMapper.insert(config);
        toolsService.sendPPsortConfig();

        UserOperationLogSaveReqVO operationLog = UserOperationLogSaveReqVO.builder()
                .operateAction("添加参数设置")
                .nickName(SecurityFrameworkUtils.getLoginUserNickname()).build();
        userOperationLogService.createUserOperationLog(operationLog);
        // 返回
        return config.getId();
    }

    /**
     * 设置一次的开始时间和结束时间
     *
     * @param config
     * @param chargeConfig
     */
    private void setOnceStartTimeConfig(CommonConfigDO config, CommonConfigVO chargeConfig) {

        LocalDateTime now = LocalDateTime.now();
        LocalDateTime nowEnd = LocalDateTime.now();

        if (now.isAfter(chargeConfig.getScheduleChargeEndTime())) {
            now = now.plusDays(1);
            nowEnd = nowEnd.plusDays(1);
        }

        LocalDateTime s = LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth(),
                chargeConfig.getScheduleChargeStartTime().getHour(),
                chargeConfig.getScheduleChargeStartTime().getMinute(), 00);

        LocalDateTime e = LocalDateTime.of(nowEnd.getYear(), nowEnd.getMonth(), nowEnd.getDayOfMonth(),
                chargeConfig.getScheduleChargeEndTime().getHour(),
                chargeConfig.getScheduleChargeEndTime().getMinute(), 00);

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String onceStartTime = s.format(formatter);
        String onceEndTime = e.format(formatter);

        Gson gson = new Gson();
        Type type = new TypeToken<Map<String, String>>(){}.getType();
        Map<String, String> map = gson.fromJson(config.getConfigStr(), type);
        map.put("onceStartTime", onceStartTime);
        map.put("onceEndTime", onceEndTime);

        String str = JSON.toJSONString(map);

        config.setConfigStr(str);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateConfig(CommonConfigSaveReqVO updateReqVO) {
        // 校验存在
        validateConfigExists(updateReqVO.getId());
        // 更新
        CommonConfigDO updateObj = BeanUtils.toBean(updateReqVO, CommonConfigDO.class);

        CommonConfigVO chargeConfig = JSONUtil.toBean(updateReqVO.getConfigStr(), CommonConfigVO.class);
        if (CommandConfigTypeEnum.CHARG_CONFIG.getType().equals(updateReqVO.getConfigType())) {
            //一次
            if (ZeroOneEnum.ZERO.getType().equals(chargeConfig.getEveryDay())
                    && ObjectUtil.isNotEmpty(chargeConfig.getScheduleChargeStartTime())) {
                setOnceStartTimeConfig(updateObj, chargeConfig);
            } else if (ZeroOneEnum.ONE.getType().equals(chargeConfig.getEveryDay())) {
                JSONObject jsonObject = new JSONObject(updateObj.getConfigStr());
                jsonObject.put("onceStartTime", "");
                jsonObject.put("onceEndTime", "");
                String str = JSON.toJSONString(jsonObject);
                updateObj.setConfigStr(str);
            }
        }

        configMapper.updateById(updateObj);

        toolsService.sendPPsortConfig();

        UserOperationLogSaveReqVO operationLog = UserOperationLogSaveReqVO.builder()
                .operateAction("修改参数设置")
                .nickName(SecurityFrameworkUtils.getLoginUserNickname()).build();
        userOperationLogService.createUserOperationLog(operationLog);
    }

    @Override
    public void deleteConfig(Long id) {
        // 校验存在
        validateConfigExists(id);
        // 删除
        configMapper.deleteById(id);
    }

    private void validateConfigExists(Long id) {
        if (configMapper.selectById(id) == null) {
            throw exception(CONFIG_NOT_EXISTS);
        }
    }

    @Override
    public CommonConfigDO getConfig(Long configType) {
        CommonConfigDO commonConfigDO = configMapper.selectOne(new LambdaQueryWrapper<CommonConfigDO>()
                .eq(CommonConfigDO::getConfigType, configType));
        return commonConfigDO;
    }

    @Override
    public PageResult<CommonConfigDO> getConfigPage(CommonConfigPageReqVO pageReqVO) {
        return configMapper.selectPage(pageReqVO);
    }

}
