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

/**
 * M-MEMBER-01-07: EffectiveQuotaService
 *
 * 统一额度引擎。迁移三阶段：legacy → shadow → enforced。
 * 本 Issue 默认 Shadow——不改变用户结果。
 */

export interface QuotaLimit {
  quotaType: string;
  limit: number;
  unit: string;
  windowType: string; // daily | monthly | lifetime | per_request
  isUnlimited: boolean;
}

export interface EffectiveQuota {
  planCode: string;
  limits: QuotaLimit[];
  overrides: string[]; // 哪些 quota 被 Admin 覆盖
}

export interface ReservationResult {
  allowed: boolean;
  quotaType: string;
  limit: number;
  used: number;
  remaining: number;
  reservationId?: string;
}

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

  // 迁移模式（由 Feature Flag 控制）
  private mode: 'legacy' | 'shadow' | 'enforced' = 'shadow';

  constructor(
    private readonly prisma: PrismaService,
    private readonly membershipService: EffectiveMembershipService,
  ) {}

  setMode(mode: 'legacy' | 'shadow' | 'enforced') {
    this.mode = mode;
  }

  getMode() { return this.mode; }

  // ── Effective Quota ──

  async computeEffectiveQuota(userId: string): Promise<EffectiveQuota> {
    const membership = await this.membershipService.compute(userId);
    const planCode = membership.effectivePlan;

    // 从 PlanQuota 读取基础额度
    const plan = await this.prisma.membershipPlan.findUnique({
      where: { code: planCode },
      include: { planQuotas: true },
    });

    const limits: QuotaLimit[] = [];
    const overrides: string[] = [];

    if (plan?.planQuotas) {
      for (const q of plan.planQuotas) {
        limits.push({
          quotaType: q.quotaType,
          limit: q.limit,
          unit: q.unit,
          windowType: q.windowType,
          isUnlimited: q.isUnlimited,
        });
      }
    }

    // Admin Override（暂不实现——由后续 Feature Flag 控制）
    // 当前仅使用 PlanQuota 默认值

    return { planCode, limits, overrides };
  }

  // ── Reservation ──

  async reserve(
    userId: string,
    quotaType: string,
    operationId: string,
    amount: number = 1,
  ): Promise<ReservationResult> {
    // 读取限额
    const quota = await this.computeEffectiveQuota(userId);
    const limit = quota.limits.find(l => l.quotaType === quotaType);
    if (!limit) {
      return { allowed: true, quotaType, limit: -1, used: 0, remaining: -1 };
    }
    if (limit.isUnlimited) {
      return { allowed: true, quotaType, limit: -1, used: 0, remaining: -1 };
    }

    // 统计当前窗口已用量
    const used = await this.countUsedInWindow(userId, quotaType, limit.windowType);

    // Enforced 模式才真正拦截
    const allowed = this.mode === 'enforced' ? (used + amount <= limit.limit) : true;
    // N2: 非 enforced 模式下直接返回全量（无实际预占记录，used 始终为 0）
    const remaining = Math.max(0, limit.limit - used);

    // N1: findFirst + create 防并发重复预占（替代 P2002 方案）
    let reservationId: string | undefined;
    if (this.mode === 'enforced' && allowed) {
      const existing = await this.prisma.quotaUsage.findFirst({
        where: { resource: operationId },
        select: { id: true },
      });
      if (existing) {
        reservationId = existing.id;
      } else {
        try {
          const record = await this.prisma.quotaUsage.create({
            data: { userId, quotaType, amount, resource: operationId },
          });
          reservationId = record.id;
        } catch (err: any) {
          if (err?.code === 'P2002') {
            const dup = await this.prisma.quotaUsage.findUnique({
              where: { resource: operationId },
              select: { id: true },
            });
            reservationId = dup?.id;
          }
        }
      }
    }

    // Shadow 模式记录差异
    if (this.mode === 'shadow' && used + amount > limit.limit) {
      this.logger.log(
        `[Shadow] Would block: userId=${userId} quota=${quotaType} ` +
        `used=${used} limit=${limit.limit} plan=${quota.planCode}`,
      );
    }

    return {
      allowed,
      quotaType,
      limit: limit.limit,
      used,
      remaining: Math.max(0, limit.limit - used),
      reservationId,
    };
  }

  async commit(_operationId: string) {
    // Reservation 保留——记录已计入 used 统计
  }

  async release(operationId: string) {
    // 失败/取消 → 删除预占记录（释放额度）
    await this.prisma.quotaUsage.deleteMany({
      where: { resource: operationId },
    });
  }

  // ── Private ──

  private async countUsedInWindow(
    userId: string,
    quotaType: string,
    windowType: string,
  ): Promise<number> {
    const start = this.windowStart(windowType);
    const records = await this.prisma.quotaUsage.findMany({
      where: {
        userId,
        quotaType,
        resource: { not: null },  // 所有预占/已结算记录
        createdAt: { gte: start },
      },
      select: { amount: true },
    });
    return records.reduce((sum, r) => sum + r.amount, 0);
  }

  private windowStart(windowType: string): Date {
    const now = new Date();
    switch (windowType) {
      case 'daily':
        return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), -8, 0, 0)); // UTC+8
      case 'monthly':
        return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1, -8, 0, 0));
      case 'lifetime':
      default:
        return new Date(0);
    }
  }
}
