package com.heyu.api.controller.vv;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.heyu.api.alibaba.request.mm.VvAnonymousUserLoginRequest;
import com.heyu.api.alibaba.request.mm.VvAppBuyerInfoRequest;
import com.heyu.api.alibaba.request.mm.order.VvActivityDTO;
import com.heyu.api.alibaba.request.vv.AppUserLoginRequest;
import com.heyu.api.common.annotation.AppRealyLogin;
import com.heyu.api.common.annotation.Describe;
import com.heyu.api.data.constants.ApiConstants;
import com.heyu.api.data.dao.vv.VvActivityDao;
import com.heyu.api.data.dao.vv.VvBuyerDao;
import com.heyu.api.data.dao.vv.VvPromoterBuyerDao;
import com.heyu.api.data.dao.vv.VvPromoterDao;
import com.heyu.api.data.dto.BuyerDTO;
import com.heyu.api.data.dto.WeiChatLoginDTO;
import com.heyu.api.data.entity.vv.VvActivityEntity;
import com.heyu.api.data.entity.vv.VvBuyerEntity;
import com.heyu.api.data.entity.vv.VvPromoterBuyerEntity;
import com.heyu.api.data.entity.vv.VvPromoterEntity;
import com.heyu.api.data.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

/**
 * App用户登录控制器
 * 提供用户登录、匿名登录、用户信息更新等功能
 *
 * @author heyu
 */
@Slf4j
@RestController
@RequestMapping("/app/user")
public class AppUserLoginController {

    @Autowired
    private VvBuyerDao vvBuyerDao;

    @Autowired
    private RedisUtils redisUtils;


    @Autowired
    private WeChatUtils weChatUtils;


    @Autowired
    private VvPromoterBuyerDao vvPromoterBuyerDao;


    @Autowired
    private VvPromoterDao vvPromoterDao;

    @Autowired
    private VvActivityDao vvActivityDao;


    /**
     * 微信用户登录
     * 通过微信授权码进行登录，如果用户不存在则自动注册
     *
     * @param request 登录请求参数，包含微信授权code和token
     * @return 登录结果，包含买家信息和token
     */
    // http://localhost:8888/app/user/login
    @RequestMapping("/login")
    @Describe("微信用户登录")
    public R login(@RequestBody AppUserLoginRequest request) {
        log.info("[微信用户登录] 开始处理登录请求, code={}", request.getCode());

        // 通过微信授权码获取openId和sessionKey
        WeiChatLoginDTO weiChatLoginDTO = weChatUtils.getOpenId(request.getCode());
        if (weiChatLoginDTO == null) {
            log.warn("[微信用户登录] 微信授权码失效, code={}", request.getCode());
            return R.error("code 失效");
        }

        log.info("[微信用户登录] 获取微信用户信息成功, openid={}", weiChatLoginDTO.getOpenid());

        // 根据openId查询用户信息
        VvBuyerEntity target = vvBuyerDao.selectVvBuyerOpenId(weiChatLoginDTO.getOpenid());
        if (target == null) {
            log.info("[微信用户登录] 新用户注册, openid={}", weiChatLoginDTO.getOpenid());
            target = new VvBuyerEntity();
            target.setOpenid(weiChatLoginDTO.getOpenid());
            target.setIsTest(0);
            target.setCreateTimestamp(System.currentTimeMillis());
        } else {
            log.info("[微信用户登录] 老用户登录, buyerId={}, openid={}", target.getId(), weiChatLoginDTO.getOpenid());
        }

        // 更新sessionKey
        target.setSessionKey(weiChatLoginDTO.getSessionKey());
        vvBuyerDao.insertOrUpdateVvBuyer(target);

        // 构建买家信息并缓存到Redis，默认24小时
        BuyerDTO buyerDTO = buildBuyerLoginInfoCacheRedisDB(target, RedisUtils.DEFAULT_EXPIRE, null, 1);
        log.info("[微信用户登录] 用户登录成功, buyerId={}, token={}", buyerDTO.getBuyerId(), buyerDTO.getToken());

        // 处理推广关系
        insertPromoter(request.getToken(), buyerDTO);

        return R.ok().put("buyer", buyerDTO);
    }

