package com.corewing.app.modules.app;

import cn.dev33.satoken.stp.StpUtil;
import com.corewing.app.common.Result;
import com.corewing.app.common.annotation.CommonLog;
import com.corewing.app.dto.*;
import com.corewing.app.entity.User;
import com.corewing.app.service.UserService;
import com.corewing.app.service.VerifyCodeService;
import com.corewing.app.util.I18nUtil;
import com.corewing.app.util.IpUtil;
import com.corewing.app.util.RedisUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;

/**
 * 应用用户 Controller
 */
@Api(tags = "用户接口")
@RestController
@RequestMapping("/user")
public class AppUserController {

    @Resource
    private UserService userService;

    @Resource
    private VerifyCodeService verifyCodeService;

    @Resource
    private RedisUtil redisUtil;


    /**
     * 发送验证码
     */
    @CommonLog("发送验证码接口")
    @ApiOperation("发送验证码接口")
    @PostMapping("/sendCode")
    public Result<String> sendCode(@RequestBody SendCodeRequest request) {
        try {
            boolean success = verifyCodeService.sendCode(request.getAccount(), request.getType());
            if (success) {
                return Result.success(I18nUtil.getMessage("user.code.send.success"));
            }
            return Result.error(I18nUtil.getMessage("user.code.send.failed"));
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }

    /**
     * 用户登录（支持用户名/邮箱/手机号）
     */
    @ApiOperation("用户登录接口")
    @PostMapping("/login")
    public Result<Map<String, Object>> login(@RequestBody LoginRequest request, HttpServletRequest httpRequest) {
        try {
            String token = userService.login(request.getAccount(), request.getPassword());

            // 更新登录IP和归属地
            User user = userService.getByAccount(request.getAccount());
            String loginIp = IpUtil.getClientIp(httpRequest);
            userService.updateLoginInfo(user.getId(), loginIp);

            Map<String, Object> data = new HashMap<>();
            data.put("token", token);
            data.put("userId", user.getId());
            data.put("username", user.getUsername());

            redisUtil.set("APP_" + user.getId(), user);

            return Result.success(I18nUtil.getMessage("user.login.success"), data);
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }

    /**
     * 用户注册（需要验证码）
     */
    @ApiOperation("用户注册接口")
    @PostMapping("/register")
    public Result<String> register(@RequestBody RegisterRequest request, HttpServletRequest httpRequest) {
        try {
            User user = new User();
            user.setUsername(request.getUsername());
            user.setPassword(request.getPassword());
            user.setEmail(request.getEmail());
            user.setTelephone(request.getTelephone());
            user.setAvatar(request.getAvatar());

            // 获取注册IP
            String registerIp = IpUtil.getClientIp(httpRequest);
            userService.register(user, request.getCode(), registerIp);
            return Result.success(I18nUtil.getMessage("user.register.success"));
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }

    /**
     * 用户登出
     */
    @ApiOperation("用户登出接口")
    @PostMapping("/logout")
    public Result<String> logout() {
        StpUtil.logout();
        return Result.success(I18nUtil.getMessage("user.logout.success"));
    }

    /**
     * 获取当前登录用户信息
     */
    @CommonLog("获取当前登录用户信息")
    @ApiOperation("获取当前登录用户信息")
    @GetMapping("/info")
    public Result<User> getUserInfo() {
        Long userId = StpUtil.getLoginIdAsLong();

        try {
            // 缓存获取
            User user = (User) redisUtil.get("APP_" + userId);
            return Result.success(user);
        } catch (Exception e) {
            User user = userService.getById(userId);
            // 隐藏密码
            user.setPassword(null);
            return Result.success(user);
        }
    }

    /**
     * 根据ID查询用户
     */
    @CommonLog("根据id查询用户")
    @ApiOperation("根据id查询用户")
    @GetMapping("/{id}")
    public Result<User> getById(@PathVariable Long id) {
        User user = userService.getById(id);
        if (user != null) {
            // 隐藏密码
            user.setPassword(null);
            return Result.success(user);
        }
        return Result.error(I18nUtil.getMessage("user.not.found"));
    }

    /**
     * 更新用户信息
     */
    @CommonLog("更新用户信息")
    @ApiOperation("更新用户信息")
    @PutMapping("/update")
    public Result<String> update(@RequestBody User user) {
        Long userId = StpUtil.getLoginIdAsLong();
        user.setId(userId);
        // 不允许通过此接口修改密码
        user.setPassword(null);
        boolean success = userService.updateById(user);

        // 更新缓存
        User cacheUser = userService.getById(userId);
        redisUtil.set("APP_" + user.getId(), cacheUser);
        if (success) {
            return Result.success(I18nUtil.getMessage("user.update.success"));
        }
        return Result.error(I18nUtil.getMessage("user.update.failed"));
    }

    /**
     * 修改密码
     */
    @CommonLog("用户修改密码")
    @ApiOperation("用户修改密码")
    @PutMapping("/password")
    public Result<String> updatePassword(@RequestBody UpdatePasswordRequest request) {
        try {
            Long userId = StpUtil.getLoginIdAsLong();
            User user = userService.getById(userId);

            // 验证旧密码
            String oldPasswordMd5 = org.springframework.util.DigestUtils.md5DigestAsHex(
                    request.getOldPassword().getBytes(java.nio.charset.StandardCharsets.UTF_8));

            if (!oldPasswordMd5.equals(user.getPassword())) {
                return Result.error(I18nUtil.getMessage("user.password.old.incorrect"));
            }

            // 更新新密码
            String newPasswordMd5 = org.springframework.util.DigestUtils.md5DigestAsHex(
                    request.getNewPassword().getBytes(java.nio.charset.StandardCharsets.UTF_8));

            user.setPassword(newPasswordMd5);
            userService.updateById(user);

            return Result.success(I18nUtil.getMessage("user.password.update.success"));
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }

    /**
     * 忘记密码
     * @param request
     * @return
     */
    @CommonLog("忘记密码")
    @ApiOperation("忘记密码")
    @PutMapping("/forgetPassword")
    public Result<String> forgetPassword(@RequestBody ForgetPasswordRequest request) {
        return Result.isBool(userService.forgetPassword(request));
    }

    /**
     * 验证码登录
     * @return
     */
    @ApiOperation("验证码登录")
    @PostMapping("/codeLogin")
    public Result<Map<String, Object>> codeLogin(@RequestBody CodeLoginRequest codeLoginRequest, HttpServletRequest request) {

        String token = userService.codeLogin(codeLoginRequest);
        // 更新登录IP和归属地
        User user = userService.getByAccount(codeLoginRequest.getAccount());
        String loginIp = IpUtil.getClientIp(request);
        userService.updateLoginInfo(user.getId(), loginIp);

        Map<String, Object> data = new HashMap<>();
        data.put("token", token);
        data.put("userId", user.getId());
        data.put("username", user.getUsername());
        redisUtil.set("APP_" + user.getId(), user);
        return Result.success(I18nUtil.getMessage("user.login.success"), data);
    }

    /**
     * 注销用户
     * @param logoffRequest
     * @return
     */
    @CommonLog("注销用户")
    @ApiOperation("注销用户")
    @DeleteMapping("/delete")
    public Result<String> logoff(@RequestBody @Valid LogoffRequest logoffRequest) {
        return Result.isBool(userService.logoff(logoffRequest));
    }

    /**
     * 注销发送验证码
     * @return
     */
    @CommonLog("发送注销验证码")
    @ApiOperation("发送注销验证码")
    @PostMapping("/delete/sendCode")
    public Result<Map<String, String>> deleteSendCode() {
        return userService.deleteSendCode();
    }
}
