/**
 * Token cost analytics module.
 *
 * Aggregates spending from TokenMessage records (what Token costs via OpenRouter)
 * and CostEntry records (what the user reports paying cloud providers), then
 * computes savings estimates by comparing Token's cost against equivalent
 * cloud API pricing.
 */

import { db } from "@/lib/db";
import { logger } from "@/lib/logger";

/* ── Cloud API pricing per 1M tokens (USD) ─────────────────────────── */
const CLOUD_PRICING = {
  "gpt-4o": { input: 2.5, output: 10.0 },
  "claude-sonnet": { input: 3.0, output: 15.0 },
  "gemini-pro": { input: 1.25, output: 5.0 },
  average: { input: 2.25, output: 10.0 },
} as const;

/* ── Token spending (from TokenMessage records) ─────────────────────── */

export interface TokenSpending {
  today: number;
  thisMonth: number;
  allTime: number;
  byModel: Record<string, number>;
  byIntent: Record<string, number>;
  messageCount: number;
  budgetUsedPct: number;
  budgetRemaining: number;
}

export async function getTokenSpending(userId: string): Promise<TokenSpending> {
  const now = new Date();
  const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);

  // Get all conversations for this user to filter messages
  const conversations = await db.tokenConversation.findMany({
    where: { userId },
    select: { id: true },
  });

  const conversationIds = conversations.map((c) => c.id);

  if (conversationIds.length === 0) {
    const config = await db.tokenConfig.findUnique({ where: { id: "singleton" } });
    const budget = config?.monthlyBudgetUsd ?? 50.0;
    return {
      today: 0,
      thisMonth: 0,
      allTime: 0,
      byModel: {},
      byIntent: {},
      messageCount: 0,
      budgetUsedPct: 0,
      budgetRemaining: budget,
    };
  }

  // Fetch all assistant messages for this user (user messages have costUsd=0)
  const messages = await db.tokenMessage.findMany({
    where: {
      conversationId: { in: conversationIds },
      role: "assistant",
    },
    select: {
      costUsd: true,
      model: true,
      messageType: true,
      createdAt: true,
    },
  });

  let today = 0;
  let thisMonth = 0;
  let allTime = 0;
  const byModel: Record<string, number> = {};
  const byIntent: Record<string, number> = {};

  for (const msg of messages) {
    const cost = msg.costUsd;
    allTime += cost;

    if (msg.createdAt >= monthStart) {
      thisMonth += cost;
    }
    if (msg.createdAt >= todayStart) {
      today += cost;
    }

    const modelKey = msg.model ?? "unknown";
    byModel[modelKey] = (byModel[modelKey] ?? 0) + cost;

    const intentKey = msg.messageType ?? "chat";
    byIntent[intentKey] = (byIntent[intentKey] ?? 0) + cost;
  }

  // Load budget from config
  const config = await db.tokenConfig.findUnique({ where: { id: "singleton" } });
  const budget = config?.monthlyBudgetUsd ?? 50.0;
  const totalSpent = config?.totalSpentUsd ?? 0;

  const budgetUsedPct = budget > 0 ? (totalSpent / budget) * 100 : 0;
  const budgetRemaining = Math.max(0, budget - totalSpent);

  logger.debug(
    { action: "token_analytics_spending", user_id: userId, message_count: messages.length },
    "Token spending computed",
  );

  return {
    today: roundCents(today),
    thisMonth: roundCents(thisMonth),
    allTime: roundCents(allTime),
    byModel: roundRecord(byModel),
    byIntent: roundRecord(byIntent),
    messageCount: messages.length,
    budgetUsedPct: Math.round(budgetUsedPct * 100) / 100,
    budgetRemaining: roundCents(budgetRemaining),
  };
}

/* ── Cloud spending (from CostEntry records) ────────────────────────── */

export interface CloudSpending {
  thisMonth: number;
  lastMonth: number;
  byProvider: Record<string, number>;
  trend: "up" | "down" | "flat";
}

