import { describe, it, expect } from 'vitest'

import { renderOverview } from '../src/overview.js'
import type { ProjectSummary } from '../src/types.js'

function makeProject(opts: {
  project: string
  projectPath: string
  cost: number
  calls: number
  model: string
  provider: string
  tokens: { input: number; output: number; cacheR: number; cacheW: number }
}): ProjectSummary {
  const usage = {
    inputTokens: opts.tokens.input,
    outputTokens: opts.tokens.output,
    cacheReadInputTokens: opts.tokens.cacheR,
    cacheCreationInputTokens: opts.tokens.cacheW,
  }
  return {
    project: opts.project,
    projectPath: opts.projectPath,
    totalCostUSD: opts.cost,
    totalSavingsUSD: 0,
    totalProxiedCostUSD: 0,
    totalApiCalls: opts.calls,
    sessions: [{
      sessionId: 's1',
      project: opts.project,
      totalInputTokens: opts.tokens.input,
      totalOutputTokens: opts.tokens.output,
      totalCacheReadTokens: opts.tokens.cacheR,
      totalCacheWriteTokens: opts.tokens.cacheW,
      apiCalls: opts.calls,
      modelBreakdown: { [opts.model]: { calls: opts.calls, costUSD: opts.cost, savingsUSD: 0, tokens: usage } },
      categoryBreakdown: { coding: { turns: 1, costUSD: opts.cost, savingsUSD: 0, retries: 0, editTurns: 1, oneShotTurns: 1 } },
      toolBreakdown: { Bash: { calls: 5 }, Read: { calls: 2 } },
      mcpBreakdown: {},
      bashBreakdown: {},
      skillBreakdown: {},
      subagentBreakdown: {},
      turns: [{
        userMessage: 'hi',
        timestamp: '2026-06-15T10:00:00Z',
        sessionId: 's1',
        category: 'coding',
        retries: 0,
        hasEdits: true,
        assistantCalls: [{ provider: opts.provider, model: opts.model, costUSD: opts.cost, usage }],
      }],
    }],
  } as unknown as ProjectSummary
}

describe('renderOverview', () => {
  it('renders the detailed sections from real aggregation', () => {
    const out = renderOverview([makeProject({
      project: 'myproject',
      projectPath: '/Users/test/myproject',
      cost: 12.5,
      calls: 3,
      model: 'claude-opus-4-8',
      provider: 'claude',
      tokens: { input: 1000, output: 200, cacheR: 5000, cacheW: 100 },
    })], { label: 'June 2026', color: false })

    for (const section of ['Totals', 'By tool', 'Top models', 'Highest-value days', 'Top projects', 'Daily', 'By activity', 'Tools']) {
      expect(out).toContain(section)
    }
    expect(out).toContain('Opus 4.8')   // model display name
    expect(out).toContain('claude')     // provider in By tool
    expect(out).toContain('myproject')  // clean project name from path basename
    expect(out).toContain('$12.50')
    expect(out).toContain('2026-06-15')
    expect(out).toContain('Coding')
    expect(out).toContain('Bash')
  })

  it('uses thousands separators and a B unit, and strips color in no-color mode', () => {
    const out = renderOverview([makeProject({
      project: 'big',
      projectPath: '/Users/test/big',
      cost: 1234.56,
      calls: 10,
      model: 'claude-opus-4-8',
      provider: 'claude',
      tokens: { input: 1_000_000, output: 1_000_000, cacheR: 2_000_000_000, cacheW: 0 },
    })], { label: 'June 2026', color: false })

    expect(out).toContain('$1,234.56')
    // tokens render as full, comma-grouped numbers (not abbreviated)
    expect(out).toContain('2,002,000,000')
    // no-color mode must not emit ANSI escape codes
    // eslint-disable-next-line no-control-regex
    expect(out).not.toMatch(/\[/)
  })

  it('reports no usage for an empty range', () => {
    const out = renderOverview([], { label: 'June 2026', color: false })
    expect(out).toContain('No usage found for June 2026')
  })

  it('does not split a slug-only Claude project path into fake path segments', () => {
    const out = renderOverview([makeProject({
      project: 'Projects-Content-OS',
      projectPath: 'Projects/Content/OS',
      cost: 3.25,
      calls: 1,
      model: 'claude-sonnet-4-5',
      provider: 'claude',
      tokens: { input: 1000, output: 200, cacheR: 0, cacheW: 0 },
    })], { label: 'June 2026', color: false })

    expect(out).toContain('Projects-Content-OS')
    expect(out).not.toContain(' OS ')
  })
})

describe('renderOverview unpriced models', () => {
  it('warns when a model with usage has no pricing data', () => {
    const out = renderOverview([makeProject({
      project: 'mystery',
      projectPath: '/Users/test/mystery',
      cost: 0,
      calls: 4,
      model: 'zz-mystery-paid-model-999',
      provider: 'claude',
      tokens: { input: 1000, output: 200, cacheR: 0, cacheW: 0 },
    })], { label: 'June 2026', color: false })

    expect(out).toContain('Unpriced')
    expect(out).toContain('1 model at $0')
    expect(out).toContain('zz-mystery-paid-model-999')
    expect(out).toContain('codeburn model-alias')
  })

  it('stays silent when every model is priced', () => {
    const out = renderOverview([makeProject({
      project: 'priced',
      projectPath: '/Users/test/priced',
      cost: 5,
      calls: 2,
      model: 'claude-opus-4-8',
      provider: 'claude',
      tokens: { input: 100, output: 50, cacheR: 0, cacheW: 0 },
    })], { label: 'June 2026', color: false })

    expect(out).not.toContain('Unpriced')
  })
})