    /**
     * 匿名用户登录
     * 允许用户在不进行微信授权的情况下使用部分功能
     * 使用设备ID进行身份识别，token有效期较短(30分钟)
     *
     * @param request 匿名登录请求参数，包含设备ID和token
     * @return 登录结果，包含买家信息和token
     */
    // http://localhost:8888/app/user/anonymous/login
    @RequestMapping("/anonymous/login")
    @Describe("匿名用户登录")
    public R anonymousLogin(@RequestBody VvAnonymousUserLoginRequest request) {
        log.info("[匿名用户登录] 开始处理匿名登录请求, deviceId={}, token={}", request.getDeviceId(), request.getToken());

        // 解密并验证设备ID
        String deviceId = request.getDeviceId();
        String value = AesUtil.decrypt(deviceId, ApiConstants.AnonymousUserLogin_aes_password);
        if (StringUtils.isBlank(value) || !value.startsWith(ApiConstants.AnonymousUserLogin_pre)) {
            log.warn("[匿名用户登录] 设备号验证失败, deviceId={}, decryptValue={}", deviceId, value);
            return R.error("设备号不对");
        }

        log.info("[匿名用户登录] 设备号验证通过, decryptValue={}", value);

        BuyerDTO buyerDTO = null;
        // 尝试从Redis获取已登录的用户信息
        String activityInfoStr = redisUtils.get(request.getToken());
        if (StringUtils.isNotEmpty(activityInfoStr)) {
            buyerDTO = JSONObject.parseObject(activityInfoStr, BuyerDTO.class);
            log.info("[匿名用户登录] 从token中获取到用户信息, buyerId={}", buyerDTO.getBuyerId());

            // 如果是真实用户(buyerId > 0)，重新构建登录信息
            if (buyerDTO.getBuyerId() > 0) {
                VvBuyerEntity target = vvBuyerDao.selectVvBuyerById(buyerDTO.getBuyerId());
                buyerDTO = buildBuyerLoginInfoCacheRedisDB(target, RedisUtils.DEFAULT_EXPIRE, null, 1);
                log.info("[匿名用户登录] 真实用户登录, buyerId={}", buyerDTO.getBuyerId());
            }
        }

        // 如果没有用户信息，创建匿名用户(buyerId=0)
        if (buyerDTO == null) {
            log.info("[匿名用户登录] 创建匿名用户, deviceId={}", deviceId);
            VvBuyerEntity target = new VvBuyerEntity();
            target.setId(0L);
            target.setIsTest(0);
            buyerDTO = buildBuyerLoginInfoCacheRedisDB(target, RedisUtils.thirty_minute, request.getDeviceId(), 0);
        }

        log.info("[匿名用户登录] 登录成功, buyerId={}, loginType={}, token={}",
                buyerDTO.getBuyerId(), buyerDTO.getLoginType(), buyerDTO.getToken());

        // 处理推广关系
        insertPromoter(request.getToken(), buyerDTO);

        return R.ok().put("buyer", buyerDTO);
    }


