package com.ai.da.service.impl;

import com.ai.da.common.config.exception.BusinessException;
import com.ai.da.common.context.UserContext;
import com.ai.da.common.response.ResultEnum;
import com.ai.da.common.utils.CopyUtil;
import com.ai.da.common.utils.RedisUtil;
import com.ai.da.mapper.primary.AccountMapper;
import com.ai.da.mapper.primary.OrganizationMapper;
import com.ai.da.mapper.primary.SubscriptionPlanMapper;
import com.ai.da.mapper.primary.entity.Account;
import com.ai.da.mapper.primary.entity.Organization;
import com.ai.da.mapper.primary.entity.SubscriptionPlan;
import com.ai.da.model.dto.AddSubAccountDTO;
import com.ai.da.model.dto.SubscriptionPlanDTO;
import com.ai.da.model.dto.SubscriptionPlanPageQuery;
import com.ai.da.model.dto.UpdateSubscriptionPlanDTO;
import com.ai.da.model.vo.SubscriptionPlanVO;
import com.ai.da.service.AccountService;
import com.ai.da.service.SubscriptionPlanService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import static com.ai.da.mapper.primary.entity.SubscriptionPlan.SubscriptionStatus.ACTIVE;
import static com.ai.da.mapper.primary.entity.SubscriptionPlan.SubscriptionStatus.PENDING;

