package com.greenorange.promotion.controller.user;

import com.auth0.jwt.interfaces.DecodedJWT;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.greenorange.promotion.annotation.RequiresPermission;
import com.greenorange.promotion.common.BaseResponse;
import com.greenorange.promotion.common.ErrorCode;
import com.greenorange.promotion.common.ResultUtils;
import com.greenorange.promotion.constant.UserConstant;
import com.greenorange.promotion.exception.BusinessException;
import com.greenorange.promotion.exception.ThrowUtils;
import com.greenorange.promotion.model.dto.CommonBatchRequest;
import com.greenorange.promotion.model.dto.CommonRequest;
import com.greenorange.promotion.model.dto.user.UserInfoAddRequest;
import com.greenorange.promotion.model.dto.user.UserInfoLoginRequest;
import com.greenorange.promotion.model.dto.user.UserInfoQueryRequest;
import com.greenorange.promotion.model.dto.user.UserInfoUpdateRequest;
import com.greenorange.promotion.model.entity.UserInfo;
import com.greenorange.promotion.model.vo.user.UserInfoVO;
import com.greenorange.promotion.service.common.CommonService;
import com.greenorange.promotion.service.user.UserInfoService;
import com.greenorange.promotion.utils.JWTUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 用户表 控制器
 */
@RestController
@RequestMapping("userInfo")
@Slf4j
@Tag(name = "用户表管理")
public class UserInfoController {


    @Resource
    private UserInfoService userInfoService;


    @Resource
    private CommonService commonService;


    @Resource
    private RedisTemplate<String, String> redisTemplate;


    @Resource
    private JWTUtils jwtUtils;




    /**
     * web端管理员登录
     * @param userInfoLoginRequest 用户登录请求体
     * @return 是否登录成功
     */
    @PostMapping("login")
    @Operation(summary = "web端管理员登录", description = "参数：用户登录请求体，权限：管理员（boss, admin)，方法名：userInfoLogin")
    public BaseResponse<String> userInfoLogin(@RequestBody UserInfoLoginRequest userInfoLoginRequest, HttpServletRequest request) {
        String userAccount = userInfoLoginRequest.getUserAccount();
        String userPassword = userInfoLoginRequest.getUserPassword();
        ThrowUtils.throwIf(StringUtils.isAnyBlank(userAccount, userPassword), ErrorCode.PARAMS_ERROR);
        String token = userInfoService.userInfoLogin(userAccount, userPassword, request);
        return ResultUtils.success(token);
    }



    /**
     * web端管理员退出登录(用户退出时将 token 加入 Redis 黑名单)
     * @return 是否退出登录成功
     */
    @PostMapping("logout")
    @Operation(summary = "web端管理员退出登录", description = "参数：JWT，权限：管理员（boss, admin)，方法名：userInfoLogout")
    @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Boolean> userInfoLogout(@RequestHeader("Authorization") String token) {
        // 获取 token 的过期时间
        DecodedJWT decodedJWT = jwtUtils.verify(token);
        long expirationTime = decodedJWT.getExpiresAt().getTime() - System.currentTimeMillis();

        // 将 token 存入 Redis 黑名单，并设置过期时间与 token 一致
        redisTemplate.opsForValue().set(token, token, expirationTime, TimeUnit.MILLISECONDS);
        return ResultUtils.success(true);
    }




    /**
     * web端管理员添加用户表
     * @param userInfoAddRequest 用户表添加请求体
     * @return 是否添加成功
     */
    @PostMapping("add")
    @Operation(summary = "web端管理员添加用户表", description = "参数：用户表添加请求体，权限：管理员（boss, admin)，方法名：addUserInfo")
    public BaseResponse<Boolean> addUserInfo(@Valid @RequestBody UserInfoAddRequest userInfoAddRequest) {
        UserInfo userInfo = commonService.copyProperties(userInfoAddRequest, UserInfo.class);
        userInfoService.save(userInfo);
        return ResultUtils.success(true);
    }



