import { describe, it, expect } from "vitest";
import {
  generateSavingsReport,
  formatSavingsPrompt,
  CLOUD_PRICING,
  LOCAL_COST_PER_M_TOKENS,
} from "@/lib/token/agents/savings-reporter";

describe("Savings Reporter", () => {
  describe("generateSavingsReport", () => {
    it("should calculate savings correctly", () => {
      const report = generateSavingsReport({
        localRequests: 1000,
        cloudRequests: 200,
        totalRequests: 1200,
        localCost: 0.5,
        cloudCost: 20.0,
        cloudEquivalentCost: 100.0,
        periodDays: 30,
      });

      expect(report.totalSaved).toBeCloseTo(99.5);
      expect(report.savingsPercentage).toBeGreaterThan(0);
      expect(report.projectedMonthlySavings).toBeGreaterThan(0);
    });

    it("should handle zero local requests", () => {
      const report = generateSavingsReport({
        localRequests: 0,
        cloudRequests: 100,
        totalRequests: 100,
        localCost: 0,
        cloudCost: 50.0,
        cloudEquivalentCost: 0,
        periodDays: 30,
      });

      expect(report.totalSaved).toBe(0);
      expect(report.recommendation).toContain("llmhosts up");
    });

    it("should recommend more local routing at low savings", () => {
      const report = generateSavingsReport({
        localRequests: 10,
        cloudRequests: 90,
        totalRequests: 100,
        localCost: 0.01,
        cloudCost: 45.0,
        cloudEquivalentCost: 5.0,
        periodDays: 30,
      });

      expect(report.recommendation).toContain("prefer_local");
    });

    it("should congratulate at high savings percentage", () => {
      const report = generateSavingsReport({
        localRequests: 950,
        cloudRequests: 50,
        totalRequests: 1000,
        localCost: 1.0,
        cloudCost: 5.0,
        cloudEquivalentCost: 200.0,
        periodDays: 30,
      });

      expect(report.recommendation).toContain("maximum value");
    });

    it("should project monthly savings", () => {
      const report = generateSavingsReport({
        localRequests: 500,
        cloudRequests: 100,
        totalRequests: 600,
        localCost: 0.25,
        cloudCost: 10.0,
        cloudEquivalentCost: 50.0,
        periodDays: 15,
      });

      // 15 days savings * 2 = monthly
      expect(report.projectedMonthlySavings).toBeCloseTo((49.75 / 15) * 30, 0);
    });

    it("should handle zero period days", () => {
      const report = generateSavingsReport({
        localRequests: 10,
        cloudRequests: 5,
        totalRequests: 15,
        localCost: 0.01,
        cloudCost: 1.0,
        cloudEquivalentCost: 2.0,
        periodDays: 0,
      });

      expect(report.projectedMonthlySavings).toBe(0);
    });

    it("should generate summary for moderate savings ($10-$100)", () => {
      const report = generateSavingsReport({
        localRequests: 500,
        cloudRequests: 100,
        totalRequests: 600,
        localCost: 0.5,
        cloudCost: 10.0,
        cloudEquivalentCost: 50.0,
        periodDays: 30,
      });

      expect(report.summary).toContain("paying for themselves");
    });

    it("should generate summary for large savings (>$100)", () => {
      const report = generateSavingsReport({
        localRequests: 5000,
        cloudRequests: 200,
        totalRequests: 5200,
        localCost: 2.0,
        cloudCost: 20.0,
        cloudEquivalentCost: 500.0,
        periodDays: 30,
      });

      expect(report.summary).toContain("less than cloud-only");
    });

    it("should generate summary for small savings (<$10)", () => {
      const report = generateSavingsReport({
        localRequests: 20,
        cloudRequests: 10,
        totalRequests: 30,
        localCost: 0.01,
        cloudCost: 1.0,
        cloudEquivalentCost: 5.0,
        periodDays: 7,
      });

      expect(report.summary).toContain("savings compound");
    });

    it("should include breakdown with request counts", () => {
      const report = generateSavingsReport({
        localRequests: 100,
        cloudRequests: 50,
        totalRequests: 150,
        localCost: 0.1,
        cloudCost: 5.0,
        cloudEquivalentCost: 10.0,
        periodDays: 7,
      });

      expect(report.breakdown).toContain("100 local");
      expect(report.breakdown).toContain("50 cloud");
      expect(report.breakdown).toContain("Period: 7 days");
    });

    it("should recommend adding GPU for mid-range savings", () => {
      // savingsPercentage = (30 - 1) / (30 + 40) * 100 = ~41%
      const report = generateSavingsReport({
        localRequests: 300,
        cloudRequests: 200,
        totalRequests: 500,
        localCost: 1.0,
        cloudCost: 40.0,
        cloudEquivalentCost: 30.0,
        periodDays: 30,
      });

      expect(report.recommendation).toContain("GPU");
    });
  });

  describe("formatSavingsPrompt", () => {
    it("should format report as prompt section", () => {
      const report = generateSavingsReport({
        localRequests: 100,
        cloudRequests: 50,
        totalRequests: 150,
        localCost: 0.1,
        cloudCost: 5.0,
        cloudEquivalentCost: 10.0,
        periodDays: 7,
      });

      const prompt = formatSavingsPrompt(report);
      expect(prompt).toContain("Savings Report");
      expect(prompt).toContain("Breakdown");
      expect(prompt).toContain("Recommendation");
    });

    it("should include projected monthly savings", () => {
      const report = generateSavingsReport({
        localRequests: 100,
        cloudRequests: 50,
        totalRequests: 150,
        localCost: 0.1,
        cloudCost: 5.0,
        cloudEquivalentCost: 10.0,
        periodDays: 7,
      });

      const prompt = formatSavingsPrompt(report);
      expect(prompt).toContain("Projected monthly savings");
    });
  });

  describe("pricing constants", () => {
    it("should have cloud pricing for major providers", () => {
      expect(CLOUD_PRICING["gpt-4o"]).toBeDefined();
      expect(CLOUD_PRICING["claude-sonnet-4-6"]).toBeDefined();
      expect(CLOUD_PRICING["gemini-2.5-flash"]).toBeDefined();
    });

    it("should have reasonable local cost estimate", () => {
      expect(LOCAL_COST_PER_M_TOKENS).toBeLessThan(1);
      expect(LOCAL_COST_PER_M_TOKENS).toBeGreaterThan(0);
    });

    it("should have input and output pricing for each model", () => {
      for (const [, pricing] of Object.entries(CLOUD_PRICING)) {
        expect(pricing.input).toBeGreaterThan(0);
        expect(pricing.output).toBeGreaterThan(0);
        expect(pricing.output).toBeGreaterThanOrEqual(pricing.input);
      }
    });
  });
});
