package org.dromara.zhishu.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.RandomStringUtils;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.zhishu.domain.TInviteCode;
import org.dromara.zhishu.domain.TInviteRelation;
import org.dromara.zhishu.domain.bo.InviteCodeBo;
import org.dromara.zhishu.domain.vo.InviteCodeVo;
import org.dromara.zhishu.mapper.TInviteCodeMapper;
import org.dromara.zhishu.mapper.TInviteRelationMapper;
import org.dromara.zhishu.service.ITInviteCodeService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 邀请码 Service 实现
 */
@Service
@RequiredArgsConstructor
public class TInviteCodeServiceImpl implements ITInviteCodeService {

    private final TInviteCodeMapper inviteCodeMapper;
    private final TInviteRelationMapper inviteRelationMapper;

    @Value("${invite.url.prefix:https://erp.buzhiyushu.cn/register?code=}")
    private String inviteUrlPrefix;

    @Value("${invite.code.expireDays:30}")
    private int defaultExpireDays;

    /**
     * 查询邀请码
     *
     * @param id 邀请码主键
     * @return 邀请码
     */
    @Override
    public InviteCodeVo queryById(Long id) {
        return MapstructUtils.convert(inviteCodeMapper.selectById(id), InviteCodeVo.class);
    }

    /**
     * 查询邀请码列表
     *
     * @param userId 用户ID
     * @return 邀请码列表
     */
    @Override
    public List<InviteCodeVo> queryListByUserId(Long userId) {
        return inviteCodeMapper.selectListByUserId(userId);
    }

    /**
     * 查询邀请码分页列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 邀请码分页列表
     */
    @Override
    public TableDataInfo<InviteCodeVo> queryPageList(InviteCodeBo bo, PageQuery pageQuery) {
        Page<InviteCodeVo> page = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize());
        page = inviteCodeMapper.selectPageList(page, bo.getUserId(), bo.getCode(), bo.getUsed());
        return TableDataInfo.build(page);
    }

    /**
     * 生成邀请码
     *
     * @param bo 邀请码信息
     * @return 邀请码
     */
    @Override
    public int generateInviteCode(InviteCodeBo bo) {
        TInviteCode inviteCode = new TInviteCode();
        inviteCode.setUserId(bo.getUserId());

        // 生成随机邀请码
        String code = generateUniqueCode();
        inviteCode.setCode(code);

        // 生成邀请链接
        inviteCode.setInviteUrl(inviteUrlPrefix + code);

        // 设置为永不过期（使用非常远的未来日期）
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.YEAR, 100);  // 100年后过期，实际上相当于永不过期
        inviteCode.setExpireTime(calendar.getTime());

        // 设置未使用状态
        inviteCode.setUsed(false);
        inviteCode.setCreatedAt(new Date());
        // 3. 转换为 VO 对象并返回
        return inviteCodeMapper.insertGenerateInviteCode(inviteCode);
    }

    /**
     * 验证邀请码
     *
     * @param code 邀请码
     * @return 邀请码信息，如果无效则返回null
     */
    @Override
    public TInviteCode validateInviteCode(String code) {
        return inviteCodeMapper.validateInviteCode(code);
    }

    /**
     * 使用邀请码
     *
     * @param code      邀请码
     * @param inviteeId 被邀请人ID
     * @return 是否使用成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean useInviteCode(String code, Long inviteeId) {
        // 验证邀请码是否有效
        TInviteCode inviteCode = validateInviteCode(code);
        if (inviteCode == null) {
            return false;
        }

        // 检查用户是否已被邀请
        LambdaQueryWrapper<TInviteRelation> checkWrapper = Wrappers.lambdaQuery();
        checkWrapper.eq(TInviteRelation::getInviteeId, inviteeId);
        if (inviteRelationMapper.selectCount(checkWrapper) > 0) {
            return false; // 用户已经被邀请过
        }

        // 创建邀请关系
        TInviteRelation relation = new TInviteRelation();
        relation.setInviterId(inviteCode.getUserId());
        relation.setInviteeId(inviteeId);
        relation.setInviteCode(code);
        relation.setInviteTime(new Date());
        inviteRelationMapper.insert(relation);

        return true;
    }

    /**
     * 构建查询条件
     *
     * @param bo 查询条件
     * @return 构建好的查询条件
     */
    private LambdaQueryWrapper<TInviteCode> buildQueryWrapper(InviteCodeBo bo) {
        LambdaQueryWrapper<TInviteCode> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getUserId() != null, TInviteCode::getUserId, bo.getUserId());
        lqw.eq(StringUtils.isNotBlank(bo.getCode()), TInviteCode::getCode, bo.getCode());
        lqw.eq(bo.getUsed() != null, TInviteCode::getUsed, bo.getUsed());
        return lqw;
    }

    /**
     * 生成唯一邀请码
     *
     * @return 唯一邀请码
     */
    private String generateUniqueCode() {
        String code;
        boolean exists;
        do {
            // 生成8位字母数字混合邀请码
            code = RandomStringUtils.randomAlphanumeric(8);

            // 检查邀请码是否已存在
            LambdaQueryWrapper<TInviteCode> checkWrapper = Wrappers.lambdaQuery();
            checkWrapper.eq(TInviteCode::getCode, code);
            exists = inviteCodeMapper.selectCount(checkWrapper) > 0;
        } while (exists);

        return code;
    }

    /**
     * 获取过期时间
     *
     * @param days 过期天数
     * @return 过期时间
     */
    private Date getExpireTime(int days) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, days);
        return calendar.getTime();
    }
} 