import { BaseCommand, flags } from '@adonisjs/core/ace'
import type { CommandOptions } from '@adonisjs/core/types/ace'
import { DateTime } from 'luxon'

import User from '#models/user'
import Invoice from '#models/invoice'
import RelanceTask from '#models/relance_task'

/**
 * Programme une RelanceTask à une date arbitraire pour la démo.
 *
 *   node ace demo:schedule-relance --email arthurbarre.js@gmail.com --date 2026-05-09
 *   node ace demo:schedule-relance --email ... --date 2026-05-09 --hour 14
 *   node ace demo:schedule-relance --email ... --date 2026-05-09 --invoice F-2026-0042
 *
 * Logique :
 *  - Trouve une facture active (pending / in_relance / awaiting) avec un plan
 *  - Pioche le premier step du plan (amical en général) — sinon `--step-order N`
 *  - Crée une RelanceTask `scheduled` à la date demandée
 *
 * Utilise l'horloge virtuelle si la démo est active (compare-toi à la date
 * que tu vois sur l'horloge top-right).
 */
export default class DemoScheduleRelance extends BaseCommand {
  static commandName = 'demo:schedule-relance'
  static description = 'Programme une RelanceTask à une date arbitraire (démo)'

  static options: CommandOptions = {
    startApp: true,
  }

  @flags.string({ description: 'Email du user', required: true })
  declare email: string

  @flags.string({ description: 'Date YYYY-MM-DD', required: true })
  declare date: string

  @flags.number({ description: 'Heure d\'envoi (0-23)', default: 9 })
  declare hour: number

  @flags.string({
    description: 'Numéro de facture spécifique (sinon : 1re active trouvée)',
  })
  declare invoice?: string

  @flags.number({
    description: 'Order du step plan à utiliser (0 = premier)',
    default: 0,
  })
  declare stepOrder: number

  async run() {
    const user = await User.findBy('email', this.email.toLowerCase())
    if (!user || !user.organizationId) {
      this.logger.error(`User introuvable ou sans org : ${this.email}`)
      this.exitCode = 1
      return
    }

    let invoiceQuery = Invoice.query()
      .where('organization_id', user.organizationId)
      .preload('plan', (q) => q.preload('steps'))
      .preload('client')
      .whereIn('status', ['pending', 'in_relance', 'awaiting_user_confirmation'])
      .orderBy('due_date', 'asc')

    if (this.invoice) {
      invoiceQuery = invoiceQuery.where('numero', this.invoice)
    }

    const invoice = await invoiceQuery.first()
    if (!invoice) {
      this.logger.error(
        this.invoice
          ? `Facture ${this.invoice} non trouvée ou inactive.`
          : 'Aucune facture active (pending/in_relance/awaiting) dans cette org.'
      )
      this.exitCode = 1
      return
    }

    if (!invoice.plan?.steps?.length) {
      this.logger.error(
        `Facture ${invoice.numero} sans plan ou plan sans étapes — assignez un plan d'abord.`
      )
      this.exitCode = 1
      return
    }

    const sortedSteps = invoice.plan.steps.slice().sort((a, b) => a.order - b.order)
    const step = sortedSteps[this.stepOrder]
    if (!step) {
      this.logger.error(
        `Step order ${this.stepOrder} introuvable. Plan a ${sortedSteps.length} étape(s).`
      )
      this.exitCode = 1
      return
    }

    const sendAt = DateTime.fromISO(
      `${this.date}T${String(this.hour).padStart(2, '0')}:00:00.000`,
      { zone: 'utc' }
    )
    if (!sendAt.isValid) {
      this.logger.error(
        `Date invalide : "${this.date}" (attendu YYYY-MM-DD), heure ${this.hour}.`
      )
      this.exitCode = 1
      return
    }

    const task = await RelanceTask.create({
      organizationId: user.organizationId,
      invoiceId: invoice.id,
      planStepId: step.id,
      sendAt,
      status: 'scheduled',
      sentAt: null,
      queueJobId: null,
    })

    this.logger.success('Relance programmée pour la démo :')
    this.logger.info(`  · facture : ${invoice.numero} → ${invoice.client.name}`)
    this.logger.info(
      `  · step    : J${step.offsetDays >= 0 ? '+' : ''}${step.offsetDays} (${step.tone}) — "${step.subject}"`
    )
    this.logger.info(`  · sendAt  : ${sendAt.toFormat('cccc dd LLLL yyyy HH:mm')} UTC`)
    this.logger.info(`  · task id : ${task.id}`)
    this.logger.info('')
    this.logger.info(
      "→ En mode démo, l'horloge déclenchera l'envoi quand virtualNow ≥ sendAt."
    )
  }
}
