import { describe, it, expect } from 'vitest'
import { generate } from '../generate.js'
import type { ScaffoldComponentInput, PageSpecMin } from '../types.js'

/**
 * Responsive list-table contract (the "tableaux responsives + tooltip si le
 * libellé est tronqué" feature). scaffold-component must:
 *  - render <ResponsiveDataTable> (wraps the local <DataTable>) instead of <DataTable>,
 *  - keep the code + label columns ALWAYS visible (no minBreakpoint),
 *  - assign md → lg → xl to the remaining columns by declaration order,
 *  - flag every text column truncate:true,
 *  - honour BA overrides (priority:'always', explicit minBreakpoint).
 */

const I18N = {
  'list.title': 'Budgets', 'list.subtitle': 'x', 'list.create': 'x', 'list.search': 'x',
  'list.loading': 'x', 'list.empty': 'x',
  'list.columns.code': 'Code', 'list.columns.label': 'Libellé',
  'list.columns.amount': 'Montant', 'list.columns.category': 'Catégorie',
  'list.columns.region': 'Région', 'list.columns.notes': 'Notes',
}

function pageSpec(columns: PageSpecMin['columns']): PageSpecMin {
  return {
    screenCode: 'SCR-BUDGET-LIST',
    module: 'budgets',
    appCode: 'testv2',
    section: 'budgets',
    entity: 'Budget',
    view: 'list',
    filePath: 'src/pages/testv2/budgets/budgets/BudgetsListPage.tsx',
    permission: 'budgets.budgets.read',
    actions: [],
    columns,
    i18nKeys: { fr: I18N, en: I18N, it: I18N, de: I18N },
    needsRefinement: false,
    specHash: 'a'.repeat(64),
  }
}

function gen(columns: PageSpecMin['columns']): string {
  const input: ScaffoldComponentInput = {
    module: 'budgets',
    appCode: 'testv2',
    entity: 'Budget',
    section: 'budgets',
    views: ['list'],
    fields: [
      { name: 'code', type: 'string', required: true },
      { name: 'label', type: 'string', required: true },
      { name: 'amount', type: 'number', required: true },
      { name: 'category', type: 'string', required: false },
      { name: 'region', type: 'string', required: false },
      { name: 'notes', type: 'string', required: false },
    ],
    projectPath: '/web',
    pageSpec: pageSpec(columns),
  }
  const files = generate(input)
  const list = files.find((f) => /ListPage\.tsx$/.test(f.path))
  if (!list) throw new Error('no list page emitted')
  return list.content
}

/** Extracts the emitted column object literal for a given key. */
function entryFor(content: string, key: string): string {
  const re = new RegExp(`\\{ key: '${key}',[^}]*\\}`)
  const m = content.match(re)
  if (!m) throw new Error(`no column entry for key '${key}'`)
  return m[0]
}

const DEFAULT_COLUMNS: PageSpecMin['columns'] = [
  { key: 'code', labelKey: 'list.columns.code', sortable: true },
  { key: 'label', labelKey: 'list.columns.label', sortable: true },
  { key: 'amount', labelKey: 'list.columns.amount', sortable: true },
  { key: 'category', labelKey: 'list.columns.category', sortable: true },
  { key: 'region', labelKey: 'list.columns.region', sortable: true },
]

describe('scaffold-component / responsive list table — wrapper wiring', () => {
  it('renders <ResponsiveDataTable> and imports it from @/components/ui/ResponsiveDataTable', () => {
    const c = gen(DEFAULT_COLUMNS)
    expect(c).toMatch(/import \{ ResponsiveDataTable, type ResponsiveColumn \} from '@\/components\/ui\/ResponsiveDataTable'/)
    expect(c).toMatch(/<ResponsiveDataTable<Budget>/)
    expect(c).toMatch(/const columns: ResponsiveColumn<Budget>\[\] =/)
  })

  it('no longer imports or renders the raw <DataTable>', () => {
    const c = gen(DEFAULT_COLUMNS)
    expect(c).not.toMatch(/from '@\/components\/ui\/DataTable'/)
    expect(c).not.toMatch(/<DataTable</)
  })
})

describe('scaffold-component / responsive list table — default column contract', () => {
  it('keeps code + label ALWAYS visible (no minBreakpoint) and truncatable', () => {
    const c = gen(DEFAULT_COLUMNS)
    const code = entryFor(c, 'code')
    const label = entryFor(c, 'label')
    expect(code).toMatch(/truncate: true/)
    expect(code).not.toMatch(/minBreakpoint/)
    expect(label).toMatch(/truncate: true/)
    expect(label).not.toMatch(/minBreakpoint/)
  })

  it('assigns md → lg → xl to the extra columns by declaration order', () => {
    const c = gen(DEFAULT_COLUMNS)
    expect(entryFor(c, 'amount')).toMatch(/minBreakpoint: 'md'/)
    expect(entryFor(c, 'category')).toMatch(/minBreakpoint: 'lg'/)
    expect(entryFor(c, 'region')).toMatch(/minBreakpoint: 'xl'/)
  })

  it('caps further extra columns at xl (no breakpoint beyond xl)', () => {
    const c = gen([...DEFAULT_COLUMNS, { key: 'notes', labelKey: 'list.columns.notes', sortable: false }])
    expect(entryFor(c, 'region')).toMatch(/minBreakpoint: 'xl'/)
    expect(entryFor(c, 'notes')).toMatch(/minBreakpoint: 'xl'/)
  })

  it('flags every text column truncate:true (the actions column has its own render)', () => {
    const c = gen(DEFAULT_COLUMNS)
    for (const key of ['code', 'label', 'amount', 'category', 'region']) {
      expect(entryFor(c, key), key).toMatch(/truncate: true/)
    }
  })
})

describe('scaffold-component / responsive list table — BA overrides', () => {
  it('priority:"always" forces a column to stay visible (no minBreakpoint)', () => {
    const c = gen([
      { key: 'code', labelKey: 'list.columns.code', sortable: true },
      { key: 'label', labelKey: 'list.columns.label', sortable: true },
      { key: 'amount', labelKey: 'list.columns.amount', sortable: true, priority: 'always' },
      { key: 'category', labelKey: 'list.columns.category', sortable: true },
    ])
    expect(entryFor(c, 'amount')).not.toMatch(/minBreakpoint/)
    // category is then the FIRST auto-tier extra → md
    expect(entryFor(c, 'category')).toMatch(/minBreakpoint: 'md'/)
  })

  it('respects an explicit minBreakpoint override', () => {
    const c = gen([
      { key: 'code', labelKey: 'list.columns.code', sortable: true },
      { key: 'label', labelKey: 'list.columns.label', sortable: true },
      { key: 'amount', labelKey: 'list.columns.amount', sortable: true, minBreakpoint: 'xl' },
    ])
    expect(entryFor(c, 'amount')).toMatch(/minBreakpoint: 'xl'/)
  })
})

describe('scaffold-component / responsive list table — fallback identification', () => {
  it('with no code/label match, keeps the first two columns always visible', () => {
    const c = gen([
      { key: 'firstName', labelKey: 'list.columns.firstName', sortable: true },
      { key: 'lastName', labelKey: 'list.columns.lastName', sortable: true },
      { key: 'amount', labelKey: 'list.columns.amount', sortable: true },
    ])
    expect(entryFor(c, 'firstName')).not.toMatch(/minBreakpoint/)
    expect(entryFor(c, 'lastName')).not.toMatch(/minBreakpoint/)
    expect(entryFor(c, 'amount')).toMatch(/minBreakpoint: 'md'/)
  })
})