@Slf4j
@Service
@RequiredArgsConstructor
public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMapper, SubscriptionPlan> implements SubscriptionPlanService {

    private final AccountMapper accountMapper;

    private final AccountService accountService;

    private final OrganizationMapper organizationMapper;

    private final RedisUtil redisUtil;

    // 创建
    @Override
    public void createPlan(SubscriptionPlanDTO subscriptionPlanDTO) {
        // 参数校验
        validateCreatePlanParams(subscriptionPlanDTO);

        SubscriptionPlan subscriptionPlan = CopyUtil.copyObject(subscriptionPlanDTO, SubscriptionPlan.class);
        if (StringUtils.isBlank(subscriptionPlanDTO.getStatus())) {
            subscriptionPlan.setStatus(PENDING.name());
        }
        if (Objects.isNull(subscriptionPlan.getName())) {
            subscriptionPlan.setName("DEFAULT_NAME");
        }
        subscriptionPlan.setCreditUsage(BigDecimal.ZERO);
        subscriptionPlan.setCreateTime(LocalDateTime.now());
        if (Objects.isNull(subscriptionPlanDTO.getCreditLimit())) {
            subscriptionPlan.setCreditLimit(BigDecimal.ZERO);
        }

        baseMapper.insert(subscriptionPlan);
        if (subscriptionPlanDTO.getStatus().equals(SubscriptionPlan.SubscriptionStatus.ACTIVE.name())) {
            // 执行一次激活扫描器
            activeSubscriptionPlan();
        }
    }

    private void validateCreatePlanParams(SubscriptionPlanDTO subscriptionPlanDTO) {
        // 校验组织是否存在
        Organization organization = organizationMapper.selectById(subscriptionPlanDTO.getOrganizationId());
        if (Objects.isNull(organization)) {
            throw new BusinessException("unknown.organization");
        }

        // 校验结束时间是否大于开始时间
        if (subscriptionPlanDTO.getCurrentPeriodEnd() <= subscriptionPlanDTO.getCurrentPeriodStart()) {
            throw new BusinessException("end.time.must.be.later.than.the.start.time");
        }

        // 校验管理员账号id是否存在
        Account account = accountMapper.selectById(subscriptionPlanDTO.getAdminAccId());
        if (Objects.isNull(account)) {
            throw new BusinessException("unknown.administrator.user");
        }
        if (account.getSystemUser().equals(8) || account.getSystemUser().equals(6)) {
            throw new BusinessException("Sub-accounts.cannot.be.admins");
        }
    }

    // 更新 到期时间、积分总量、已使用积分量
    @Override
    public void updatePlan(UpdateSubscriptionPlanDTO updateDTO) {
        if (Objects.isNull(updateDTO.getId())) {
            throw new BusinessException("id.cannot.be.empty");
        }

        SubscriptionPlan subscriptionPlan = baseMapper.selectById(updateDTO.getId());
        if (Objects.isNull(subscriptionPlan)) {
            throw new BusinessException("unknown.subscription.plan");
        }

        if (Objects.nonNull(updateDTO.getCurrentPeriodStart()) && !updateDTO.getCurrentPeriodStart().equals(subscriptionPlan.getCurrentPeriodStart())) {
            subscriptionPlan.setCurrentPeriodStart(updateDTO.getCurrentPeriodStart());
        }

        if (Objects.nonNull(updateDTO.getCurrentPeriodEnd()) && !updateDTO.getCurrentPeriodEnd().equals(subscriptionPlan.getCurrentPeriodEnd())) {
            subscriptionPlan.setCurrentPeriodEnd(updateDTO.getCurrentPeriodEnd());
        }

        if (Objects.nonNull(updateDTO.getAccountNum()) && !updateDTO.getAccountNum().equals(subscriptionPlan.getAccountNum())) {
            subscriptionPlan.setAccountNum(updateDTO.getAccountNum());
        }

        if (Objects.nonNull(updateDTO.getCreditLimit()) && !updateDTO.getCreditLimit().equals(subscriptionPlan.getCreditLimit())) {
            subscriptionPlan.setCreditLimit(updateDTO.getCreditLimit());
        }

        if (Objects.nonNull(updateDTO.getAdminAccId()) && !updateDTO.getAdminAccId().equals(subscriptionPlan.getAdminAccId())) {
            subscriptionPlan.setAdminAccId(updateDTO.getAdminAccId());
        }

        if (StringUtils.isNotBlank(updateDTO.getName()) && !updateDTO.getName().equals(subscriptionPlan.getName())) {
            subscriptionPlan.setName(updateDTO.getName());
        }

        subscriptionPlan.setUpdateTime(LocalDateTime.now());
        updateById(subscriptionPlan);

    }

    public void updatePlan() {


    }

    @Override
    public List<SubscriptionPlan> searchByOrganizationIdAndStatus(SubscriptionPlanPageQuery subscriptionPlanPageQuery) {
        QueryWrapper<SubscriptionPlan> queryWrapper = new QueryWrapper<>();

        queryWrapper.lambda().eq(SubscriptionPlan::getAdminAccId, UserContext.getUserHolder().getId());
        if (Objects.nonNull(subscriptionPlanPageQuery.getOrganizationId())){
            queryWrapper.lambda().eq(SubscriptionPlan::getOrganizationId, subscriptionPlanPageQuery.getOrganizationId());
        } else {
            throw new BusinessException("please.specify.the.organizationId");
        }

        if (!CollectionUtils.isEmpty(subscriptionPlanPageQuery.getStatus())) {
            queryWrapper.lambda().in(SubscriptionPlan::getStatus, subscriptionPlanPageQuery.getStatus());
        }

        return baseMapper.selectList(queryWrapper);

    }

    @Override
    public IPage<SubscriptionPlanVO> searchByPage(SubscriptionPlanPageQuery subscriptionPlanPageQuery) {
        // 1. 参数校验
        validatePageQuery(subscriptionPlanPageQuery);

        // 2. 构建查询条件（不需要包含is_deleted条件，因为SQL中已包含）
        QueryWrapper<SubscriptionPlan> queryWrapper = buildQueryWrapperWithoutDeleted(subscriptionPlanPageQuery);

        // 3. 执行自定义的分页查询
        Page<SubscriptionPlanVO> page = new Page<>(
                subscriptionPlanPageQuery.getPage(),
                subscriptionPlanPageQuery.getSize()
        );

        // 查询数据
        return baseMapper.selectWithEmailPage(page, queryWrapper);
    }

    /**
     * 构建查询条件（不包含is_deleted条件，因为SQL中已包含）
     */
    private QueryWrapper<SubscriptionPlan> buildQueryWrapperWithoutDeleted(SubscriptionPlanPageQuery query) {
        QueryWrapper<SubscriptionPlan> wrapper = new QueryWrapper<>();

        // 精确匹配条件 - 需要指定表别名
        if (query.getId() != null) {
            wrapper.eq("sp.id", query.getId());
        }
        if (query.getOrganizationId() != null) {
            wrapper.eq("sp.organization_id", query.getOrganizationId());
        }
        if (query.getAdminAccId() != null) {
            wrapper.eq("sp.admin_acc_id", query.getAdminAccId());
        }

        // 时间范围查询
        if (StringUtils.isNotBlank(query.getStartTime())) {
            LocalDateTime startTime = parseDateTime(query.getStartTime());
            wrapper.ge("sp.create_time", startTime);
        }
        if (StringUtils.isNotBlank(query.getEndTime())) {
            LocalDateTime endTime = parseDateTime(query.getEndTime());
            wrapper.le("sp.create_time", endTime);
        }

        // 状态匹配
        if (!CollectionUtils.isEmpty(query.getStatus())) {
            wrapper.in("sp.status", query.getStatus());
        }

        // 按创建时间倒序排序
        wrapper.ne("sp.is_deleted", 1)
                .orderByDesc("sp.create_time");

        return wrapper;
    }


    // 查找 根据入参提供的参数进行分页查询
   /* @Override
    public IPage<SubscriptionPlanVO> searchByPage(SubscriptionPlanPageQuery subscriptionPlanPageQuery) {
        // 1. 参数校验
        validatePageQuery(subscriptionPlanPageQuery);

        // 2. 构建查询条件
        LambdaQueryWrapper<SubscriptionPlan> queryWrapper = buildQueryWrapper(subscriptionPlanPageQuery);

        // 3. 执行分页查询
        Page<SubscriptionPlan> page = new Page<>(subscriptionPlanPageQuery.getPage(), subscriptionPlanPageQuery.getSize());
        IPage<SubscriptionPlan> resultPage = baseMapper.selectPage(page, queryWrapper);

        // 4. 转换为VO并返回
        // todo 用户邮箱
        return resultPage.convert((Function<SubscriptionPlan, SubscriptionPlanVO>) plan -> CopyUtil.copyObject(plan, SubscriptionPlanVO.class));
    }*/

    /**
     * 参数校验
     */
    private void validatePageQuery(SubscriptionPlanPageQuery query) {
        // 基本分页参数校验（JSR-303已校验，这里做额外业务校验）
        if (query.getPage() <= 0) {
            throw new BusinessException("page.num.limit");
        }
        if (query.getSize() <= 0 || query.getSize() > 100) {
            throw new BusinessException("page.size.limit");
        }

        // 时间格式校验
        if (StringUtils.isNotBlank(query.getStartTime()) && StringUtils.isNotBlank(query.getEndTime())) {
            try {
                LocalDateTime start = parseDateTime(query.getStartTime());
                LocalDateTime end = parseDateTime(query.getEndTime());
                assert start != null;
                if (start.isAfter(end)) {
                    throw new BusinessException("the.start.time.cannot.be.later.than.the.end.time");
                }
            } catch (DateTimeParseException e) {
                throw new BusinessException("invalid.time.format");
            }
        }

        if (!CollectionUtils.isEmpty(query.getStatus())) {
            for (String status : query.getStatus()) {
                try {
                    SubscriptionPlan.SubscriptionStatus.valueOf(status.toUpperCase());
                } catch (IllegalArgumentException e) {
                    log.error("未知订阅状态:{}", status);
                    throw new BusinessException("unknown.subscription.status");
                }
            }

        }
    }


    /**
     * 构建查询条件
     */
    private LambdaQueryWrapper<SubscriptionPlan> buildQueryWrapper(SubscriptionPlanPageQuery query) {
        LambdaQueryWrapper<SubscriptionPlan> wrapper = new LambdaQueryWrapper<>();

        // 精确匹配条件
        if (query.getId() != null) {
            wrapper.eq(SubscriptionPlan::getId, query.getId());
        }
        if (query.getOrganizationId() != null) {
            wrapper.eq(SubscriptionPlan::getOrganizationId, query.getOrganizationId());
        }
        if (query.getAdminAccId() != null) {
            wrapper.eq(SubscriptionPlan::getAdminAccId, query.getAdminAccId());
        }

        // 时间范围查询
        if (StringUtils.isNotBlank(query.getStartTime())) {
            LocalDateTime startTime = parseDateTime(query.getStartTime());
            wrapper.ge(SubscriptionPlan::getCreateTime, startTime);
        }
        if (StringUtils.isNotBlank(query.getEndTime())) {
            LocalDateTime endTime = parseDateTime(query.getEndTime());
            wrapper.le(SubscriptionPlan::getCreateTime, endTime);
        }

        // 状态匹配
        if (!CollectionUtils.isEmpty(query.getStatus())) {
            wrapper.in(SubscriptionPlan::getStatus, query.getStatus());
        }

        // 默认按创建时间倒序排序
        wrapper.eq(SubscriptionPlan::getIsDeleted, 0)
                .orderByDesc(SubscriptionPlan::getCreateTime);

        return wrapper;
    }

    /**
     * 时间字符串解析（支持多种格式）
     */
    private LocalDateTime parseDateTime(String timeStr) {
        if (StringUtils.isBlank(timeStr)) {
            return null;
        }

        // 尝试解析完整时间格式
        try {
            return LocalDateTime.parse(timeStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        } catch (DateTimeParseException e1) {
            // 尝试解析日期格式（自动补全时间为00:00:00）
            try {
                LocalDate date = LocalDate.parse(timeStr, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                return date.atStartOfDay();
            } catch (DateTimeParseException e2) {
                throw new DateTimeParseException("时间格式错误，请使用yyyy-MM-dd或yyyy-MM-dd HH:mm:ss格式", timeStr, 0);
            }
        }
    }

    // 删除（逻辑删除）
    @Override
    public void deletePlan(Long id) {
        Long adminAccountId = UserContext.getUserHolder().getId();
        // 1. 参数基础校验
        if (id == null || id <= 0) {
            throw new BusinessException("ID.cannot.be.empty.and.must.be.greater.than.0");
        }

        // 2. 检查数据是否存在
        SubscriptionPlan plan = baseMapper.selectById(id);
        if (plan == null) {
            throw new BusinessException("subscription.plan.does.not.exist");
        }

        // 3. 检查是否已被删除（防止重复删除） 一般情况下走不到，逻辑删除的数据通过mybatis-plus查不到
        if (plan.getIsDeleted() == 1) {
            throw new BusinessException("subscription.plan.has.been.deleted");
        }

        // 4. 检查业务约束条件（例如：是否有正在使用的订单等）
        checkBusinessConstraints(plan);

        // 5. 执行逻辑删除
        LambdaUpdateWrapper<SubscriptionPlan> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(SubscriptionPlan::getId, id)
                .set(SubscriptionPlan::getIsDeleted, 1)
                .set(SubscriptionPlan::getDeleteBy, adminAccountId);

        int rows = baseMapper.update(null, wrapper);
        if (rows == 0) {
            throw new BusinessException("deletion.failed.please.try.again.later");
        }

        // 6. 记录操作日志
        log.info("管理员{}， 删除订阅计划 {}", adminAccountId, plan);

    }

    /**
     * 检查业务约束条件
     */
    private void checkBusinessConstraints(SubscriptionPlan plan) {
        // 检查是否有活跃的用户关联
        Long activeSubAcc = countActiveSubAccByPlanId(plan.getId());
        if (activeSubAcc > 0) {
            throw new BusinessException("users.currently.using.this.plan");
        }

        // 检查是否在有效期内
        if (plan.getCurrentPeriodEnd() != null && isExpired(plan.getCurrentPeriodEnd())) {
            throw new BusinessException("valid.subscription.period");
        }
    }

    private Long countActiveSubAccByPlanId(Long planId) {
        QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Account::getSubscriptionPlanId, planId);
        return accountMapper.selectCount(queryWrapper);
    }

    // 判断是否已过期
    private boolean isExpired(Long currentPeriodEnd) {
        if (currentPeriodEnd == null) {
            return false; // 永久有效
        }
        long currentTimestamp = System.currentTimeMillis() / 1000;
        return currentPeriodEnd < currentTimestamp;
    }

    public void activeSubscriptionPlan() {
        log.info("开始执行订阅计划生效检查...");

        // 1. 扫描所有的订阅计划的开始时间currentPeriodStart，找出今天开始生效的计划
        List<SubscriptionPlan> todayActivePlans = findTodayActivePlans();

        if (CollectionUtils.isEmpty(todayActivePlans)) {
            log.info("今日没有需要生效的订阅计划");
            return;
        }

        log.info("发现{}个今日生效的订阅计划", todayActivePlans.size());

        // 2. 处理每个今天开始生效的订阅计划
        for (SubscriptionPlan plan : todayActivePlans) {
            try {
                processActiveSubscriptionPlan(plan);
                // 3. 修改订阅状态
                plan.setStatus(SubscriptionPlan.SubscriptionStatus.ACTIVE.name());
                plan.setUpdateTime(LocalDateTime.now());
                baseMapper.updateById(plan);
            } catch (Exception e) {
                log.error("处理订阅计划失败，ID: {}, 错误: {}", plan.getId(), e.getMessage(), e);
                // 继续处理其他计划，不中断整体流程
            }
        }

        log.info("订阅计划生效检查执行完成");
    }

    /**
     * 查找今天开始生效的订阅计划
     */
    private List<SubscriptionPlan> findTodayActivePlans() {
        // 获取今天的开始和结束时间戳（秒级）
        long todayStart = getTodayStartTimestamp();
        long todayEnd = getTodayEndTimestamp();

        log.debug("扫描时间范围: {} - {} (今日)", formatTimestamp(todayStart), formatTimestamp(todayEnd));

        // 查询今天开始生效的订阅计划
        QueryWrapper<SubscriptionPlan> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_deleted", 0) // 未删除
                .in("status", Arrays.asList(PENDING.name(), ACTIVE.name()))  // 还未被激活的,或者设置为激活状态但是未被实际激活的
                .between("current_period_start", todayStart, todayEnd)  // 今天开始生效
                .orderByAsc("current_period_start");  // 按开始时间排序

        return baseMapper.selectList(queryWrapper);
    }

    /**
     * 处理单个生效的订阅计划
     */
    private void processActiveSubscriptionPlan(SubscriptionPlan plan) {
        log.info("处理生效订阅计划，ID: {}, 组织ID: {}, 管理员ID: {}",
                plan.getId(), plan.getOrganizationId(), plan.getAdminAccId());

        // 获取关联的管理员账号
        Account adminAccount = accountMapper.selectById(plan.getAdminAccId());
        if (adminAccount == null) {
            log.error("管理员账号不存在，ID: {}", plan.getAdminAccId());
            return;
        }

        // 3. 检查管理员当前是否处于其他有效订阅中
        if (isAccountInActiveSubscription(adminAccount, plan.getId())) {
            log.info("管理员ID: {} 已处于有效订阅中，本次不修改账户信息", adminAccount.getId());
            return;
        }

        // 4. 更新管理员账号信息
        updateAccount(adminAccount, plan, true);

        log.info("订阅计划处理完成，ID: {}", plan.getId());
    }

    /**
     * 更新账号信息（管理员和子账号）
     */
    private void updateAccount(Account account, SubscriptionPlan plan, boolean isAdmin) {
        // 如果是管理员的切换，先再次记录一下已使用的积分
        if (isAdmin && Objects.nonNull(account.getSubscriptionPlanId())) {
            SubscriptionPlan currentPlan = baseMapper.selectById(account.getSubscriptionPlanId());
            if (currentPlan.getCreditUsage().compareTo(account.getCreditsUsage()) < 0) {
                updateSubscriptionPlanUsage(currentPlan, account.getCreditsUsage());
            }
        }
        Account updateAccount = new Account();
        updateAccount.setId(account.getId());

        // 通用更新逻辑
        updateAccount.setValidEndTime(plan.getCurrentPeriodEnd() * 1000);
        updateAccount.setSubscriptionPlanId(plan.getId());

        // 更新组织信息
        Organization organization = organizationMapper.selectById(plan.getOrganizationId());
        if (Objects.nonNull(organization)) {
            updateAccount.setOrganizationId(plan.getOrganizationId());
            updateAccount.setOrganizationName(organization.getName());
        } else {
            log.error("organization id为 {} 的组织，在表中找不到对应记录", plan.getOrganizationId());
            throw new BusinessException("unknown.organization");
        }

        // 根据用户类型设置不同的业务逻辑
        if (isAdmin) {
            updateAdminSpecificFields(updateAccount, account, plan);
        } else {
            updateSubAccountSpecificFields(updateAccount, account, plan);
        }

        // 执行更新
        int rows = accountMapper.updateById(updateAccount);
        if (rows > 0) {
            log.info("{}更新成功，ID: {}, 有效期至: {}, 用户类型: {}, 积分: {}",
                    isAdmin ? "管理员账号" : "子账号",
                    account.getId(),
                    formatTimestamp(plan.getCurrentPeriodEnd()),
                    updateAccount.getSystemUser(),
                    updateAccount.getCredits());
        } else {
            log.error("{}更新失败，ID: {}", isAdmin ? "管理员账号" : "子账号", account.getId());
        }

        // 仅子账号需要更新订阅计划的使用量
        if (!isAdmin) {
            updateSubscriptionPlanUsage(plan, plan.getCreditUsage().add(updateAccount.getCreditsUsageLimit()));
        }
    }

    /**
     * 更新管理员特有的字段
     */
    private void updateAdminSpecificFields(Account updateAccount, Account originalAccount, SubscriptionPlan plan) {
        // 保留管理员自己购买的积分
        if ((originalAccount.getSystemUser() == 5 || originalAccount.getSystemUser() == 7)
                && Objects.nonNull(originalAccount.getCreditsUsageLimit())) {
            BigDecimal leftCredits = originalAccount.getCredits()
                    .add(originalAccount.getCreditsUsage())
                    .subtract(originalAccount.getCreditsUsageLimit());

            updateAccount.setCredits(leftCredits.compareTo(BigDecimal.ZERO) > 0
                    ? plan.getCreditLimit().subtract(plan.getCreditUsage()).add(leftCredits)
                    : plan.getCreditLimit().subtract(plan.getCreditUsage()));
        } else {
            updateAccount.setCredits(plan.getCreditLimit().subtract(plan.getCreditUsage()).add(originalAccount.getCredits()));
        }

        // 设置用户类型和其他字段
        updateAccount.setSystemUser(determineSystemUserType(plan, true));
        updateAccount.setCreditsUsage(plan.getCreditUsage());
        updateAccount.setCreditsUsageLimit(plan.getCreditLimit());
        updateAccount.setSubAccountNum(plan.getAccountNum());
        updateAccount.setId(originalAccount.getId());
    }

    /**
     * 更新子账号特有的字段
     */
    private void updateSubAccountSpecificFields(Account updateAccount, Account originalAccount, SubscriptionPlan plan) {
        // 计算可分配的积分
        BigDecimal remainingCredits = plan.getCreditLimit().subtract(plan.getCreditUsage());
        BigDecimal allocatedCredits = calculateAllocatedCredits(remainingCredits);

        updateAccount.setParentId(plan.getAdminAccId());
        updateAccount.setCreditsUsageLimit(allocatedCredits);
        updateAccount.setCredits(allocatedCredits.add(originalAccount.getCredits()));
        updateAccount.setCreditsUsage(BigDecimal.ZERO);
        updateAccount.setSystemUser(determineSystemUserType(plan, false));
    }

    /**
     * 计算分配给子账号的积分
     */
    private BigDecimal calculateAllocatedCredits(BigDecimal remainingCredits) {
        if (remainingCredits.compareTo(new BigDecimal(1000)) > 0) {
            return new BigDecimal(1000);
        } else if (remainingCredits.compareTo(new BigDecimal(100)) > 0) {
            return new BigDecimal(100);
        } else if (remainingCredits.compareTo(BigDecimal.ZERO) > 0) {
            return remainingCredits;
        } else {
            return BigDecimal.ZERO;
        }
    }

    /**
     * 更新订阅计划使用量（仅子账号）
     */
    private void updateSubscriptionPlanUsage(SubscriptionPlan plan, BigDecimal newCreditsUsage) {
        plan.setCreditUsage(newCreditsUsage);
        plan.setUpdateTime(LocalDateTime.now());
        baseMapper.updateById(plan);
    }

    /**
     * 计算新的有效期结束时间
     */
    private Long calculateNewValidEndTime(Account account, SubscriptionPlan plan) {
        long now = System.currentTimeMillis() / 1000;
        Long currentValidEndTime = account.getValidEndTime();

        // 如果当前有效期晚于现在，则延长有效期
        if (currentValidEndTime != null && currentValidEndTime > now) {
            // 计算订阅的时长（秒）
            long subscriptionDuration = plan.getCurrentPeriodEnd() - plan.getCurrentPeriodStart();

            // 延长现有有效期
            return currentValidEndTime + subscriptionDuration * 1000;
        } else {
            // 否则使用订阅结束时间
            return plan.getCurrentPeriodEnd() * 1000;
        }
    }

    /**
     * 根据计划确定用户类型
     */
    private Integer determineSystemUserType(SubscriptionPlan plan, boolean isAdmin) {
        // 根据组织ID, 去organization表中查询判断是学校还是企业
        Long orgId = plan.getOrganizationId();

        Organization organization = organizationMapper.selectById(orgId);

        if (Objects.isNull(organization)) {
            log.error("未知组织id: {}", orgId);
            throw new BusinessException("unknown.organization");
        }
        if (organization.getType().equals("Enterprise") && isAdmin) {
            return 5; // 企业管理员
        } else if (organization.getType().equals("Enterprise")) {
            return 6; // 企业子账号
        } else if (organization.getType().equals("Education") && isAdmin) {
            return 7; // 学校管理员
        } else if (organization.getType().equals("Education")) {
            return 8; // 学校子账号
        } else {
            log.error("组织id未知组织类型");
            throw new BusinessException("unknown.type");
        }
    }

    /**
     * 获取今天开始的秒级时间戳
     */
    private long getTodayStartTimestamp() {
        LocalDate today = LocalDate.now();
        LocalDateTime startOfDay = today.atStartOfDay();
        return startOfDay.atZone(ZoneId.systemDefault()).toEpochSecond();
    }

    /**
     * 获取今天结束的秒级时间戳
     */
    private long getTodayEndTimestamp() {
        LocalDate today = LocalDate.now();
        LocalDateTime endOfDay = today.atTime(23, 59, 59);
        return endOfDay.atZone(ZoneId.systemDefault()).toEpochSecond();
    }

    /**
     * 格式化时间戳为可读字符串
     */
    private String formatTimestamp(Long timestamp) {
        if (timestamp == null) return "null";
        Instant instant = Instant.ofEpochSecond(timestamp);
        LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        return dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }

    /**
     * 判断管理员在当前时间是否有活跃订阅（用于新订阅激活判断）
     * 规则：只要有一个活跃订阅，就不更新管理员信息
     */
    private boolean isAccountInActiveSubscription(Account account, Long excludePlanId) {
        long now = System.currentTimeMillis() / 1000;

        QueryWrapper<SubscriptionPlan> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_deleted", 0)
                .eq("admin_acc_id", account.getId())
                .ne(excludePlanId != null, "id", excludePlanId)
                .le("current_period_start", now)  // 已开始
                .ge("current_period_end", now);   // 未结束

        Long count = baseMapper.selectCount(queryWrapper);
        return count != null && count > 0;
    }

    // 定时器清除到期订阅，查看管理员是否还有其他处于订阅中的计划并更新管理员信息
    public void expireSubscription() {
        // 1. 查询有哪些已过期订阅
        List<SubscriptionPlan> recentlyExpiredPlans = findRecentlyExpiredPlans();
        if (CollectionUtils.isEmpty(recentlyExpiredPlans)) {
            log.info("过去24h没有过期的订阅计划");
            return;
        }

        log.info("发现{}个过去24h过期的订阅计划", recentlyExpiredPlans.size());

        // 2. 更新与订阅相关账号的状态
        for (SubscriptionPlan subscriptionPlan : recentlyExpiredPlans) {
            processExpiringSubscriptionPlan(subscriptionPlan);
            // 6. 修改订阅状态
            subscriptionPlan.setStatus(SubscriptionPlan.SubscriptionStatus.EXPIRED.name());
            subscriptionPlan.setUpdateTime(LocalDateTime.now());
            baseMapper.updateById(subscriptionPlan);
        }
    }

    /**
     * 查找最近过期的订阅（过去24小时内到期的）
     */
    private List<SubscriptionPlan> findRecentlyExpiredPlans() {
        long now = System.currentTimeMillis() / 1000;
        long yesterday = now - (24 * 60 * 60); // 24小时前

        log.debug("扫描时间范围: {} - {} (过去24h)", formatTimestamp(yesterday), formatTimestamp(now));

        QueryWrapper<SubscriptionPlan> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_deleted", 0)
                .ne("status", "EXPIRED")
                .between("current_period_end", yesterday, now) // 过去24小时内到期
                .orderByAsc("current_period_end");

        return baseMapper.selectList(queryWrapper);
    }

    /**
     * 完整的订阅到期处理流程
     */
    private void processExpiringSubscriptionPlan(SubscriptionPlan plan) {
        long now = System.currentTimeMillis() / 1000;

        // 1. 检查订阅是否真的过期
        if (now <= plan.getCurrentPeriodEnd()) {
            log.info("订阅{}尚未完全过期，跳过处理", plan.getId());
            return;
        }

        // 2. 获取关联的管理员账号
        Account adminAccount = accountMapper.selectById(plan.getAdminAccId());
        if (adminAccount == null) {
            log.error("关联的管理员账号不存在，ID: {}", plan.getAdminAccId());
            return;
        }

        // 3. 检查管理员当前激活的订阅是否是这一个
        SubscriptionPlan currentActivatedPlan = getCurrentActivatedSubscription(adminAccount);
        boolean isCurrentlyActivated = currentActivatedPlan != null &&
                currentActivatedPlan.getId().equals(plan.getId());

        if (isCurrentlyActivated) {
            // 4. 管理员当前正使用这个订阅，需要处理切换或降级
            handleSubscriptionExpiration(adminAccount, plan);
        } else {
            // 5. 管理员当前未使用这个订阅，只处理订阅关系状态
            log.info("订阅{}已过期，但管理员{}未激活此订阅", plan.getId(), adminAccount.getId());
        }
        // 6. 处理该订阅下的子账号
        processChildAccountsForExpiredSubscription(plan);
    }

    /**
     * 获取管理员当前激活的订阅计划（account.subscriptionPlanId对应的）
     */
    private SubscriptionPlan getCurrentActivatedSubscription(Account account) {
        if (account.getSubscriptionPlanId() == null) {
            return null;
        }

        SubscriptionPlan plan = baseMapper.selectById(account.getSubscriptionPlanId());
        if (plan == null || plan.getIsDeleted() == 1) {
            return null;
        }

        return plan;
    }

    /**
     * 订阅到期处理逻辑（使用 getAccountActiveSubscriptions）
     */
    private void handleSubscriptionExpiration(Account adminAccount, SubscriptionPlan expiringPlan) {
        log.info("开始处理订阅{}到期，管理员ID: {}", expiringPlan.getId(), adminAccount.getId());

        // 1. 获取管理员的其他活跃订阅（排除当前到期订阅）
        List<SubscriptionPlan> otherActiveSubscriptions =
                getAccountActiveSubscriptions(adminAccount, expiringPlan.getId());

        if (!otherActiveSubscriptions.isEmpty()) {
            // 2. 有其他活跃订阅，找到开始最早的进行切换
            SubscriptionPlan earliestActivePlan = otherActiveSubscriptions.get(0); // 已按开始时间排序

            log.info("管理员{}还有其他{}个活跃订阅，切换到开始最早的订阅{}",
                    adminAccount.getId(), otherActiveSubscriptions.size(), earliestActivePlan.getId());

            // 3. 切换到开始最早的订阅
            updateAccount(adminAccount, earliestActivePlan, true);

            // 4. 修改订阅状态
            earliestActivePlan.setStatus(SubscriptionPlan.SubscriptionStatus.ACTIVE.name());
            earliestActivePlan.setUpdateTime(LocalDateTime.now());
            baseMapper.updateById(earliestActivePlan);

        } else {
            // 5. 没有其他活跃订阅，将管理员降级为游客
            log.info("管理员{}没有其他活跃订阅，降级为游客", adminAccount.getId());

//            downgradeAccountToVisitor(adminAccount);
            accountMapper.toVisitor(adminAccount.getId());
            log.info("管理员账号{}已降级为游客", adminAccount.getId());

        }
    }

    /**
     * 获取管理员当前的活跃订阅（用于订阅到期判断）
     * 返回：按开始时间排序的活跃订阅列表
     */
    private List<SubscriptionPlan> getAccountActiveSubscriptions(Account account, Long excludePlanId) {
        long now = System.currentTimeMillis() / 1000;

        QueryWrapper<SubscriptionPlan> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SubscriptionPlan::getIsDeleted, 0)
                .eq(SubscriptionPlan::getAdminAccId, account.getId())
                .ne(excludePlanId != null, SubscriptionPlan::getId, excludePlanId)
                .le(SubscriptionPlan::getCurrentPeriodStart, now)  // 已开始
                .ge(SubscriptionPlan::getCurrentPeriodEnd, now)    // 未结束
                .orderByAsc(SubscriptionPlan::getCurrentPeriodStart); // 按开始时间升序

        return baseMapper.selectList(queryWrapper);
    }

    private void processChildAccountsForExpiredSubscription(SubscriptionPlan expiredPlan) {
        log.info("开始处理过期订阅下的子账号，订阅ID: {}，组织ID: {}",
                expiredPlan.getId(), expiredPlan.getOrganizationId());

        // 1. 查找该订阅下的所有子账号
        List<Account> childAccounts = findChildAccountsBySubscription(expiredPlan);
        if (CollectionUtils.isEmpty(childAccounts)) {
            log.info("订阅{}下没有需要处理的子账号", expiredPlan.getId());
            return;
        }

        log.info("找到{}个子账号需要处理，订阅ID: {}", childAccounts.size(), expiredPlan.getId());
        for (Account account : childAccounts) {
            accountMapper.toVisitor(account.getId());
            log.info("账号{}已降级为游客", account.getId());
        }
    }

    private List<Account> findChildAccountsBySubscription(SubscriptionPlan expiredPlan) {
        QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Account::getOrganizationId, expiredPlan.getOrganizationId())
                .eq(Account::getSubscriptionPlanId, expiredPlan.getId());

        return accountMapper.selectList(queryWrapper);
    }

    /**
     * 切换订阅计划（管理员和子账号）
     * @param subscriptionPlanId 订阅计划ID
     * @param targetAccId 目标账号ID（管理员或子账号ID）
     * @param isAdmin 是否是管理员切换
     */
    public void switchSubscriptionPlan(Long subscriptionPlanId, Long targetAccId, boolean isAdmin) {
        // 1. 获取当前用户和基础数据校验
        Long currentUserId = UserContext.getUserHolder().getId();

        // 获取订阅计划
        SubscriptionPlan subscriptionPlan = baseMapper.selectById(subscriptionPlanId);
        validateSubscriptionPlan(subscriptionPlan);

        // 权限校验
        validatePermission(currentUserId, subscriptionPlan);

        // 确定目标账号ID
        Long finalTargetAccId = determineTargetAccountId(currentUserId, targetAccId, isAdmin);

        // 获取目标账号
        Account targetAccount = accountMapper.selectById(finalTargetAccId);
        if (Objects.isNull(targetAccount)) {
            throw new BusinessException(isAdmin ? "unknown.administrator.user" : "unknown.sub.account");
        }

        // 管理员权限校验
        if (isAdmin) {
            validateAdminPermission(finalTargetAccId, subscriptionPlan);
        } else {
            validateSubAccountPermission(currentUserId, subscriptionPlan, targetAccount);
        }

        // 检查是否已经是当前管理的订阅
        if (targetAccount.getSubscriptionPlanId() != null &&
                targetAccount.getSubscriptionPlanId().equals(subscriptionPlanId)) {
            log.info("用户：{} 当前正在订阅 {} 中", finalTargetAccId, subscriptionPlanId);
            return;
        }

        // 2. 执行切换操作
        if (isAdmin) {
            // 管理员直接更新
            updateAccount(targetAccount, subscriptionPlan, true);
        } else {
            // 子账号需要先从原订阅移除
            accountService.removeSubAccount(new AddSubAccountDTO(Collections.singletonList(finalTargetAccId)), currentUserId);
            updateAccount(accountMapper.selectById(finalTargetAccId), subscriptionPlan, false);
        }
    }

    /**
     * 管理员切换当前管理的订阅（保持原有接口）
     */
    public void switchSubscriptionPlan(Long subscriptionPlanId, Long adminAccId) {
        switchSubscriptionPlan(subscriptionPlanId, adminAccId, true);
    }

    /**
     * 子账号切换订阅计划（保持原有接口）
     */
    public void switchSubAccSubscriptionPlan(Long subscriptionPlanId, Long subAccId) {
        switchSubscriptionPlan(subscriptionPlanId, subAccId, false);
    }

    /**
     * 校验订阅计划
     */
    private void validateSubscriptionPlan(SubscriptionPlan subscriptionPlan) {
        if (Objects.isNull(subscriptionPlan)) {
            throw new BusinessException("unknown.subscription.plan");
        }
        long now = System.currentTimeMillis() / 1000;
        if (subscriptionPlan.getStatus().equals(SubscriptionPlan.SubscriptionStatus.EXPIRED.name())
                || subscriptionPlan.getCurrentPeriodEnd() <= now) {
            throw new BusinessException("subscription.has.expired");
        }
    }

    /**
     * 权限校验
     */
    private void validatePermission(Long userId, SubscriptionPlan subscriptionPlan) {
        // 87L是特殊权限用户
        if (!userId.equals(subscriptionPlan.getAdminAccId()) && !userId.equals(87L)) {
            throw new BusinessException("have.no.permission");
        }
    }

    /**
     * 确定目标账号ID
     */
    private Long determineTargetAccountId(Long currentUserId, Long targetAccId, boolean isAdmin) {
        // 如果是管理员切换且当前用户不是特殊权限用户，则使用当前用户ID
        if (isAdmin && !currentUserId.equals(87L)) {
            return currentUserId;
        }
        return targetAccId;
    }

    /**
     * 管理员权限校验
     */
    private void validateAdminPermission(Long adminAccId, SubscriptionPlan subscriptionPlan) {
        if (!adminAccId.equals(subscriptionPlan.getAdminAccId())) {
            log.info("用户：{} 没有权限管理订阅：{}", adminAccId, subscriptionPlan.getId());
            throw new BusinessException("no.permission.manage.subscription", ResultEnum.PROMPT.getCode());
        }
    }

    /**
     * 子账号权限校验
     */
    private void validateSubAccountPermission(Long adminAccId, SubscriptionPlan subscriptionPlan, Account subAccount) {
        // 验证管理员是否有权限
        validateAdminPermission(adminAccId, subscriptionPlan);

        Account adminAcc = accountMapper.selectById(adminAccId);
        if (!subAccount.getSubscriptionPlanId().equals(adminAcc.getSubscriptionPlanId())) {
            throw new BusinessException("switch.failed.sub-account.not.under.your.active.subscription");
        }

        // 校验子账号总数是否达上限
        QueryWrapper<Account> qw = new QueryWrapper<>();
        qw.lambda().eq(Account::getOrganizationId, subscriptionPlan.getOrganizationId())
                .eq(Account::getSubscriptionPlanId, subscriptionPlan.getId());
        List<Account> accounts = accountMapper.selectList(qw);

        if (accounts.size() >= subscriptionPlan.getAccountNum()) {

            throw new BusinessException("Error: Sub-account quota reached (Max: " +
                    adminAcc.getSubAccountNum() + "). Upgrade to create more.");
        }
    }

}