export async function getCloudSpending(userId: string): Promise<CloudSpending> {
  const now = new Date();
  const thisMonthPeriod = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`;

  // Compute last month period
  const lastMonthDate = new Date(now.getFullYear(), now.getMonth() - 1, 1);
  const lastMonthPeriod = `${lastMonthDate.getFullYear()}-${String(lastMonthDate.getMonth() + 1).padStart(2, "0")}`;

  const entries = await db.costEntry.findMany({
    where: {
      userId,
      period: { in: [thisMonthPeriod, lastMonthPeriod] },
    },
    select: {
      amount: true,
      provider: true,
      period: true,
    },
  });

  let thisMonth = 0;
  let lastMonth = 0;
  const byProvider: Record<string, number> = {};

  for (const entry of entries) {
    if (entry.period === thisMonthPeriod) {
      thisMonth += entry.amount;
      byProvider[entry.provider] = (byProvider[entry.provider] ?? 0) + entry.amount;
    } else if (entry.period === lastMonthPeriod) {
      lastMonth += entry.amount;
    }
  }

  let trend: "up" | "down" | "flat";
  if (lastMonth === 0 && thisMonth === 0) {
    trend = "flat";
  } else if (lastMonth === 0) {
    trend = thisMonth > 0 ? "up" : "flat";
  } else {
    const changePct = ((thisMonth - lastMonth) / lastMonth) * 100;
    if (changePct > 5) trend = "up";
    else if (changePct < -5) trend = "down";
    else trend = "flat";
  }

  logger.debug(
    { action: "token_analytics_cloud", user_id: userId, this_month: thisMonth, last_month: lastMonth },
    "Cloud spending computed",
  );

  return {
    thisMonth: roundCents(thisMonth),
    lastMonth: roundCents(lastMonth),
    byProvider: roundRecord(byProvider),
    trend,
  };
}

/* ── Savings estimate ───────────────────────────────────────────────── */

export interface SavingsEstimate {
  tokenCostUsd: number;
  equivalentCloudCost: number;
  savingsUsd: number;
  savingsPct: number;
}

export async function getSavingsEstimate(userId: string): Promise<SavingsEstimate> {
  // Get all conversations for this user
  const conversations = await db.tokenConversation.findMany({
    where: { userId },
    select: { id: true },
  });

  const conversationIds = conversations.map((c) => c.id);

  if (conversationIds.length === 0) {
    return { tokenCostUsd: 0, equivalentCloudCost: 0, savingsUsd: 0, savingsPct: 0 };
  }

  // Aggregate token counts for all assistant messages
  const messages = await db.tokenMessage.findMany({
    where: {
      conversationId: { in: conversationIds },
      role: "assistant",
    },
    select: {
      costUsd: true,
      inputTokens: true,
      outputTokens: true,
    },
  });

  let tokenCostUsd = 0;
  let totalInputTokens = 0;
  let totalOutputTokens = 0;

  for (const msg of messages) {
    tokenCostUsd += msg.costUsd;
    totalInputTokens += msg.inputTokens;
    totalOutputTokens += msg.outputTokens;
  }

  // Estimate equivalent cloud cost using average pricing
  const rate = CLOUD_PRICING.average;
  const equivalentCloudCost =
    (totalInputTokens / 1_000_000) * rate.input + (totalOutputTokens / 1_000_000) * rate.output;

  const savingsUsd = Math.max(0, equivalentCloudCost - tokenCostUsd);
  const savingsPct = equivalentCloudCost > 0 ? (savingsUsd / equivalentCloudCost) * 100 : 0;

  logger.debug(
    {
      action: "token_analytics_savings",
      user_id: userId,
      token_cost: tokenCostUsd,
      cloud_equivalent: equivalentCloudCost,
    },
    "Savings estimate computed",
  );

  return {
    tokenCostUsd: roundCents(tokenCostUsd),
    equivalentCloudCost: roundCents(equivalentCloudCost),
    savingsUsd: roundCents(savingsUsd),
    savingsPct: Math.round(savingsPct * 100) / 100,
  };
}

/* ── Format spending context for the system prompt ──────────────────── */

export function formatSpendingContext(
  tokenSpending: TokenSpending,
  cloudSpending: CloudSpending,
  savings: SavingsEstimate,
): string {
  const lines: string[] = [];

  // Token assistant spending
  lines.push("### Token Assistant Costs");
  lines.push(`- Today: $${tokenSpending.today.toFixed(4)}`);
  lines.push(`- This month: $${tokenSpending.thisMonth.toFixed(4)}`);
  lines.push(`- All time: $${tokenSpending.allTime.toFixed(4)}`);
  lines.push(`- Messages: ${tokenSpending.messageCount}`);
  lines.push(`- Budget used: ${tokenSpending.budgetUsedPct.toFixed(1)}% ($${tokenSpending.budgetRemaining.toFixed(2)} remaining)`);

  if (Object.keys(tokenSpending.byModel).length > 0) {
    lines.push("\n### Cost by Model");
    for (const [model, cost] of Object.entries(tokenSpending.byModel)) {
      lines.push(`- ${model}: $${cost.toFixed(4)}`);
    }
  }

  if (Object.keys(tokenSpending.byIntent).length > 0) {
    lines.push("\n### Cost by Intent");
    for (const [intent, cost] of Object.entries(tokenSpending.byIntent)) {
      lines.push(`- ${intent}: $${cost.toFixed(4)}`);
    }
  }

  // Cloud spending
  if (cloudSpending.thisMonth > 0 || cloudSpending.lastMonth > 0) {
    lines.push("\n### Cloud API Spending (user-reported)");
    lines.push(`- This month: $${cloudSpending.thisMonth.toFixed(2)}`);
    lines.push(`- Last month: $${cloudSpending.lastMonth.toFixed(2)}`);
    lines.push(`- Trend: ${cloudSpending.trend}`);

    if (Object.keys(cloudSpending.byProvider).length > 0) {
      for (const [provider, amount] of Object.entries(cloudSpending.byProvider)) {
        lines.push(`- ${provider}: $${amount.toFixed(2)}`);
      }
    }
  }

  // Savings
  if (savings.equivalentCloudCost > 0) {
    lines.push("\n### Savings vs Cloud APIs");
    lines.push(`- Token cost (OpenRouter): $${savings.tokenCostUsd.toFixed(4)}`);
    lines.push(`- Equivalent cloud cost: $${savings.equivalentCloudCost.toFixed(4)}`);
    lines.push(`- You saved: $${savings.savingsUsd.toFixed(4)} (${savings.savingsPct.toFixed(1)}%)`);
  }

  return lines.join("\n");
}

/* ── Helpers ─────────────────────────────────────────────────────────── */

function roundCents(n: number): number {
  return Math.round(n * 10000) / 10000;
}

function roundRecord(rec: Record<string, number>): Record<string, number> {
  const result: Record<string, number> = {};
  for (const [key, val] of Object.entries(rec)) {
    result[key] = roundCents(val);
  }
  return result;
}
