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

type Kpis = {
  rubisCount: number
  rubisThisMonth: number
  encaisseCents: number
  factureToRelance: number
  factureInRelance: number
  miseEnDemeurePending: number
  monthlyGoalProgress: number
}

type ActivityEvent = { id: string; kind: string; label: string }
type LatePayer = { clientId: string; name: string; lateInvoicesCount: number }

test.group('Dashboard — GET /dashboard/kpis', (group) => {
  group.each.setup(() => testUtils.db().withGlobalTransaction())

  test('zéros sur une org vierge', async ({ client, assert }) => {
    const { bearer } = await createTestUser()
    const r = await client.get('/api/v1/dashboard/kpis').headers(bearer)
    r.assertStatus(200)

    const k = body<ApiOk<Kpis>>(r).data
    assert.equal(k.rubisCount, 0)
    assert.equal(k.rubisThisMonth, 0)
    assert.equal(k.encaisseCents, 0)
    assert.equal(k.factureToRelance, 0)
    assert.equal(k.factureInRelance, 0)
    assert.equal(k.miseEnDemeurePending, 0)
  })

  test('factureToRelance compte les pending', async ({ client, assert }) => {
    const { bearer } = await createTestUser()
    const c = await client
      .post('/api/v1/clients')
      .headers(bearer)
      .json({ name: 'Dash', email: 'dash@spec.test' })
    const cid = body<ApiOk<{ id: string }>>(c).data.id

    await client.post('/api/v1/invoices').headers(bearer).json({
      clientId: cid,
      clientName: 'Dash',
      numero: 'F-DASH-01',
      amountTtcCents: 10000,
      issueDate: '2026-04-01T09:00:00.000Z',
      dueDate: '2026-05-01T09:00:00.000Z',
    })

    const r = await client.get('/api/v1/dashboard/kpis').headers(bearer)
    assert.equal(body<ApiOk<Kpis>>(r).data.factureToRelance, 1)
  })

  test('encaisseCents et rubisCount bumpent après mark-paid', async ({
    client,
    assert,
  }) => {
    const { bearer } = await createTestUser()
    const c = await client
      .post('/api/v1/clients')
      .headers(bearer)
      .json({ name: 'Paid Spec', email: 'paid@spec.test' })
    const cid = body<ApiOk<{ id: string }>>(c).data.id

    const inv = await client.post('/api/v1/invoices').headers(bearer).json({
      clientId: cid,
      clientName: 'Paid Spec',
      numero: 'F-PAID-01',
      amountTtcCents: 250000,
      // issueDate/dueDate dans le mois courant pour rentrer dans rubisThisMonth
      issueDate: new Date().toISOString(),
      dueDate: new Date(Date.now() + 86_400_000).toISOString(),
    })
    const invId = body<ApiOk<{ id: string }>>(inv).data.id

    await client.post(`/api/v1/invoices/${invId}/mark-paid`).headers(bearer)

    const r = await client.get('/api/v1/dashboard/kpis').headers(bearer)
    const k = body<ApiOk<Kpis>>(r).data
    assert.equal(k.rubisCount, 1)
    assert.equal(k.encaisseCents, 250000)
  })
})

test.group('Dashboard — GET /dashboard/activity', (group) => {
  group.each.setup(() => testUtils.db().withGlobalTransaction())

  test('vide sur une org sans actions', async ({ client, assert }) => {
    const { bearer } = await createTestUser()
    const r = await client.get('/api/v1/dashboard/activity').headers(bearer)
    r.assertStatus(200)
    assert.deepEqual(body<ApiOk<ActivityEvent[]>>(r).data, [])
  })

  test('mark-paid logge un event invoice_paid', async ({ client, assert }) => {
    const { bearer } = await createTestUser()
    const c = await client
      .post('/api/v1/clients')
      .headers(bearer)
      .json({ name: 'Activity', email: 'activity@spec.test' })
    const cid = body<ApiOk<{ id: string }>>(c).data.id

    const inv = await client.post('/api/v1/invoices').headers(bearer).json({
      clientId: cid,
      clientName: 'Activity',
      numero: 'F-ACT-01',
      amountTtcCents: 50000,
      issueDate: '2026-04-01T09:00:00.000Z',
      dueDate: '2026-05-01T09:00:00.000Z',
    })
    const invId = body<ApiOk<{ id: string }>>(inv).data.id

    await client.post(`/api/v1/invoices/${invId}/mark-paid`).headers(bearer)

    const r = await client.get('/api/v1/dashboard/activity').headers(bearer)
    const events = body<ApiOk<ActivityEvent[]>>(r).data
    assert.isAbove(events.length, 0)
    assert.equal(events[0].kind, 'invoice_paid')
  })
})

test.group('Dashboard — GET /dashboard/top-late', (group) => {
  group.each.setup(() => testUtils.db().withGlobalTransaction())

  test('liste les clients avec factures actives en retard', async ({
    client,
    assert,
  }) => {
    const { bearer } = await createTestUser()
    const c = await client
      .post('/api/v1/clients')
      .headers(bearer)
      .json({ name: 'En Retard', email: 'late@spec.test' })
    const cid = body<ApiOk<{ id: string }>>(c).data.id

    // dueDate dans le passé → en retard
    await client.post('/api/v1/invoices').headers(bearer).json({
      clientId: cid,
      clientName: 'En Retard',
      numero: 'F-LATE-01',
      amountTtcCents: 50000,
      issueDate: '2025-12-01T09:00:00.000Z',
      dueDate: '2025-12-31T09:00:00.000Z',
    })

    const r = await client.get('/api/v1/dashboard/top-late').headers(bearer)
    r.assertStatus(200)
    const list = body<ApiOk<LatePayer[]>>(r).data
    assert.lengthOf(list, 1)
    assert.equal(list[0].name, 'En Retard')
    assert.equal(list[0].lateInvoicesCount, 1)
  })
})
