import ActivityEvent from '#models/activity_event'
import {
  computeKpis,
  computeTimeseries,
  topLatePayers,
  type RangeMonths,
} from '#services/dashboard'
import type { HttpContext } from '@adonisjs/core/http'
import { Exception } from '@adonisjs/core/exceptions'
import vine from '@vinejs/vine'

const timeseriesValidator = vine.create({
  range: vine.number().in([3, 6, 12]).optional(),
})

const ACTIVITY_DEFAULT_LIMIT = 20

function requireOrgId(auth: HttpContext['auth']): string {
  const user = auth.getUserOrFail()
  if (!user.organizationId) {
    throw new Exception('Aucune organisation rattachée', { status: 404, code: 'not_found' })
  }
  return user.organizationId
}

export default class DashboardController {
  /**
   * GET /dashboard/kpis
   *
   * Cf. service dashboard.ts — quelques metrics V1 sont placeholder
   * (miseEnDemeurePending=0 tant que RelanceTask pas branché, percentile
   * undefined tant que cohorte trop petite).
   */
  async kpis({ auth, response }: HttpContext) {
    const organizationId = requireOrgId(auth)
    const data = await computeKpis(organizationId)
    return response.json({ data })
  }

  /**
   * GET /dashboard/activity
   *
   * Journal append-only. Limit 20 par défaut, plus récent en tête.
   */
  async activity({ auth, response }: HttpContext) {
    const organizationId = requireOrgId(auth)

    const events = await ActivityEvent.query()
      .where('organization_id', organizationId)
      .orderBy('at', 'desc')
      .limit(ACTIVITY_DEFAULT_LIMIT)

    return response.json({
      data: events.map((e) => ({
        id: e.id,
        kind: e.kind,
        at: e.at.toISO()!,
        label: e.label,
        meta: e.meta,
      })),
    })
  }

  /**
   * GET /dashboard/top-late
   *
   * Top 5 clients avec le plus de factures en retard (status actif +
   * due_date dépassée).
   */
  async topLate({ auth, response }: HttpContext) {
    const organizationId = requireOrgId(auth)
    const data = await topLatePayers(organizationId)
    return response.json({ data })
  }

  /**
   * GET /dashboard/timeseries?range=6
   *
   * Séries temporelles pour les graphes (encaissé mensuel + DSO mensuel
   * + pipeline par statut). Range : 3, 6 ou 12 mois (défaut 6).
   */
  async timeseries({ auth, request, response }: HttpContext) {
    const organizationId = requireOrgId(auth)
    const { range } = await request.validateUsing(timeseriesValidator, {
      data: {
        range: request.input('range') ? Number(request.input('range')) : undefined,
      },
    })
    const data = await computeTimeseries(organizationId, (range ?? 6) as RangeMonths)
    return response.json({ data })
  }
}
