package com.kexue.skills.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.kexue.skills.common.LoginUserCacheUtil;
import com.kexue.skills.entity.CmsContent;
import com.kexue.skills.entity.ContentPurchase;
import com.kexue.skills.entity.dto.ContentPurchaseDto;
import com.kexue.skills.common.Assert;
import com.kexue.skills.exception.BizException;
import com.kexue.skills.mapper.ContentPurchaseMapper;
import com.kexue.skills.service.AccountService;
import com.kexue.skills.service.CmsContentService;
import com.kexue.skills.service.ContentPurchaseService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import cn.dev33.satoken.stp.StpUtil;

/**
 * (ContentPurchase)表服务实现类
 *
 * @author 王志维
 * @since 2025-02-21 23:01:48
 */
@Service("contentPurchaseService")
@Transactional(rollbackFor = Exception.class)
public class ContentPurchaseServiceImpl implements ContentPurchaseService {
    @Resource
    private ContentPurchaseMapper contentPurchaseMapper;

    @Resource
    private CmsContentService cmsContentService;

    @Resource
    private AccountService accountService;
    
    @Resource
    private LoginUserCacheUtil loginUserCacheUtil;

    /**
     * 分页查询
     *
     * @param queryDto 筛选条件
     * @return 查询结果
     */
    @Override
    public PageInfo<ContentPurchase> getPageList(ContentPurchaseDto queryDto) {
        PageHelper.startPage(queryDto.getPageNum(), queryDto.getPageSize());
        List<ContentPurchase> list = this.contentPurchaseMapper.getPageList(queryDto);
        return new PageInfo<>(list);
    }

    /**
     * 查询列表
     *
     * @param queryDto 筛选条件
     * @return 查询结果
     */
    @Override
    public List<ContentPurchase> getList(ContentPurchaseDto queryDto) {
        return this.contentPurchaseMapper.getList(queryDto);
    }

    /**
     * 通过主键查询单条数据
     *
     * @param purchaseId 主键
     * @return 实例对象
     */
    @Override
    public ContentPurchase queryById(Long purchaseId) {
        return this.contentPurchaseMapper.queryById(purchaseId);
    }

    /**
     * 通过用户ID和内容ID查询购买记录
     *
     * @param userId 用户ID
     * @param contentId 内容ID
     * @return 实例对象
     */
    @Override
    public ContentPurchase queryByUserIdAndContentId(Long userId, Long contentId) {
        return this.contentPurchaseMapper.queryByUserIdAndContentId(userId, contentId);
    }

    /**
     * 新增数据
     *
     * @param purchase 实例对象
     * @return 实例对象
     */
    @Override
    public ContentPurchase insert(ContentPurchase purchase) {
        // 设置创建时间和更新时间
        Date now = new Date();
        purchase.setCreateTime(now);
        purchase.setUpdateTime(now);
        // 设置默认值
        purchase.setDeleteFlag(0);
        // 保存数据
        this.contentPurchaseMapper.insert(purchase);
        return purchase;
    }

    /**
     * 更新数据
     *
     * @param purchase 实例对象
     * @return 实例对象
     */
    @Override
    public ContentPurchase update(ContentPurchase purchase) {
        // 设置更新时间
        purchase.setUpdateTime(new Date());
        // 更新数据
        this.contentPurchaseMapper.update(purchase);
        return this.queryById(purchase.getPurchaseId());
    }

    /**
     * 更新购买状态
     *
     * @param purchaseId 购买ID
     * @param status 状态
     * @return 影响行数
     */
    @Override
    public int updateStatus(Long purchaseId, Integer status) {
        return this.contentPurchaseMapper.updateStatus(purchaseId, status);
    }

    /**
     * 通过主键逻辑删除
     *
     * @param purchaseId 主键
     * @param updateBy 更新人
     * @return 影响行数
     */
    @Override
    public int logicDeleteById(Long purchaseId, String updateBy) {
        return this.contentPurchaseMapper.logicDeleteById(purchaseId, updateBy);
    }

