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

export interface CostSummary {
  totalMonthly: number;
  totalYearly: number;
  totalOneTime: number;
  items: any[];
  byMonth: { month: string; total: number; items: { name: string; amount: number }[] }[];
  expiringSoon: any[];
}

@Injectable()
export class AdminCostsService {
  constructor(private readonly prisma: PrismaService) {}

  async list() {
    return this.prisma.adminCostItem.findMany({ orderBy: { createdAt: 'desc' } });
  }

  async create(data: { name: string; category: string; amount: number; currency?: string; purchaseDate: string; expiryDate?: string; billingCycle?: string; note?: string }) {
    return this.prisma.adminCostItem.create({
      data: {
        name: data.name, category: data.category || 'other', amount: data.amount,
        currency: data.currency || 'CNY', purchaseDate: new Date(data.purchaseDate),
        expiryDate: data.expiryDate ? new Date(data.expiryDate) : null,
        billingCycle: data.billingCycle || 'once', note: data.note,
      },
    });
  }

  async update(id: string, data: any) {
    return this.prisma.adminCostItem.update({ where: { id }, data });
  }

  async delete(id: string) {
    return this.prisma.adminCostItem.delete({ where: { id } });
  }

  async summary(): Promise<CostSummary> {
    const items = await this.prisma.adminCostItem.findMany({ orderBy: { purchaseDate: 'desc' } });
    const now = new Date();

    // Calculate monthly equivalent
    let totalMonthly = 0, totalYearly = 0, totalOneTime = 0;
    const byMonth: Record<string, { total: number; items: { name: string; amount: number }[] }> = {};
    const expiringSoon: any[] = [];

    for (const item of items) {
      // Monthly cost
      let monthly = 0;
      if (item.billingCycle === 'monthly') monthly = item.amount;
      else if (item.billingCycle === 'yearly') monthly = item.amount / 12;
      else totalOneTime += item.amount;

      totalMonthly += monthly;
      if (item.billingCycle === 'yearly') totalYearly += item.amount;

      // Group by purchase month
      const month = item.purchaseDate.toISOString().slice(0, 7);
      if (!byMonth[month]) byMonth[month] = { total: 0, items: [] };
      byMonth[month].total += item.amount;
      byMonth[month].items.push({ name: item.name, amount: item.amount });

      // Expiring within 30 days
      if (item.expiryDate) {
        const daysLeft = Math.ceil((new Date(item.expiryDate).getTime() - now.getTime()) / 86400000);
        if (daysLeft <= 30 && daysLeft >= 0) {
          expiringSoon.push({ ...item, daysLeft });
        }
      }
    }

    return {
      totalMonthly: Math.round(totalMonthly * 100) / 100,
      totalYearly: Math.round(totalYearly * 100) / 100,
      totalOneTime: Math.round(totalOneTime * 100) / 100,
      items,
      byMonth: Object.entries(byMonth).map(([month, data]) => ({ month, ...data })).sort((a, b) => b.month.localeCompare(a.month)),
      expiringSoon: expiringSoon.sort((a: any, b: any) => a.daysLeft - b.daysLeft),
    };
  }

  async getTopConsumers(since: Date, limit: number) {
    const top = await this.prisma.aiUsageLog.groupBy({
      by: ['userId'],
      where: { createdAt: { gte: since } },
      _sum: { estimatedCost: true, inputTokens: true, outputTokens: true },
      _count: { id: true },
      orderBy: { _sum: { estimatedCost: 'desc' } },
      take: limit,
    });
    return top.map(t => ({
      userId: t.userId,
      calls: t._count.id,
      tokens: (t._sum.inputTokens || 0) + (t._sum.outputTokens || 0),
      cost: (t._sum.estimatedCost || 0).toFixed(4),
    }));
  }
}
