import { test } from '@japa/runner'
import testUtils from '@adonisjs/core/services/test_utils'
import ImportDraft from '#models/import_draft'
import { createTestUser } from '../helpers/auth.js'
import { body, type ApiOk } from '../helpers/response.js'

type DraftShape = {
  id: string
  filename: string
  status: 'pending' | 'validated' | 'skipped'
  extracted: { clientName: string; numero: string }
  edited: { clientName: string; numero: string }
}

type BatchShape = {
  id: string
  drafts: DraftShape[]
}

test.group('Imports — POST /invoices/upload (mock JSON)', (group) => {
  group.each.setup(() => testUtils.db().withGlobalTransaction())

  test('crée 1 batch + N drafts depuis filenames (mock OCR)', async ({
    client,
    assert,
  }) => {
    const { bearer } = await createTestUser()
    const r = await client
      .post('/api/v1/invoices/upload')
      .headers(bearer)
      .json({ filenames: ['facture-001.pdf', 'facture-002.pdf'] })

    r.assertStatus(201)
    const batch = body<ApiOk<BatchShape>>(r).data
    assert.lengthOf(batch.drafts, 2)
    for (const d of batch.drafts) {
      assert.equal(d.status, 'pending')
      assert.exists(d.extracted.clientName)
      assert.exists(d.extracted.numero)
    }
  })

  test('refuse > 20 fichiers (422)', async ({ client }) => {
    const { bearer } = await createTestUser()
    const filenames = Array.from({ length: 21 }, (_, i) => `f-${i}.pdf`)
    const r = await client
      .post('/api/v1/invoices/upload')
      .headers(bearer)
      .json({ filenames })
    r.assertStatus(422)
  })
})

test.group('Imports — Validate / Skip draft', (group) => {
  group.each.setup(() => testUtils.db().withGlobalTransaction())

  test('validate transforme un draft en Invoice + status=validated', async ({
    client,
    assert,
  }) => {
    const { bearer } = await createTestUser()
    const upload = await client
      .post('/api/v1/invoices/upload')
      .headers(bearer)
      .json({ filenames: ['facture-validate.pdf'] })
    const batch = body<ApiOk<BatchShape>>(upload).data
    const draft = batch.drafts[0]

    const r = await client
      .post(`/api/v1/invoices/import-batch/${batch.id}/drafts/${draft.id}/validate`)
      .headers(bearer)
      .json({
        clientId: null,
        clientName: 'Client OCR',
        clientEmail: 'ocr@spec.test',
        numero: 'F-OCR-01',
        amountTtcCents: 50000,
        issueDate: '2026-04-01T09:00:00.000Z',
        dueDate: '2026-05-01T09:00:00.000Z',
        planId: null,
      })
    r.assertStatus(201)

    const fresh = await ImportDraft.findOrFail(draft.id)
    assert.equal(fresh.status, 'validated')
    assert.isNotNull(fresh.invoiceId)
  })

  test('validate sur draft déjà processed → 409', async ({ client }) => {
    const { bearer } = await createTestUser()
    const upload = await client
      .post('/api/v1/invoices/upload')
      .headers(bearer)
      .json({ filenames: ['facture-once.pdf'] })
    const batch = body<ApiOk<BatchShape>>(upload).data
    const draft = batch.drafts[0]

    const payload = {
      clientId: null,
      clientName: 'Client',
      clientEmail: 'c@spec.test',
      numero: 'F-OCR-X',
      amountTtcCents: 10000,
      issueDate: '2026-04-01T09:00:00.000Z',
      dueDate: '2026-05-01T09:00:00.000Z',
      planId: null,
    }

    await client
      .post(`/api/v1/invoices/import-batch/${batch.id}/drafts/${draft.id}/validate`)
      .headers(bearer)
      .json(payload)

    const r2 = await client
      .post(`/api/v1/invoices/import-batch/${batch.id}/drafts/${draft.id}/validate`)
      .headers(bearer)
      .json({ ...payload, numero: 'F-OCR-Y' })

    r2.assertStatus(409)
  })

  test('skip → status=skipped, idempotent', async ({ client, assert }) => {
    const { bearer } = await createTestUser()
    const upload = await client
      .post('/api/v1/invoices/upload')
      .headers(bearer)
      .json({ filenames: ['facture-skip.pdf'] })
    const batch = body<ApiOk<BatchShape>>(upload).data
    const draft = batch.drafts[0]

    const r = await client
      .post(`/api/v1/invoices/import-batch/${batch.id}/drafts/${draft.id}/skip`)
      .headers(bearer)
    r.assertStatus(200)
    const data = body<ApiOk<DraftShape>>(r).data
    assert.equal(data.status, 'skipped')

    // Re-skip = idempotent (200 toujours)
    const again = await client
      .post(`/api/v1/invoices/import-batch/${batch.id}/drafts/${draft.id}/skip`)
      .headers(bearer)
    again.assertStatus(200)
  })

  test('DELETE /import-batch/:id supprime le batch + drafts (cascade)', async ({
    client,
    assert,
  }) => {
    const { bearer } = await createTestUser()
    const upload = await client
      .post('/api/v1/invoices/upload')
      .headers(bearer)
      .json({ filenames: ['a.pdf', 'b.pdf'] })
    const batch = body<ApiOk<BatchShape>>(upload).data

    const del = await client
      .delete(`/api/v1/invoices/import-batch/${batch.id}`)
      .headers(bearer)
    del.assertStatus(204)

    const remaining = await ImportDraft.query().where('batch_id', batch.id)
    assert.lengthOf(remaining, 0)
  })
})
