package com.gxwebsoft.common.system.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.common.core.exception.BusinessException;
import com.gxwebsoft.common.system.entity.TenantPackage;
import com.gxwebsoft.common.system.entity.TenantSubscription;
import com.gxwebsoft.common.system.mapper.TenantSubscriptionMapper;
import com.gxwebsoft.common.system.service.TenantPackageService;
import com.gxwebsoft.common.system.service.TenantSubscriptionService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * 租户订阅记录ServiceImpl
 *
 * @author WebSoft
 * @since 2025-12-12
 */
@Service
public class TenantSubscriptionServiceImpl extends ServiceImpl<TenantSubscriptionMapper, TenantSubscription> implements TenantSubscriptionService {

    @Resource
    private TenantPackageService tenantPackageService;

    @Override
    public TenantSubscription getByTenantId(Integer tenantId) {
        return baseMapper.selectByTenantIdRel(tenantId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TenantSubscription createOrUpdateSubscription(Integer tenantId, Integer packageId, Integer version,
                                                         Date startTime, Date endTime, Integer isTrial) {
        // 查询是否已存在订阅
        TenantSubscription subscription = getOne(new LambdaQueryWrapper<TenantSubscription>()
                .eq(TenantSubscription::getTenantId, tenantId));

        if (subscription == null) {
            // 创建新订阅
            subscription = new TenantSubscription();
            subscription.setTenantId(tenantId);
            subscription.setPackageId(packageId);
            subscription.setVersion(version);
            subscription.setStartTime(startTime);
            subscription.setEndTime(endTime);
            subscription.setIsTrial(isTrial);
            subscription.setIsExpired(0);
            subscription.setAutoRenewal(0);
            subscription.setNotifyStatus(0);
            subscription.setStatus(1);
            subscription.setCreateTime(new Date());
            save(subscription);
        } else {
            // 更新订阅
            subscription.setPackageId(packageId);
            subscription.setVersion(version);
            subscription.setStartTime(startTime);
            subscription.setEndTime(endTime);
            subscription.setIsTrial(isTrial);
            subscription.setIsExpired(0);
            subscription.setNotifyStatus(0);
            subscription.setUpdateTime(new Date());
            updateById(subscription);
        }

        return subscription;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean upgradeSubscription(Integer tenantId, Integer newPackageId) {
        TenantSubscription subscription = getByTenantId(tenantId);
        if (subscription == null) {
            throw new BusinessException("订阅不存在");
        }

        TenantPackage newPackage = tenantPackageService.getById(newPackageId);
        if (newPackage == null) {
            throw new BusinessException("套餐不存在");
        }

        // 检查是否是升级
        if (newPackage.getVersion() <= subscription.getVersion()) {
            throw new BusinessException("只能升级到更高版本");
        }

        subscription.setPackageId(newPackageId);
        subscription.setVersion(newPackage.getVersion());
        subscription.setUpdateTime(new Date());

        return updateById(subscription);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean renewSubscription(Integer tenantId, Integer months) {
        TenantSubscription subscription = getByTenantId(tenantId);
        if (subscription == null) {
            throw new BusinessException("订阅不存在");
        }

        // 从当前到期时间延长
        Date newEndTime = DateUtil.offsetMonth(subscription.getEndTime(), months);
        subscription.setEndTime(newEndTime);
        subscription.setIsExpired(0);
        subscription.setUpdateTime(new Date());

        return updateById(subscription);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean setAutoRenewal(Integer tenantId, Integer autoRenewal, Integer renewalPackageId) {
        TenantSubscription subscription = getByTenantId(tenantId);
        if (subscription == null) {
            throw new BusinessException("订阅不存在");
        }

        subscription.setAutoRenewal(autoRenewal);
        subscription.setRenewalPackageId(renewalPackageId);
        subscription.setUpdateTime(new Date());

        return updateById(subscription);
    }

    @Override
    public boolean isSubscriptionValid(Integer tenantId) {
        TenantSubscription subscription = getByTenantId(tenantId);
        if (subscription == null) {
            return false;
        }
        return subscription.getStatus() == 1 && subscription.getIsExpired() == 0
                && subscription.getEndTime().after(new Date());
    }

    @Override
    public boolean isSubscriptionExpired(Integer tenantId) {
        TenantSubscription subscription = getByTenantId(tenantId);
        if (subscription == null) {
            return true;
        }
        return subscription.getIsExpired() == 1 || subscription.getEndTime().before(new Date());
    }

    @Override
    public List<TenantSubscription> listExpiringSoon(Integer days) {
        return baseMapper.selectExpiringSoon(days);
    }

    @Override
    public List<TenantSubscription> listExpired() {
        return baseMapper.selectExpired();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean markAsExpired(Long subscriptionId) {
        TenantSubscription subscription = getById(subscriptionId);
        if (subscription == null) {
            return false;
        }

        subscription.setIsExpired(1);
        subscription.setUpdateTime(new Date());

        return updateById(subscription);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean sendExpiryNotification(Long subscriptionId, Integer notifyStatus) {
        TenantSubscription subscription = getById(subscriptionId);
        if (subscription == null) {
            return false;
        }

        subscription.setNotifyStatus(notifyStatus);
        subscription.setUpdateTime(new Date());

        return updateById(subscription);
    }
}
