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

import { filterProjectsByName } from '../src/parser.js'
import type { ProjectSummary } from '../src/types.js'

function makeProject(project: string, projectPath = project): ProjectSummary {
  return {
    project,
    projectPath,
    sessions: [],
    totalCostUSD: 0,
    totalApiCalls: 0,
  }
}

describe('filterProjectsByName', () => {
  const projects = [
    makeProject('codeburn', '/Users/alice/codeburn'),
    makeProject('AgentSeal', '/Users/alice/projects/AgentSeal'),
    makeProject('dashboard', '/Users/alice/AgentSeal/dashboard'),
    makeProject('sandbox', '/tmp/sandbox'),
  ]

  it('returns all projects when no filters given', () => {
    expect(filterProjectsByName(projects)).toEqual(projects)
    expect(filterProjectsByName(projects, [], [])).toEqual(projects)
    expect(filterProjectsByName(projects, undefined, undefined)).toEqual(projects)
  })

  it('include matches project name (case-insensitive substring)', () => {
    const result = filterProjectsByName(projects, ['codeburn'])
    expect(result.map(p => p.project)).toEqual(['codeburn'])
  })

  it('include is case-insensitive', () => {
    const result = filterProjectsByName(projects, ['AGENTSEAL'])
    expect(result.map(p => p.project).sort()).toEqual(['AgentSeal', 'dashboard'])
  })

  it('include matches substring in path when name does not match', () => {
    const result = filterProjectsByName(projects, ['alice/projects'])
    expect(result.map(p => p.project)).toEqual(['AgentSeal'])
  })

  it('include uses OR semantics across patterns', () => {
    const result = filterProjectsByName(projects, ['codeburn', 'sandbox'])
    expect(result.map(p => p.project).sort()).toEqual(['codeburn', 'sandbox'])
  })

  it('exclude removes matching projects (AND-negation across patterns)', () => {
    const result = filterProjectsByName(projects, undefined, ['codeburn', 'sandbox'])
    expect(result.map(p => p.project).sort()).toEqual(['AgentSeal', 'dashboard'])
  })

  it('exclude matches path substring', () => {
    const result = filterProjectsByName(projects, undefined, ['/tmp'])
    expect(result.map(p => p.project)).not.toContain('sandbox')
  })

  it('exclude is applied after include', () => {
    const result = filterProjectsByName(projects, ['AgentSeal'], ['dashboard'])
    expect(result.map(p => p.project)).toEqual(['AgentSeal'])
  })

  it('returns empty array when no project matches include', () => {
    expect(filterProjectsByName(projects, ['does-not-exist'])).toEqual([])
  })

  it('empty-string pattern matches every project', () => {
    const resultInclude = filterProjectsByName(projects, [''])
    expect(resultInclude).toHaveLength(projects.length)
    const resultExclude = filterProjectsByName(projects, undefined, [''])
    expect(resultExclude).toEqual([])
  })

  it('does not mutate the input array', () => {
    const input = [makeProject('a'), makeProject('b')]
    const snapshot = [...input]
    filterProjectsByName(input, ['a'], ['b'])
    expect(input).toEqual(snapshot)
  })
})