    /**
     * web端管理员更新用户表
     * @param userInfoUpdateRequest 用户表更新请求体
     * @return 是否更新成功
     */
    @PostMapping("update")
    @Operation(summary = "web端管理员更新用户表", description = "参数：用户表更新请求体，权限：管理员（boss, admin)，方法名：updateUserInfo")
    public BaseResponse<Boolean> updateUserInfo(@RequestBody UserInfoUpdateRequest userInfoUpdateRequest) {
        ThrowUtils.throwIf(userInfoUpdateRequest == null || userInfoUpdateRequest.getId() <= 0, ErrorCode.PARAMS_ERROR);
        UserInfo userInfo = commonService.copyProperties(userInfoUpdateRequest, UserInfo.class);
        userInfoService.updateById(userInfo);
        return ResultUtils.success(true);
    }

    /**
     * web端管理员删除用户表
     * @param commonRequest 用户表删除请求体
     * @return 是否删除成功
     */
    @PostMapping("delete")
    @Operation(summary = "web端管理员删除用户表", description = "参数：用户表删除请求体，权限：管理员（boss, admin)，方法名：delUserInfo")
    public BaseResponse<Boolean> delUserInfo(@RequestBody CommonRequest commonRequest) {
        ThrowUtils.throwIf(commonRequest == null || commonRequest.getId() <= 0, ErrorCode.PARAMS_ERROR);
        Long id = commonRequest.getId();
        userInfoService.removeById(id);
        return ResultUtils.success(true);
    }

    /**
     * Web端管理员分页查看用户表
     * @param userInfoQueryRequest 用户表查询请求体
     * @return 用户表列表
     */
    @PostMapping("page")
    @Operation(summary = "Web端管理员分页查看用户表", description = "参数：用户表查询请求体，权限：管理员（boss, admin)，方法名:listUserInfoByPage")
    public BaseResponse<Page<UserInfoVO>> listUserInfoByPage(@RequestBody UserInfoQueryRequest userInfoQueryRequest) {
        if (userInfoQueryRequest == null) throw new BusinessException(ErrorCode.PARAMS_ERROR);
        long current = userInfoQueryRequest.getCurrent();
        long pageSize = userInfoQueryRequest.getPageSize();
        QueryWrapper<UserInfo> queryWrapper = userInfoService.getQueryWrapper(userInfoQueryRequest);
        Page<UserInfo> page = userInfoService.page(new Page<>(current, pageSize), queryWrapper);
        List<UserInfo> userInfoList = page.getRecords();
        List<UserInfoVO> userInfoVOList = commonService.convertList(userInfoList, UserInfoVO.class);
        Page<UserInfoVO> voPage = new Page<>();
        voPage.setRecords(userInfoVOList);
        voPage.setPages(page.getPages());
        voPage.setCurrent(page.getCurrent());
        voPage.setTotal(page.getTotal());
        voPage.setSize(page.getSize());
        return ResultUtils.success(voPage);
    }

    /**
     * web端管理员根据id查询用户表
     * @param commonRequest 用户表查询请求体
     * @return 用户表信息
     */
    @PostMapping("queryById")
    @Operation(summary = "web端管理员根据id查询用户表", description = "参数：用户表查询请求体，权限：管理员（boss, admin)，方法名:queryUserInfoById")
    @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<UserInfoVO> queryUserInfoById(@RequestBody CommonRequest commonRequest) {
        ThrowUtils.throwIf(commonRequest == null || commonRequest.getId() <= 0, ErrorCode.PARAMS_ERROR);
        Long id = commonRequest.getId();
        UserInfo userInfo = userInfoService.getById(id);
        ThrowUtils.throwIf(userInfo == null, ErrorCode.OPERATION_ERROR, "当前用户不存在");
        UserInfoVO userInfoVO = commonService.copyProperties(userInfo, UserInfoVO.class);
        return ResultUtils.success(userInfoVO);
    }


    /**
     * web端管理员批量删除用户表
     * @param commonBatchRequest 用户表批量删除请求体
     * @return 是否删除成功
     */
    @PostMapping("delBatch")
    @Operation(summary = "web端管理员批量删除用户表", description = "参数：用户表批量删除请求体，权限：管理员（boss, admin)，方法名:delBatchUserInfo")
    public BaseResponse<Boolean> delBatchUserInfo(@RequestBody CommonBatchRequest commonBatchRequest) {
        ThrowUtils.throwIf(commonBatchRequest == null || commonBatchRequest.getIds() == null || commonBatchRequest.getIds().isEmpty(), ErrorCode.PARAMS_ERROR);
        List<Long> ids = commonBatchRequest.getIds();
        userInfoService.removeByIds(ids);
        return ResultUtils.success(true);
    }
}