    /**
     * 通过主键物理删除
     *
     * @param purchaseId 主键
     * @return 影响行数
     */
    @Override
    public int deleteById(Long purchaseId) {
        return this.contentPurchaseMapper.deleteById(purchaseId);
    }

    /**
     * 购买内容
     *
     * @param userId 用户ID
     * @param contentId 内容ID
     * @param payType 支付方式：1.余额支付 2.积分支付 3.微信支付 4.支付宝支付
     * @return 购买结果
     */
    @Override
    public ContentPurchase purchaseContent(Long userId, Long contentId, Integer payType) {
        // 1. 查询内容信息
        CmsContent content = this.cmsContentService.queryById(contentId);
        Assert.notNull(content, "内容不存在");

        // 2. 检查内容是否需要付费
        Assert.isTrue(content.getIsPaid() != 0, "该内容为免费内容，无需购买");

        // 3. 检查用户是否已经购买过该内容
        ContentPurchase existingPurchase = this.queryByUserIdAndContentId(userId, contentId);
        if (existingPurchase != null && existingPurchase.getStatus() == 2) {
            // 已经购买过，直接返回
            return existingPurchase;
        }

        // 4. 创建购买记录
        ContentPurchase purchase = new ContentPurchase();
        purchase.setUserId(userId);
        purchase.setContentId(contentId);
        purchase.setContentTitle(content.getTitle());
        purchase.setPayType(payType);
        purchase.setStatus(1); // 待支付
        purchase.setCreateTime(new Date());
        purchase.setUpdateTime(new Date());
        purchase.setDeleteFlag(0);

        // 5. 根据支付方式处理支付
        String transactionNo = UUID.randomUUID().toString().replaceAll("-", "");
        boolean isPaid = false;
        if (payType == 1) {
            // 余额支付
            BigDecimal price = content.getPrice();
            purchase.setAmount(price);
            purchase.setPoints(0);
            
            // 扣除用户余额
            this.accountService.reduceBalance(userId, price, transactionNo, contentId, "purchase_content", "购买内容：" + content.getTitle());
            
            // 6. 更新购买记录状态
            purchase.setStatus(2); // 已支付
            purchase.setPurchaseTime(new Date());
            this.insert(purchase);
            isPaid = true;
        } else if (payType == 3 || payType == 4) {
            // 微信支付或支付宝支付
            // 这里只创建购买记录，实际支付由前端调用支付接口完成
            // 支付完成后通过回调更新购买记录状态
            BigDecimal price = content.getPrice();
            purchase.setAmount(price);
            purchase.setPoints(0);
            
            // 插入购买记录（状态为待支付）
            this.insert(purchase);
        } else {
            Assert.isTrue(false, "不支持的支付方式");
        }

        // 更新Redis中的LoginUser对象
        if (isPaid) {
            String token = loginUserCacheUtil.getTokenFromRequest();
            if (token != null) {
                loginUserCacheUtil.updateHas(token, userId);
            }
        }

        return purchase;
    }

    /**
     * 检查用户是否有权限访问内容
     *
     * @param userId 用户ID
     * @param contentId 内容ID
     * @return 是否有权限
     */
    @Override
    public boolean checkAccessPermission(Long userId, Long contentId) {
        // 1. 查询内容信息
        CmsContent content = this.cmsContentService.queryById(contentId);
        if (content == null) {
            return false;
        }

        // 2. 如果是免费内容，直接允许访问
        if (content.getIsPaid() == 0) {
            return true;
        }

        // 3. 如果是付费内容，检查用户是否购买过
        ContentPurchase purchase = this.queryByUserIdAndContentId(userId, contentId);
        if (purchase != null && purchase.getStatus() == 2) {
            // 已经购买过，允许访问
            return true;
        }

        // 4. 未购买，不允许访问
        return false;
    }
}