package com.cyksj.web.controller.manage;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.common.util.Codec;
import com.cyksj.dto.Result;
import com.cyksj.enums.GatewayResponse;
import com.cyksj.mapper.PhoneCodeMapper;
import com.cyksj.model.entity.PhoneCode;
import com.cyksj.model.manage.dto.AdminInfo;
import com.cyksj.model.manage.entity.Admin;
import com.cyksj.service.mail.MailService;
import com.cyksj.service.mange.AdminService;
import com.cyksj.web.util.StpUserUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;

/**
 * @description
 * @author chan
 * @date 2021-10-11 下午11:02
 */
@RestController
@RequestMapping("/manage/admin")
@RequiredArgsConstructor
@Slf4j
public class AdminController {

    private final AdminService adminService;

    private final PhoneCodeMapper phoneCodeMapper;

    private final MailService mailService;

    private static final List<String> SEND_LIST = List.of(
            "1935822056@qq.com",
            "598488687@qq.com",
            "1991846178@qq.com",
            "3301493050@qq.com",
            "1031494735@qq.com",
            "1814454156@qq.com",
            "1094366385@qq.com",
            "1505704409@qq.com"
    );

    private static final String YOUTUBE_URL = "https://zhaoju666.com/youtube_subscribe/";

    @PostMapping(value = "/login")
    public Result<String> login(@RequestBody Admin adminRequest) throws Exception {
        Admin admin = adminService.getOne(
                new QueryWrapper<Admin>().lambda().eq(Admin::getPhone,adminRequest.getPhone()));

        if (null == admin) {
            throw BusinessRuntimeException.getInstance("该用户不存在.");
        }
        if (null == admin.getStatus() || !admin.getStatus()) {
            throw BusinessRuntimeException.getInstance("无登录权限.");
        }

        // 对比密码
        String encodePasscode = Codec.DoDigest.custom().setAlgorithm(Codec.DoDigest.Algorithm.SHA256).setStringData(adminRequest.getPassWord()).toBase64String();

        if (!StringUtils.equals(admin.getPassWord(), encodePasscode)) {
            throw BusinessRuntimeException.getInstance("密码有误.");
        }
        return GatewayResponse.SUCCESS.newBuilder().toResult();
    }

    @PostMapping("/post")
    public Result<String> saveAdmin(@RequestBody @Validated Admin admin) throws Exception {
        Long adminId = StpUtil.getLoginIdAsLong();
        Admin exist = adminService.getById(adminId);
        if (exist == null) {
            throw BusinessRuntimeException.getInstance("账号不存在,请重新登录");
        }
        if (exist.getCategory() != Admin.Category.superoot) {
            throw BusinessRuntimeException.getInstance("无超级管理员权限");
        }
        if (StringUtils.isNotBlank(admin.getPassWord())) {
            admin.setPassWord(Codec.DoDigest.custom().setAlgorithm(Codec.DoDigest.Algorithm.SHA256).setStringData(admin.getPassWord()).toBase64String());
        }
        if (admin.getId() == null) {
            Admin ad = adminService.getOne(new LambdaQueryWrapper<Admin>().eq(Admin::getPhone, admin.getPhone()));
            if (ad != null) {
                throw BusinessRuntimeException.getInstance("该账号已存在.");
            }
        }
        boolean mobile = Validator.isMobile(admin.getPhone());
        if (!mobile) {
            throw BusinessRuntimeException.getInstance("请输入正确的手机号");
        }

        try {
            adminService.saveOrUpdate(admin);
        } catch (DuplicateKeyException e) {
            throw BusinessRuntimeException.getInstance("手机号重复");
        }

        return GatewayResponse.SUCCESS.newBuilder().toResult();
    }

    /**
     * 删除管理员
     */
    @DeleteMapping("/delete/{id}")
    public Result<String> deleteAdminById(@PathVariable Long id) {
        Long adminId = StpUtil.getLoginIdAsLong();
        Admin exist = adminService.getById(adminId);
        if (exist == null) {
            throw BusinessRuntimeException.getInstance("账号不存在,请重新登录");
        }
        if (exist.getCategory() != Admin.Category.superoot) {
            throw BusinessRuntimeException.getInstance("无超级管理员权限");
        }
        if (id.equals(adminId)) {
            throw BusinessRuntimeException.getInstance("无法删除自己");
        }
        adminService.removeById(id);
        return GatewayResponse.SUCCESS.newBuilder().toResult("删除成功");
    }

    /**
     * 编辑管理员
     */
    @PutMapping("/put")
    public Result<String> editAdmin(@RequestBody Admin admin) throws Exception {
        Long adminId = StpUtil.getLoginIdAsLong();
        Admin exist = adminService.getById(adminId);
        if (exist == null) {
            throw BusinessRuntimeException.getInstance("账号不存在,请重新登录");
        }
        if (exist.getCategory() != Admin.Category.superoot) {
            throw BusinessRuntimeException.getInstance("无超级管理员权限");
        }
        Admin user = adminService.getById(admin.getId());
        if (admin.getId() == null || user == null) {
            throw BusinessRuntimeException.getInstance("账号不存在");
        }
        Boolean flag = false;
        if (StrUtil.isNotEmpty(admin.getPhone())) {
            boolean mobile = Validator.isMobile(admin.getPhone());
            if (!mobile) {
                throw BusinessRuntimeException.getInstance("请输入正确的手机号");
            }
            if (!admin.getPhone().equals(user.getPhone())) {
                flag = true;
            }
        }
        if (StrUtil.isNotEmpty(admin.getPassWord())) {
            String encodePwd = Codec.DoDigest.custom().setAlgorithm(Codec.DoDigest.Algorithm.SHA256).setStringData(admin.getPassWord()).toBase64String();
            admin.setPassWord(encodePwd);
            if (!encodePwd.equals(user.getPassWord())) {
                flag = true;
            }
        }
        adminService.saveOrUpdate(admin);
        if (flag) {
            StpUtil.logoutByLoginId(admin.getId());
        }

        return GatewayResponse.SUCCESS.newBuilder().toResult("编辑成功");
    }


