import { describe, expect, it } from 'vitest'
import {
  ADI_EMAIL,
  blockerReason,
  buildTogglCsv,
  formatDurationSeconds,
  splitNaiveTimestamp,
  TOGGL_COLUMNS,
  type EligibleEntry,
} from '@/lib/toggl'

describe('formatDurationSeconds', () => {
  it('TGL-001 formats zero', () => {
    expect(formatDurationSeconds(0)).toBe('00:00:00')
  })

  it('TGL-002 handles values past one hour', () => {
    expect(formatDurationSeconds(3661)).toBe('01:01:01')
    expect(formatDurationSeconds(7200)).toBe('02:00:00')
    expect(formatDurationSeconds(90)).toBe('00:01:30')
  })
})

describe('splitNaiveTimestamp', () => {
  it('TGL-003 accepts T or space separators', () => {
    expect(splitNaiveTimestamp('2026-05-20T09:30:00')).toEqual({
      date: '2026-05-20',
      time: '09:30:00',
    })
    expect(splitNaiveTimestamp('2026-05-20 09:30:00')).toEqual({
      date: '2026-05-20',
      time: '09:30:00',
    })
  })
})

describe('buildTogglCsv', () => {
  const entry: EligibleEntry = {
    source_user_email: 'dev@example.com',
    operator: 'Bowden Works',
    client: 'DaxTech',
    project: 'Website',
    description: 'Task description',
    billable: true,
    start_at: '2026-05-20 09:00:00',
    end_at: '2026-05-20 10:30:00',
    converted_user: 'Tingang',
    converted_duration_seconds: 5400,
  }

  function lines(csv: string): string[][] {
    // papaparse unparse uses \r\n. Normalize before splitting on cells.
    return csv
      .replace(/\r\n/g, '\n')
      .trim()
      .split('\n')
      .map((l) => l.split(','))
  }

  it('TGL-004 emits no header row by default (invoicing sheet expects raw data)', () => {
    const all = lines(buildTogglCsv([entry]))
    expect(all).toHaveLength(1)
    expect(all[0][0]).toBe('Tingang') // first cell is Member, not 'Member'
  })

  it('TGL-005 puts source email in Tags column, not Member', () => {
    const [data] = lines(buildTogglCsv([entry]))
    expect(data[0]).toBe('Tingang') // Member column
    expect(data[data.length - 1]).toBe('dev@example.com') // Tags column (last)
  })

  it('TGL-006 always sets Email to Adi', () => {
    const [data] = lines(buildTogglCsv([entry]))
    expect(data[1]).toBe(ADI_EMAIL)
  })

  it('TGL-015 header row can be re-enabled via option (and matches TOGGL_COLUMNS)', () => {
    const [header] = lines(buildTogglCsv([entry], { header: true }))
    expect(header).toEqual(TOGGL_COLUMNS)
  })

  it('TGL-016 teams option populates column G (7th column)', () => {
    const [data] = lines(buildTogglCsv([entry], { teams: '2026-04' }))
    expect(data[6]).toBe('2026-04') // Teams column = column G
  })

  it('TGL-017 teams defaults to "-" placeholder when omitted or empty', () => {
    const [defaultRow] = lines(buildTogglCsv([entry]))
    expect(defaultRow[6]).toBe('-')
    const [emptyRow] = lines(buildTogglCsv([entry], { teams: '   ' }))
    expect(emptyRow[6]).toBe('-')
  })
})

describe('blockerReason', () => {
  // Post invoice migration: converted_* fields are no longer required
  // for invoice eligibility (they're Toggl-export plumbing only).
  const eligible = {
    team_member_id: 'tm-1',
    operator: 'Bowden Works',
    client: 'DaxTech',
    project: 'Website',
    description: 'd',
    start_at: '2026-05-20 09:00:00',
    end_at: '2026-05-20 10:00:00',
    source_user_email: 'dev@example.com',
  }

  it('TGL-009 flags missing team_member_id', () => {
    expect(
      blockerReason({ ...eligible, team_member_id: null }),
    ).toMatch(/team member/i)
  })

  it('TGL-011 flags any missing required field', () => {
    expect(blockerReason({ ...eligible, operator: null })).toMatch(/operator/i)
    expect(blockerReason({ ...eligible, client: null })).toMatch(/client/i)
    expect(blockerReason({ ...eligible, project: null })).toMatch(/project/i)
    expect(blockerReason({ ...eligible, description: null })).toMatch(
      /description/i,
    )
    expect(blockerReason({ ...eligible, end_at: null })).toMatch(/end/i)
    expect(
      blockerReason({ ...eligible, source_user_email: null }),
    ).toMatch(/source/i)
  })

  it('TGL-012 returns null for a fully-resolved entry', () => {
    expect(blockerReason(eligible)).toBeNull()
  })
})

describe('Toggl CSV recombines client + project', () => {
  it('TGL-013 Project column becomes "{client} : {project}" with spaces around colon', () => {
    const csv = buildTogglCsv([
      {
        source_user_email: 'dev@example.com',
        operator: 'Bowden Works',
        client: 'DaxTech',
        project: 'Website',
        description: 'd',
        billable: true,
        start_at: '2026-05-20 09:00:00',
        end_at: '2026-05-20 10:30:00',
        converted_user: 'Tingang',
        converted_duration_seconds: 3600,
      },
    ])
    const lines = csv
      .replace(/\r\n/g, '\n')
      .trim()
      .split('\n')
      .map((l) => l.split(','))
    expect(lines[0][2]).toBe('Bowden Works') // Client column = operator
    expect(lines[0][3]).toBe('DaxTech : Website') // Project column = recombined
  })

  it('TGL-014 if client is null, Project column shows just the project name', () => {
    const csv = buildTogglCsv([
      {
        source_user_email: 'dev@example.com',
        operator: 'Bowden Works',
        client: null,
        project: 'Standalone',
        description: 'd',
        billable: true,
        start_at: '2026-05-20 09:00:00',
        end_at: '2026-05-20 10:30:00',
        converted_user: 'Tingang',
        converted_duration_seconds: 3600,
      },
    ])
    const lines = csv
      .replace(/\r\n/g, '\n')
      .trim()
      .split('\n')
      .map((l) => l.split(','))
    expect(lines[0][3]).toBe('Standalone')
  })
})
