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

const QUOTA_PREFIX = 'quota:';
const RESET_DAILY = 86400;

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

  constructor(
    private readonly prisma: PrismaService,
    private readonly redis: RedisService,
  ) {}

  async getRemaining(userId: string, quotaType: string): Promise<number> {
    const planLimit = await this.getPlanLimit(userId, quotaType);
    const used = await this.getUsed(userId, quotaType);
    return Math.max(0, planLimit - used);
  }

  async checkAndDeduct(userId: string, quotaType: string, amount: number): Promise<boolean> {
    const remaining = await this.getRemaining(userId, quotaType);
    if (remaining < amount) {
      this.logger.warn(`Quota exhausted: ${userId} ${quotaType} need=${amount} have=${remaining}`);
      return false;
    }

    const key = `${QUOTA_PREFIX}${userId}:${quotaType}`;
    try {
      await this.redis.incr(key);
      await this.redis.expire(key, RESET_DAILY);
    } catch {}

    await this.prisma.quotaUsage.create({
      data: { userId, quotaType, amount, resource: quotaType },
    });

    return true;
  }

  async getUsed(userId: string, quotaType: string): Promise<number> {
    try {
      const key = `${QUOTA_PREFIX}${userId}:${quotaType}`;
      const val = await this.redis.get(key);
      if (val) return parseInt(val);
    } catch {}

    const result = await this.prisma.quotaUsage.aggregate({
      _sum: { amount: true },
      where: { userId, quotaType, createdAt: { gte: new Date(Date.now() - RESET_DAILY * 1000) } },
    });
    return result._sum.amount || 0;
  }

  private async getPlanLimit(userId: string, quotaType: string): Promise<number> {
    const membership = await this.prisma.userMembership.findFirst({
      where: { userId, active: true },
      include: { plan: true },
    });

    if (!membership?.plan) {
      // Free tier defaults
      const defaults: Record<string, number> = { ai_call: 10, ocr: 5, storage: 0, vision: 3, embedding: 50 };
      return defaults[quotaType] || 10;
    }

    const plan = membership.plan;
    const limits: Record<string, number> = {
      ai_call: plan.monthlyChatCount,
      ocr: plan.monthlyOcrPages,
      storage: Number(plan.maxStorageBytes),
      vision: plan.monthlyVisionPages,
      embedding: plan.monthlyRecallCount,
    };
    return limits[quotaType] || 10;
  }
}
