
package com.yami.shop.api.controller;


import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.hutool.core.util.StrUtil;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.yami.shop.bean.app.dto.UserCenterInfoDto;
import com.yami.shop.bean.app.dto.UserDto;
import com.yami.shop.bean.app.param.UserInfoParam;
import com.yami.shop.bean.model.*;
import com.yami.shop.bean.param.UserParam;
import com.yami.shop.config.WxConfig;
import com.yami.shop.dao.ChannelMapper;
import com.yami.shop.security.api.model.YamiUser;
import com.yami.shop.security.api.service.YamiUserDetailsService;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.security.comment.enums.App;
import com.yami.shop.security.comment.exception.WxErrorException;
import com.yami.shop.security.comment.model.AppConnect;
import com.yami.shop.security.comment.service.AppConnectService;
import com.yami.shop.service.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

/**
 * 用户信息
 *
 * @author LGH
 */
@Slf4j
@RestController
@RequestMapping("/p/user")
@Api(tags = "用户接口")
@AllArgsConstructor
public class UserController {

    private final UserService userService;

    private final MapperFacade mapperFacade;

    private final OrderService orderService;

    private final ShopDetailService shopDetailService;

    private final ShopAuditingService shopAuditingService;

    private final WxConfig wxConfig;

    private final ChannelMapper channelMapper;


    private final AppConnectService appConnectService;

    private final YamiUserDetailsService yamiUserDetailsService;

    @Lazy
    private final AuthorizationServerTokenServices yamiTokenServices;


