import { describe, it, expect } from "vitest";
import { buildUsageProfile, formatUsagePrompt } from "@/lib/token/profile";

describe("Usage Profile", () => {
  const makeRecord = (
    overrides: Partial<{
      model: string;
      isLocal: boolean;
      cost: number;
      tokensIn: number;
      tokensOut: number;
      timestamp: Date;
    }> = {},
  ) => ({
    model: "qwen3:14b",
    provider: "ollama",
    tokensIn: 500,
    tokensOut: 200,
    cost: 0,
    timestamp: new Date("2026-02-15T10:00:00Z"),
    isLocal: true,
    ...overrides,
  });

  describe("buildUsageProfile", () => {
    it("should return empty profile for no records", () => {
      const profile = buildUsageProfile([]);
      expect(profile.topModels).toHaveLength(0);
      expect(profile.avgDailySpend).toBe(0);
      expect(profile.localPercentage).toBe(0);
    });

    it("should calculate local percentage", () => {
      const records = [
        makeRecord({ isLocal: true }),
        makeRecord({ isLocal: true }),
        makeRecord({ isLocal: false, model: "gpt-4o", cost: 0.05 }),
      ];

      const profile = buildUsageProfile(records);
      expect(profile.localPercentage).toBeCloseTo(66.67, 0);
    });

    it("should rank models by usage count", () => {
      const records = [
        makeRecord({ model: "qwen3:14b" }),
        makeRecord({ model: "qwen3:14b" }),
        makeRecord({ model: "qwen3:14b" }),
        makeRecord({ model: "gpt-4o", isLocal: false, cost: 0.05 }),
      ];

      const profile = buildUsageProfile(records);
      expect(profile.topModels[0].model).toBe("qwen3:14b");
      expect(profile.topModels[0].count).toBe(3);
    });

    it("should calculate total tokens", () => {
      const records = [
        makeRecord({ tokensIn: 100, tokensOut: 50 }),
        makeRecord({ tokensIn: 200, tokensOut: 100 }),
      ];

      const profile = buildUsageProfile(records);
      expect(profile.totalTokens).toBe(450);
    });

    it("should detect increasing trend", () => {
      const records = [
        makeRecord({ tokensIn: 100, tokensOut: 50, timestamp: new Date("2026-02-01") }),
        makeRecord({ tokensIn: 100, tokensOut: 50, timestamp: new Date("2026-02-05") }),
        makeRecord({ tokensIn: 500, tokensOut: 300, timestamp: new Date("2026-02-20") }),
        makeRecord({ tokensIn: 600, tokensOut: 400, timestamp: new Date("2026-02-25") }),
      ];

      const profile = buildUsageProfile(records);
      expect(profile.trend).toBe("increasing");
    });

    it("should detect decreasing trend", () => {
      const records = [
        makeRecord({ tokensIn: 600, tokensOut: 400, timestamp: new Date("2026-02-01") }),
        makeRecord({ tokensIn: 500, tokensOut: 300, timestamp: new Date("2026-02-05") }),
        makeRecord({ tokensIn: 100, tokensOut: 50, timestamp: new Date("2026-02-20") }),
        makeRecord({ tokensIn: 80, tokensOut: 40, timestamp: new Date("2026-02-25") }),
      ];

      const profile = buildUsageProfile(records);
      expect(profile.trend).toBe("decreasing");
    });

    it("should identify peak hours", () => {
      const records = Array.from({ length: 10 }, (_, i) =>
        makeRecord({
          timestamp: new Date(`2026-02-15T14:${i.toString().padStart(2, "0")}:00Z`),
        }),
      );
      records.push(makeRecord({ timestamp: new Date("2026-02-15T03:00:00Z") }));

      const profile = buildUsageProfile(records);
      expect(profile.peakHours).toContain(14);
    });

    it("should estimate savings from local inference", () => {
      const records = [
        makeRecord({ isLocal: true }),
        makeRecord({ isLocal: true }),
        makeRecord({ isLocal: false, model: "gpt-4o", cost: 0.1 }),
      ];

      const profile = buildUsageProfile(records);
      expect(profile.estimatedSavings).toBeGreaterThan(0);
    });

    it("should limit top models to 5", () => {
      const records = Array.from({ length: 7 }, (_, i) =>
        makeRecord({ model: `model-${i}` }),
      );

      const profile = buildUsageProfile(records);
      expect(profile.topModels.length).toBeLessThanOrEqual(5);
    });

    it("should calculate average daily spend across unique days", () => {
      const records = [
        makeRecord({ isLocal: false, cost: 1.0, timestamp: new Date("2026-02-01T10:00:00Z") }),
        makeRecord({ isLocal: false, cost: 2.0, timestamp: new Date("2026-02-01T14:00:00Z") }),
        makeRecord({ isLocal: false, cost: 3.0, timestamp: new Date("2026-02-02T10:00:00Z") }),
      ];

      const profile = buildUsageProfile(records);
      // 6.0 total cloud cost / 2 unique days = 3.0
      expect(profile.avgDailySpend).toBe(3.0);
    });
  });

  describe("formatUsagePrompt", () => {
    it("should format empty profile", () => {
      const profile = buildUsageProfile([]);
      const prompt = formatUsagePrompt(profile);
      expect(prompt).toContain("No usage data");
    });

    it("should include key metrics", () => {
      const records = [
        makeRecord({ tokensIn: 1000, tokensOut: 500 }),
        makeRecord({ isLocal: false, model: "gpt-4o", cost: 0.05, tokensIn: 800, tokensOut: 400 }),
      ];
      const profile = buildUsageProfile(records);
      const prompt = formatUsagePrompt(profile);

      expect(prompt).toContain("Usage Profile");
      expect(prompt).toContain("tokens processed");
      expect(prompt).toContain("Local inference");
    });

    it("should include most-used models section", () => {
      const records = [
        makeRecord({ model: "qwen3:14b" }),
        makeRecord({ model: "qwen3:14b" }),
      ];
      const profile = buildUsageProfile(records);
      const prompt = formatUsagePrompt(profile);

      expect(prompt).toContain("Most-Used Models");
      expect(prompt).toContain("qwen3:14b");
    });

    it("should include usage trend", () => {
      const records = [makeRecord()];
      const profile = buildUsageProfile(records);
      const prompt = formatUsagePrompt(profile);

      expect(prompt).toContain("Usage trend:");
    });
  });
});
