import CheckinTask from '#models/checkin_task'
import Invoice from '#models/invoice'
import User from '#models/user'
import { sendCheckinEmail } from '#services/mail_dispatcher'
import * as clock from '#services/clock'
import env from '#start/env'
import logger from '@adonisjs/core/services/logger'

/**
 * Worker BullMQ pour la queue `checkins`.
 *
 * Idempotent : si la task n'est plus `scheduled` (déjà envoyée ou
 * expirée parce que la facture a été marquée payée entre-temps),
 * no-op.
 *
 * Le `plain` token est passé dans le payload du job (pas relu depuis
 * la DB où on n'a que le hash), pour pouvoir construire les URLs.
 */
export async function sendCheckinJob(jobData: { taskId: string; plain: string }) {
  const task = await CheckinTask.find(jobData.taskId)
  if (!task) {
    logger.warn({ taskId: jobData.taskId }, 'checkin task not found, skipping')
    return
  }
  if (task.status !== 'scheduled') {
    return
  }

  const invoice = await Invoice.query()
    .where('id', task.invoiceId)
    .preload('client')
    .first()
  if (!invoice) {
    task.status = 'expired'
    await task.save()
    return
  }

  // Si la facture a été payée/annulée entre la programmation et l'exécution,
  // on n'envoie pas le check-in (l'utilisateur sait déjà).
  if (invoice.status === 'paid' || invoice.status === 'cancelled') {
    task.status = 'expired'
    await task.save()
    return
  }

  const user = await User.query().where('organization_id', invoice.organizationId).first()
  if (!user) {
    task.status = 'expired'
    await task.save()
    return
  }

  const apiUrl = env.get('APP_URL', 'http://localhost:3333')
  const paidUrl = `${apiUrl}/api/v1/checkin/${jobData.plain}/paid`
  const pendingUrl = `${apiUrl}/api/v1/checkin/${jobData.plain}/pending`

  await sendCheckinEmail({
    invoice,
    client: invoice.client,
    user,
    paidUrl,
    pendingUrl,
  })

  const sentAt = await clock.now(invoice.organizationId)
  task.status = 'sent'
  task.sentAt = sentAt
  await task.save()

  // Bascule le statut de la facture en `awaiting_user_confirmation`. Le
  // check-in vient de partir, l'user doit répondre. C'est ce statut que
  // la modale in-app (`/api/v1/checkin/inapp/pending`) liste pour rappeler
  // à l'user qu'il y a des décisions à prendre.
  // Ne touche pas si le statut a déjà bougé entre temps (in_relance, paid,
  // litigation, etc.) — only bump from `pending`.
  if (invoice.status === 'pending') {
    invoice.status = 'awaiting_user_confirmation'
    await invoice.save()
    logger.info(
      { invoiceId: invoice.id, numero: invoice.numero },
      'sendCheckinJob: invoice status bumped pending → awaiting_user_confirmation'
    )
  }
}