    /**
     * 查看用户接口
     */
    @GetMapping("/userInfo")
    @ApiOperation(value = "查看用户信息", notes = "根据用户ID（userId）获取用户信息")
    public ResponseEntity<UserDto> userInfo() {
        String userId = SecurityUtils.getUser().getUserId();
        User user = userService.getUserByUserId(userId);
        UserDto userDto = mapperFacade.map(user, UserDto.class);
        Channel channel = channelMapper.selectById(user.getChannelId());
        if (ObjectUtils.isNotEmpty(channel)) {
            userDto.setEnterprise(channel.getChannelName());
        }
        if (userDto.getUserMobile() != null) {
            userDto.setMobile(userDto.getUserMobile().replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"));
        }
        userDto.setUserId(userId);

        return ResponseEntity.ok(userDto);
    }

    @PutMapping("/setUserInfo")
    @ApiOperation(value = "设置用户信息", notes = "设置用户信息")
    public ResponseEntity<Void> setUserInfo(@RequestBody UserInfoParam userInfoParam) {
        String userId = SecurityUtils.getUser().getUserId();
        User user = new User();
        user.setUserId(userId);
        user.setPic(StrUtil.isBlank(userInfoParam.getAvatarUrl()) ? null : userInfoParam.getAvatarUrl());
        user.setSex(userInfoParam.getSex() == null ? user.getSex() : userInfoParam.getSex());
        user.setNickName(userInfoParam.getNickName() == null ? user.getNickName() : userInfoParam.getNickName());
        user.setUserMobile(userInfoParam.getUserMobile() == null ? user.getUserMobile() : userInfoParam.getUserMobile());
        user.setBirthDate(userInfoParam.getBirthDate() == null ? user.getBirthDate() : userInfoParam.getBirthDate());
        user.setUserMail(StrUtil.isNotBlank(userInfoParam.getUserMail()) ? userInfoParam.getUserMail() : user.getUserMail());
        if (StrUtil.isNotBlank(userInfoParam.getNickName())) {
            user.setNickName(userInfoParam.getNickName());
        }
        userService.updateById(user);
        return ResponseEntity.ok().build();
    }

    @GetMapping("/centerInfo")
    @ApiOperation(value = "个人中心信息", notes = "获取用户个人中心信息")
    public ResponseEntity<UserCenterInfoDto> centerInfo() {
        String userId = SecurityUtils.getUser().getUserId();
        UserCenterInfoDto userCenterInfoDto = new UserCenterInfoDto();
        userCenterInfoDto.setOrderCountData(orderService.getOrderCount(userId));

        ShopAuditing shopAuditing = shopAuditingService.getShopAuditingByUserId(userId);

        userCenterInfoDto.setShopAuditStatus(shopAuditing == null ? null : shopAuditing.getStatus());

        ShopDetail shopDetail = shopDetailService.getShopDetailByUserId(userId);

        userCenterInfoDto.setIsSetPassword(shopDetail != null && StrUtil.isNotBlank(shopDetail.getPassword()));

        userCenterInfoDto.setShopId(shopDetail == null ? null : shopDetail.getShopId());
        userCenterInfoDto.setShopStatus(shopDetail == null ? null : shopDetail.getShopStatus());
        return ResponseEntity.ok(userCenterInfoDto);
    }


    @GetMapping("/getPhoneNumber")
    @ApiOperation(value = "获取用户绑定手机号", notes = "根据小程序的加密数据，iv获取当前用户的手机号")
    public ResponseEntity<WxMaPhoneNumberInfo> getPhoneNumber(@RequestParam String encryptedData, @RequestParam String ivStr) {

        return ResponseEntity.ok(wxConfig.getWxMaService().getUserService().getPhoneNoInfo(SecurityUtils.getUser().getSessionKey(), encryptedData, ivStr));
    }

    @GetMapping("/getUserScore")
    @ApiOperation(value = "获取用户积分", notes = "返回用户的积分信息")
    public ResponseEntity<UserParam> getUserScore() {
        String userId = SecurityUtils.getUser().getUserId();
        User user = userService.getById(userId);
        UserParam userParam = mapperFacade.map(user, UserParam.class);
        System.out.println();
        return ResponseEntity.ok(userParam);
    }

    /**
     * 小程序登录接口 - 使用实体类方式
     */
    @GetMapping("/miniAppLogin")
    @ApiOperation(value = "小程序登录", notes = "通过微信小程序code登录，返回token信息")
    public ResponseEntity<MiniAppLoginResponse> miniAppLogin(@RequestParam(value = "code") String code) {
        try {
            // 通过微信code获取session信息
            WxMaJscode2SessionResult session = wxConfig.getWxMaService().getUserService().getSessionInfo(code);

            // 查找或创建AppConnect
            AppConnect appConnect = appConnectService.getByBizUserId(session.getOpenid(), App.MINI.value());
            if (appConnect == null) {
                appConnect = new AppConnect();
                appConnect.setAppId(App.MINI.value());
                appConnect.setBizUserId(session.getOpenid());
                appConnect.setBizUnionid(session.getUnionid());
                appConnectService.save(appConnect);

            }

            // 加载用户信息
            YamiUser yamiUser = yamiUserDetailsService.loadUserByAppConnect(appConnect);
            yamiUser.setSessionKey(session.getSessionKey());

            // 生成OAuth2 Token
            String clientId = String.valueOf(App.MINI.value());
            OAuth2Request oAuth2Request = new OAuth2Request(null, clientId, null, true, null,
                    null, null, null, null);

            // 手动设置用户详情
            com.yami.shop.security.comment.token.AuthenticationToken authToken =
                    new com.yami.shop.security.comment.token.AuthenticationToken();
            authToken.setDetails(yamiUser);
            authToken.setPrincipal(yamiUser.getUserId());
            authToken.setAppType(App.MINI.value());
            authToken.setAuthenticated(true);

            OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authToken);

            // 生成token
            OAuth2AccessToken oAuth2AccessToken = yamiTokenServices.createAccessToken(oAuth2Authentication);

            // 构造返回对象
            MiniAppLoginResponse response = new MiniAppLoginResponse();
            response.setAccess_token(oAuth2AccessToken.getValue());
            response.setToken_type(oAuth2AccessToken.getTokenType());
            response.setRefresh_token(oAuth2AccessToken.getRefreshToken() != null ?
                    oAuth2AccessToken.getRefreshToken().getValue() : null);
            response.setExpires_in(oAuth2AccessToken.getExpiresIn());
            response.setScope(oAuth2AccessToken.getScope() != null ?
                    String.join(",", oAuth2AccessToken.getScope()) : null);

            // 设置用户信息（直接从yamiUser获取，确保有值）
            response.setUserId(yamiUser.getUserId());
            response.setNickName(yamiUser.getName());
            response.setPic(yamiUser.getPic());
            response.setEnabled(yamiUser.isEnabled());

            // 如果token中也有额外信息，作为备用
            if (oAuth2AccessToken.getAdditionalInformation() != null && !oAuth2AccessToken.getAdditionalInformation().isEmpty()) {
                // Token增强器添加的信息作为备用
                if (response.getUserId() == null) {
                    response.setUserId((String) oAuth2AccessToken.getAdditionalInformation().get("userId"));
                }
//                if (response.getUserId() == null) {
//                    response.setUserId(appConnect.getUserId());
//                }
                if (response.getNickName() == null) {
                    response.setNickName((String) oAuth2AccessToken.getAdditionalInformation().get("nickName"));
                }
                if (response.getNickName() == null) {
                    response.setNickName(appConnect.getNickName());
                }

                if (response.getPic() == null) {
                    response.setPic((String) oAuth2AccessToken.getAdditionalInformation().get("pic"));
                }
                if (response.getEnabled() == null) {
                    response.setEnabled((Boolean) oAuth2AccessToken.getAdditionalInformation().get("enabled"));
                }
            }
            log.info("小程序登录成功，返回response：{}", response);
            return ResponseEntity.ok(response);

        } catch (me.chanjar.weixin.common.error.WxErrorException e) {
            throw new WxErrorException("微信登录失败: " + e.getMessage());
        }
    }


    /**
     * 小程序登录响应实体
     */
    @Data
    public static class MiniAppLoginResponse {
        @ApiModelProperty(value = "访问令牌")
        private String access_token;

        @ApiModelProperty(value = "令牌类型")
        private String token_type;

        @ApiModelProperty(value = "刷新令牌")
        private String refresh_token;

        @ApiModelProperty(value = "过期时间(秒)")
        private Integer expires_in;

        @ApiModelProperty(value = "授权范围")
        private String scope;

        @ApiModelProperty(value = "用户ID")
        private String userId;

        @ApiModelProperty(value = "用户昵称")
        private String nickName;

        @ApiModelProperty(value = "用户头像")
        private String pic;

        @ApiModelProperty(value = "是否启用")
        private Boolean enabled;
    }

}
