import { Injectable, Logger } from '@nestjs/common';
import { PrismaService } from '../../infrastructure/database/prisma.service';

/**
 * M-MEMBER-01-04: EffectiveMembershipService
 *
 * 计算所有来源（Apple/Admin/Trial/Compensation）的 Grant，
 * 合并为单一 effectivePlan。
 *
 * 首版规则：任意有效 premium grant → effectivePlan = premium，否则 free。
 * Apple expired/revoked 只影响对应 Apple grant，不触及 Admin/Trial/Compensation。
 */

export interface MembershipGrant {
  id: string;
  source: string;        // "apple" | "admin" | "trial" | "compensation"
  status: string;
  planCode: string;      // "free" | "premium"
  planName: string;
  startedAt: string;
  expiresAt: string | null;
  gracePeriodExpiresAt: string | null;
  autoRenewStatus: string | null;
  environment: string | null;
}

export interface EffectiveMembership {
  effectivePlan: 'free' | 'premium';
  grants: MembershipGrant[];
  appAccountToken: string | null;
}

@Injectable()
export class EffectiveMembershipService {
  private readonly logger = new Logger(EffectiveMembershipService.name);

  // status 值中哪些视为"当前有效"（保留权益）
  private readonly ACTIVE_STATUSES = new Set(['active', 'grace_period', 'billing_retry']);

  constructor(private readonly prisma: PrismaService) {}

  /**
   * 计算当前用户的有效会员。
   *
   * 规则：
   *   status IN ('active', 'grace_period', 'billing_retry')
   *   AND (expiresAt IS NULL OR expiresAt > NOW())
   *   → 该 Grant 视为有效
   *
   *   任意有效 premium grant 存在 → effectivePlan = premium
   *   否则 → effectivePlan = free
   *
   * billing_retry：仅在 expiresAt > NOW() 时有效（Apple 在重试期间保留权益，
   * 但如果已超过原到期日且无 Grace Period，则不应视为有效）。
   */
  async compute(userId: string): Promise<EffectiveMembership> {
    const now = new Date();

    // 查询所有 UserMembership 记录（非 soft-deleted），include plan
    const records = await this.prisma.userMembership.findMany({
      where: { userId },
      include: { plan: true },
      orderBy: { createdAt: 'desc' },
    });

    // 过滤有效 Grant
    const grants: MembershipGrant[] = [];

    for (const r of records) {
      if (!this.ACTIVE_STATUSES.has(r.status)) continue;

      // Admin 永久会员：expiresAt = null → 始终有效
      // grace_period：用 gracePeriodExpiresAt 代替 expiresAt 判断
      if (r.status === 'grace_period') {
        if (r.gracePeriodExpiresAt && r.gracePeriodExpiresAt <= now) continue;
      } else {
        const isExpired = r.expiresAt !== null && r.expiresAt <= now;
        if (isExpired) continue;
      }

      // billing_retry 额外检查：仅在有有效 Grace Period 时保留权益
      if (r.status === 'billing_retry') {
        if (r.gracePeriodExpiresAt && r.gracePeriodExpiresAt <= now) continue;
      }

      grants.push({
        id: r.id,
        source: r.source,
        status: r.status,
        planCode: r.plan.code,
        planName: r.plan.name,
        startedAt: r.startedAt.toISOString(),
        expiresAt: r.expiresAt?.toISOString() ?? null,
        gracePeriodExpiresAt: r.gracePeriodExpiresAt?.toISOString() ?? null,
        autoRenewStatus: r.autoRenewStatus,
        environment: r.environment,
      });
    }

    // 判定 effectivePlan
    const hasPremium = grants.some(g => g.planCode === 'premium');
    const effectivePlan = hasPremium ? 'premium' : 'free';

    // 获取 appAccountToken
    const user = await this.prisma.user.findUnique({
      where: { id: userId },
      select: { appAccountToken: true },
    });

    return {
      effectivePlan,
      grants,
      appAccountToken: user?.appAccountToken ?? null,
    };
  }

  /**
   * 获取当前有效 Plan 的权益摘要。
   * 从 MembershipPlan 字段读取——本阶段不接入 EffectiveQuota（由 Issue 07 实现）。
   */
  async getEntitlements(userId: string) {
    const membership = await this.compute(userId);
    const planCode = membership.effectivePlan;

    const plan = await this.prisma.membershipPlan.findUnique({
      where: { code: planCode },
    });

    if (!plan) {
      return { planCode, entitlements: null };
    }

    return {
      planCode,
      entitlements: {
        maxKnowledgeBases: plan.maxKnowledgeBases,
        maxStorageBytes: Number(plan.maxStorageBytes),
        maxFileSizeBytes: Number(plan.maxFileSizeBytes),
        monthlyOcrPages: plan.monthlyOcrPages,
        monthlyVisionPages: plan.monthlyVisionPages,
        monthlyChatCount: plan.monthlyChatCount,
        monthlyAiAnalysisCount: plan.monthlyAiAnalysisCount,
        monthlyRecallCount: plan.monthlyRecallCount,
        monthlyCardGenCount: plan.monthlyCardGenCount,
        monthlyQuizCount: plan.monthlyQuizCount,
      },
    };
  }
}
