/**
 * update-snapshot — unit + writer/reader round-trip.
 *
 * The round-trip test is the important one: it proves the hashes WRITTEN by
 * update-snapshot are byte-identical to the hashes compute-page-diff READS, so
 * a snapshot taken right after a run reports every page as `unchanged`. Any
 * drift between the two scanners would surface here as false `modified`.
 */
import { mkdtempSync, mkdirSync, rmSync, writeFileSync, readFileSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
import { execute } from '../execute.js'
import { computeDiff } from '../../compute-page-diff/compute-diff.js'
import { canonicalHash } from '../../../../lib/canonical-hash.js'
import { SNAPSHOT_FILENAME } from '../../compute-page-diff/scan-pagespecs.js'

const SPEC_A = { screenCode: 'SCR-A-001', entity: 'TypeAffaire', view: 'list', columns: [{ key: 'code' }] }
const SPEC_B = { screenCode: 'SCR-B-001', entity: 'TypeAffaire', view: 'form', fields: ['code'] }

describe('update-snapshot execute', () => {
  let moduleRoot: string
  beforeEach(() => {
    moduleRoot = mkdtempSync(join(tmpdir(), 'update-snapshot-'))
    mkdirSync(join(moduleRoot, 'pagespecs'), { recursive: true })
  })
  afterEach(() => rmSync(moduleRoot, { recursive: true, force: true }))

  function writePagespec(name: string, spec: object): void {
    writeFileSync(join(moduleRoot, 'pagespecs', name), '```json\n' + JSON.stringify(spec) + '\n```\n', 'utf8')
  }

  it('writes a snapshot with the canonical hash of every pagespec', () => {
    writePagespec('TypeAffaire.list.md', SPEC_A)
    writePagespec('TypeAffaire.form.md', SPEC_B)
    const report = execute({ moduleRoot, timestamp: '2026-05-29T00:00:00Z' })

    expect(report.pageCount).toBe(2)
    expect(report.lastRun).toBe('2026-05-29T00:00:00Z')

    const written = JSON.parse(readFileSync(join(moduleRoot, SNAPSHOT_FILENAME), 'utf8'))
    expect(written.lastRun).toBe('2026-05-29T00:00:00Z')
    expect(written.pages).toEqual({
      'TypeAffaire.list': canonicalHash(SPEC_A),
      'TypeAffaire.form': canonicalHash(SPEC_B),
    })
  })

  it('round-trips: a diff taken right after update-snapshot is all-unchanged', () => {
    writePagespec('TypeAffaire.list.md', SPEC_A)
    writePagespec('TypeAffaire.form.md', SPEC_B)
    execute({ moduleRoot, timestamp: '2026-05-29T00:00:00Z' })

    const diff = computeDiff({ moduleRoot })
    expect(diff.snapshotFound).toBe(true)
    expect(diff.diff.unchanged).toEqual(['TypeAffaire.form', 'TypeAffaire.list'])
    expect(diff.toRegenerate).toEqual([])
  })

  it('overwrites a stale snapshot so a later edit reads as modified', () => {
    writePagespec('TypeAffaire.list.md', SPEC_A)
    execute({ moduleRoot, timestamp: '2026-05-29T00:00:00Z' })

    // Edit the pagespec, then diff WITHOUT re-snapshotting → modified.
    writePagespec('TypeAffaire.list.md', { ...SPEC_A, columns: [{ key: 'code' }, { key: 'libelle' }] })
    const diff = computeDiff({ moduleRoot })
    expect(diff.diff.modified.map((m) => m.key)).toEqual(['TypeAffaire.list'])

    // Re-snapshot → diff is clean again.
    execute({ moduleRoot, timestamp: '2026-05-29T01:00:00Z' })
    expect(computeDiff({ moduleRoot }).toRegenerate).toEqual([])
  })
})