    /**
     * 处理推广关系
     * 当用户通过推广链接登录时，建立推广者与被推广者的关系
     *
     * @param requestToken 请求中的原始token，可能包含活动信息
     * @param buyerDTO     登录后的买家信息
     */
    public void insertPromoter(String requestToken, BuyerDTO buyerDTO) {
        log.info("[处理推广关系] 开始处理, requestToken={}, buyerId={}", requestToken, buyerDTO.getBuyerId());

        // 从Redis获取活动信息
        String activityInfo = redisUtils.get(ApiConstants.token_activity + requestToken);
        if (StringUtils.isNotEmpty(activityInfo)) {
            VvActivityDTO vvActivityDTO = JSONObject.parseObject(activityInfo, VvActivityDTO.class);
            log.info("[处理推广关系] 获取到活动信息, activityId={}, promoterId={}",
                    vvActivityDTO.getActivityId(), vvActivityDTO.getBuyerId());

            // 获取被推广买家信息
            VvBuyerEntity wasBuyerEntity = vvBuyerDao.selectVvBuyerById(buyerDTO.getBuyerId());
            if (wasBuyerEntity == null) {
                log.warn("[处理推广关系] 被推广买家不存在，使用默认值, buyerId={}", buyerDTO.getBuyerId());
                wasBuyerEntity = new VvBuyerEntity();
                wasBuyerEntity.setId(0L);
                wasBuyerEntity.setBuyerName("0");
                wasBuyerEntity.setBuyerPhone("0");
                wasBuyerEntity.setBuyerWeixin("0");
            }

            // 获取活动信息
            VvActivityEntity vvActivityEntity = vvActivityDao.selectVvActivityById(vvActivityDTO.getActivityId());

            // 计算活动剩余时间，将活动信息关联到新token
            Date endTime = new Date(vvActivityDTO.getActivityExpiredTime());
            int second = DateUtils.betweenSecond(new Date(), endTime);

            log.info("[处理推广关系] 活动信息转移, requestToken={}, loginToken={}, activityId={}, remainSeconds={}",
                    requestToken, buyerDTO.getToken(), vvActivityDTO.getActivityId(), second);

            // 将活动信息关联到新的登录token
            redisUtils.set(ApiConstants.token_activity + buyerDTO.getToken(), JSON.toJSONString(vvActivityDTO), second);

            // 查询推广者信息
            List<Long> promoterBuyerIdList = new LinkedList<>();
            promoterBuyerIdList.add(vvActivityDTO.getBuyerId());
            List<VvBuyerEntity> promoterBuyerList = vvBuyerDao.selectVvBuyerByIdList(promoterBuyerIdList);

            // 创建推广记录
            VvPromoterEntity vvPromoter = new VvPromoterEntity();
            vvPromoter.setActivityId(vvActivityDTO.getActivityId());
            vvPromoter.setPromoterCode(vvActivityDTO.getPromoterCode());
            vvPromoter.setCreateTimestamp(System.currentTimeMillis());
            vvPromoter.setActivityName(vvActivityEntity.getActivityName());
            vvPromoter.setBuyerInfo(JSONObject.toJSONString(vvActivityDTO));
            vvPromoterDao.insertVvPromoter(vvPromoter);

            log.info("[处理推广关系] 创建推广记录成功, promoterId={}, activityId={}, promoterCode={}",
                    vvPromoter.getId(), vvActivityDTO.getActivityId(), vvActivityDTO.getPromoterCode());

            // 建立推广者与被推广者的关系
            for (VvBuyerEntity promoterBuyerEntity : promoterBuyerList) {
                VvPromoterBuyerEntity vvPromoterBuyerEntity = new VvPromoterBuyerEntity();
                vvPromoterBuyerEntity.setPromoterId(vvPromoter.getId());
                vvPromoterBuyerEntity.setPromoterBuyerId(promoterBuyerEntity.getId());
                vvPromoterBuyerEntity.setPromoterBuyerName(promoterBuyerEntity.getBuyerName());
                vvPromoterBuyerEntity.setPromoterBuyerPhone(promoterBuyerEntity.getBuyerPhone());
                vvPromoterBuyerEntity.setPromoterBuyerWeixin(promoterBuyerEntity.getBuyerWeixin());
                vvPromoterBuyerEntity.setCreateTimestamp(System.currentTimeMillis());

                vvPromoterBuyerEntity.setWasBuyerId(wasBuyerEntity.getId());
                vvPromoterBuyerEntity.setWasBuyerName(wasBuyerEntity.getBuyerName());
                vvPromoterBuyerEntity.setWasBuyerPhone(wasBuyerEntity.getBuyerPhone());
                vvPromoterBuyerEntity.setWasBuyerWeixin(wasBuyerEntity.getBuyerWeixin());
                vvPromoterBuyerDao.insertOrUpdateVvPromoterBuyer(vvPromoterBuyerEntity);

                log.info("[处理推广关系] 建立推广关系成功, promoterId={}, promoterBuyerId={}, wasBuyerId={}",
                        vvPromoter.getId(), promoterBuyerEntity.getId(), wasBuyerEntity.getId());
            }
        } else {
            log.info("[处理推广关系] 无活动信息，跳过推广关系处理, requestToken={}", requestToken);
        }
    }

