import { describe, expect, it } from 'vitest'
import type { ObservabilityReport } from '@overdeck/report-contract'
import {
  buildReportCsv,
  buildReportJson,
  createSavedReportView,
  escapeCsvFormula,
  parseSavedReportViews,
  savedViewFilters,
} from './report-tools'

const report = {
  schemaVersion: 1,
  query: {
    from: '2026-08-16T00:00:00.000Z',
    to: '2026-08-17T00:00:00.000Z',
    timezone: 'UTC',
    projects: ['overdeck'],
    q: '=dangerous search',
  },
  generatedAt: '2026-08-17T00:00:00.000Z',
  coverage: {
    status: 'partial',
    from: '2026-08-16T00:00:00.000Z',
    to: '2026-08-17T00:00:00.000Z',
    generatedAt: '2026-08-17T00:00:00.000Z',
    sources: [],
    gaps: [{ domain: 'activity', reason: 'A source is unavailable.' }],
  },
  sections: [{
    kind: 'activity',
    status: 'complete',
    title: 'Activity and source trust',
    metrics: [],
    series: [],
    categoryBreakdown: [],
    attention: [{
      id: 'event-1',
      ts: '2026-08-16T01:00:00.000Z',
      kind: 'event',
      title: '  =SUM(A1:A2)',
      category: 'agent',
      severity: 'warn',
      actor: 'agent',
      sourceId: 'activity',
      evidenceQuery: { sourceId: 'activity', from: '2026-08-16T00:00:00.000Z', to: '2026-08-17T00:00:00.000Z' },
    }],
    sources: [],
    truncated: false,
    errors: [],
  }],
  filters: { projects: ['overdeck'], sources: [] },
} satisfies ObservabilityReport

describe('saved report views', () => {
  it('round-trips only canonical validated filter queries', () => {
    const view = createSavedReportView('view_1', ' Daily failures ', {
      range: '7d',
      projects: ['overdeck'],
      sources: [],
      severity: 'error',
      q: 'deploy',
    })
    expect(view).toEqual({ id: 'view_1', name: 'Daily failures', query: '?range=7d&project=overdeck&severity=error&q=deploy' })
    expect(savedViewFilters(view!)).toMatchObject({ range: '7d', projects: ['overdeck'], severity: 'error', q: 'deploy' })
  })

  it('drops malformed, duplicate, and noncanonical storage records', () => {
    const raw = JSON.stringify([
      { id: 'one', name: 'Good', query: '?range=7d' },
      { id: 'one', name: 'Duplicate', query: '' },
      { id: '../bad', name: 'Bad id', query: '' },
      { id: 'two', name: 'Unknown filter', query: '?invented=true' },
      { id: 'three', name: '', query: '' },
    ])
    expect(parseSavedReportViews(raw)).toEqual([{ id: 'one', name: 'Good', query: '?range=7d' }])
    expect(parseSavedReportViews('{broken')).toEqual([])
  })
})

describe('report export', () => {
  it.each(['=1+1', '+cmd', '-1', '@value', '  =SUM(A1:A2)', '\tvalue', '\rvalue'])(
    'escapes spreadsheet formula input %s',
    (value) => expect(escapeCsvFormula(value)).toBe(`'${value}`),
  )

  it('exports the selected visible table with report and coverage metadata', () => {
    const csv = buildReportCsv(report, 'attention')
    expect(csv).toContain('"Coverage","partial"')
    expect(csv).toContain('"Coverage gaps","1"')
    expect(csv).toContain('"Coverage gap 1","activity | A source is unavailable."')
    expect(csv).toContain('"Search","\'=dangerous search"')
    expect(csv).toContain('"\'  =SUM(A1:A2)"')
    expect(buildReportCsv(report, 'not-visible')).toBeUndefined()
  })

  it('exports the exact report envelope as JSON', () => {
    expect(JSON.parse(buildReportJson(report))).toEqual(report)
  })
})