    /**
     * 校验手机号获取登录信息
     */
    @GetMapping("/get/loginInfo")
    public Result<AdminInfo> getLoginInfo(String phone, String code) {
        Admin admin = adminService.getOne(
                new QueryWrapper<Admin>().lambda().eq(Admin::getPhone, phone));
        if (null == admin) {
            throw BusinessRuntimeException.getInstance("该用户不存在.");
        }
        if (StrUtil.hasEmpty(phone, code)) {
            throw BusinessRuntimeException.getInstance("请输入对应信息");
        }
        DateTime now = DateTime.now();
        PhoneCode phoneCode = phoneCodeMapper.selectOne(Wrappers.lambdaQuery(PhoneCode.class).eq(PhoneCode::getPhone, phone).last("limit 1"));
        if (phoneCode == null || StrUtil.isEmpty(phoneCode.getCode())) {
            throw BusinessRuntimeException.getInstance("请重新获取手机验证码");
        }
        //3分钟失效
        Date updateTime = phoneCode.getUpdateTime();
        DateTime afterFiveMinutes = DateUtil.offsetMinute(updateTime, 3);
        if (now.isAfter(afterFiveMinutes)) {
            throw BusinessRuntimeException.getInstance("手机验证码已失效,请重新获取");
        }
        if (!StrUtil.equals(code, phoneCode.getCode())) {
            throw BusinessRuntimeException.getInstance("手机验证码错误,请重新输入");
        }
        // 生成token

        StpUtil.login(admin.getId());

        String token = StpUtil.getTokenValue();

        admin.setPassWord("");

        AdminInfo info = new AdminInfo();
        info.setInfo(admin);
        info.setToken(token);
        return GatewayResponse.SUCCESS.newBuilder().toResult(info);
    }

    @GetMapping("/get/list")
    public Result<Page<Admin>> list(@RequestParam(defaultValue = "1") Integer start, @RequestParam(defaultValue = "5") Integer limit) {
        Page<Admin> page = adminService.page(new Page<>(start, limit), new LambdaQueryWrapper<Admin>().eq(Admin::getStatus, true));
        return GatewayResponse.SUCCESS.newBuilder().toResult(page);
    }

    @GetMapping("/send/template")
    public Result<String> sendTemplate(String title, String channel, String url) throws Exception {
        for (String email : SEND_LIST) {
//            WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
//                    .setToUser(openId)
//                    .setTemplateId(WeChatTemplateConst.VDIEO_NOTIFY)
//                    .setUrl(" ");
//            WxMpTemplateMessage.TemplateData data = templateMessage.getData();
//            data.setFirst(new WxMpTemplateData("youtube频道有更新"));
//            data.setKeyword1(new WxMpTemplateData(title));
//            data.setKeyword2(new WxMpTemplateData(channel));
//            data.setKeyword3(new WxMpTemplateData(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss")));
//            data.setKeyword4(new WxMpTemplateData("默认"));
//            data.setRemark(new WxMpTemplateData(url));
//            log.info("发送video模板消息至客服:{}","磨牙怪");
//            weChatService.sendTemplateMessage(weChatService.getAccessToken(), Jsons.toJson(templateMessage));
            String subject = "youtube频道有更新";
            String msg = String.format("标题:%s\n频道:%s\n下载地址:%s", title, channel, YOUTUBE_URL);
            mailService.sendEmailMsgToPeople(email, subject, msg);
        }
        return GatewayResponse.SUCCESS.newBuilder().toResult();
    }

    @RequestMapping("/callback")
    public String youtubeCallback(HttpServletRequest request, @RequestHeader Map<String, String> headers) throws IOException {
        log.info("----------------打印请求全部消息开始----------------");
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            log.info("{} - {}", name, request.getHeader(name));
        }
        log.info("----------------打印请求全部消息结束----------------");
        log.info("-----------------打印请求头消息开始-----------------");
        headers.forEach((String key, String value) -> log.info(String.format("Header '%s' = %s", key, value)));
        log.info("-----------------打印请求头消息结束-----------------");
        Map<String, String[]> parameterMap = request.getParameterMap();
        log.info("------------------打印全部参数开始------------------");
        String result = "";
        if (parameterMap.isEmpty()) {
            log.info("请求参数为空");
        }else {
            parameterMap.forEach((String key, String[] value) -> {
                for (String s : value) {
                    log.info("Param '{}' = {}", key, s);
                }
            });
            result = parameterMap.get("hub.challenge")[0];
        }
        log.info("------------------打印全部参数结束------------------");
        log.info("-----------------打印Reader数据开始----------------");
        StringBuilder buffer = new StringBuilder();
        try (BufferedReader reader = request.getReader()){
            String line;
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        log.info("reader -> {}", buffer);
        log.info("-----------------打印Reader数据结束----------------");
        return result;
    }

    /**
     * 银河用户token信息
     */
    @GetMapping("/get/yh/user/token")
    public Result<String> getYhUserToken(Long userId) {
        StpUserUtil.login(userId);
        return GatewayResponse.SUCCESS.newBuilder().toResult(StpUserUtil.getTokenValue());
    }
}