    /**
     * 更新用户信息
     * 允许用户修改昵称和头像
     *
     * @param request 更新请求参数，包含买家ID、昵称、头像
     * @return 更新结果，包含更新后的买家信息
     */
    // http://localhost:8888/app/buyer/info/update
    @RequestMapping("/buyer/info/update")
    @Describe("更新用户信息")
    @AppRealyLogin
    public R buyerInfoUpdate(@RequestBody VvAppBuyerInfoRequest request) {
        log.info("[更新用户信息] 开始处理, buyerId={}, buyerName={}", request.getBuyerId(), request.getBuyerName());

        VvBuyerEntity vvBuyerEntity = vvBuyerDao.selectVvBuyerById(request.getBuyerId());
        if (vvBuyerEntity == null) {
            log.warn("[更新用户信息] 用户不存在, buyerId={}", request.getBuyerId());
            return R.error("你不是内部用户");
        }

        // 更新用户信息
        vvBuyerEntity.setBuyerName(request.getBuyerName());
        vvBuyerEntity.setAvatar(request.getAvatar());
        vvBuyerDao.insertOrUpdateVvBuyer(vvBuyerEntity);

        log.info("[更新用户信息] 更新成功, buyerId={}, buyerName={}, avatar={}",
                vvBuyerEntity.getId(), vvBuyerEntity.getBuyerName(), vvBuyerEntity.getAvatar());

        return R.ok().put("buyer", vvBuyerEntity);
    }



    /**
     * 构建买家登录信息并缓存到Redis
     * 生成token并将买家信息存储到Redis中
     *
     * @param target     买家实体信息
     * @param expireTime token过期时间(秒)
     * @param deviceId   设备ID，用于匿名登录
     * @param loginType  登录类型(0:匿名登录, 1:微信登录)
     * @return 买家DTO，包含token等信息
     */
    public BuyerDTO buildBuyerLoginInfoCacheRedisDB(VvBuyerEntity target, Long expireTime, String deviceId, Integer loginType) {
        log.info("[构建登录信息] 开始构建, buyerId={}, loginType={}, expireTime={}秒",
                target.getId(), loginType, expireTime);

        BuyerDTO buyerDTO = new BuyerDTO();
        buyerDTO.setBuyerId(target.getId());
        buyerDTO.setBuyerName(target.getBuyerName());
        buyerDTO.setIsTest(target.getIsTest());
        buyerDTO.setAvatar(target.getAvatar());
        buyerDTO.setLoginType(loginType);
        buyerDTO.setBuyerPhone(target.getBuyerPhone());
        buyerDTO.setBuyerWeixin(target.getBuyerWeixin());

        // 生成token并缓存到Redis
        String token = TokenUtils.generateToken(target.getId() + deviceId);
        redisUtils.set(token, JSON.toJSONString(buyerDTO), expireTime);
        buyerDTO.setToken(token);

        log.info("[构建登录信息] 构建完成, buyerId={}, token={}, expireTime={}秒",
                target.getId(), token, expireTime);

        return buyerDTO;
    }




}
