import mail from '@adonisjs/mail/services/main'
import env from '#start/env'
import { DateTime } from 'luxon'
import { renderTemplate, formatAmountFr, formatDateFr } from '#services/template'
import type Invoice from '#models/invoice'
import type Client from '#models/client'
import type PlanStep from '#models/plan_step'
import type User from '#models/user'
import type Organization from '#models/organization'

type RelancePayload = {
  invoice: Invoice
  client: Client
  step: PlanStep
  user: User | null
  organization?: Organization | null
}

/**
 * Construit l'objet `vars` interpolé dans subject/body. Exposé pour
 * permettre la preview côté contrôleur (wizard de création de plan)
 * avec les mêmes variables que ce qui sera réellement envoyé.
 *
 * Variables disponibles :
 *  - {{client.name}}, {{client.email}}
 *  - {{client.contactFirstName}}, {{client.contactLastName}} (peuvent être vides)
 *  - {{numero}}, {{amount}}, {{dueDate}}, {{issueDate}}
 *  - {{daysLate}}  (jours de retard depuis dueDate, négatif = avant échéance)
 *  - {{user.fullName}}, {{user.companyName}}
 *  - {{signature}}
 */
export function buildRelanceVars({
  invoice,
  client,
  user,
  organization,
}: {
  invoice: Pick<Invoice, 'numero' | 'amountTtcCents' | 'dueDate' | 'issueDate'>
  client: Pick<Client, 'name' | 'email' | 'contactFirstName' | 'contactLastName'>
  user: Pick<User, 'fullName' | 'signature' | 'email'> | null
  organization?: Pick<Organization, 'name'> | null
}) {
  const dueDate = invoice.dueDate.toJSDate()
  // Jours de retard arrondis à l'entier (UTC pour cohérence).
  const daysLate = Math.floor(
    DateTime.utc().startOf('day').diff(invoice.dueDate.startOf('day'), 'days').days
  )
  return {
    client: {
      name: client.name,
      email: client.email,
      contactFirstName: client.contactFirstName ?? '',
      contactLastName: client.contactLastName ?? '',
    },
    user: {
      fullName: user?.fullName ?? '',
      companyName: organization?.name ?? '',
    },
    numero: invoice.numero,
    amount: formatAmountFr(invoice.amountTtcCents),
    dueDate: formatDateFr(dueDate),
    issueDate: formatDateFr(invoice.issueDate.toJSDate()),
    daysLate: String(daysLate),
    signature: user?.signature ?? user?.fullName ?? '',
  }
}

/**
 * Envoie un email de relance à un client à partir d'un step.
 * Le subject/body du step contiennent des placeholders Mustache-like
 * qu'on interpole avant l'envoi (cf. `buildRelanceVars`).
 *
 * Le mailer effectif est piloté par MAIL_DRIVER (`smtp` Mailpit en dev,
 * `resend` en prod).
 */
export async function sendRelanceEmail({
  invoice,
  client,
  step,
  user,
  organization,
}: RelancePayload) {
  const vars = buildRelanceVars({ invoice, client, user, organization })

  const subject = renderTemplate(step.subject, vars)
  const body = renderTemplate(step.body, vars)

  const mailer = mail.use(env.get('MAIL_DRIVER', 'smtp'))
  await mailer.send((m) => {
    m.from(env.get('MAIL_FROM_ADDRESS', 'relances@rubis-sur-l-ongle.fr'), env.get('MAIL_FROM_NAME', "Rubis Sur l'Ongle"))
      .to(client.email, client.name)
      .subject(subject)
      // Texte brut pour V1 — on ajoutera un template HTML quand on aura
      // décidé d'un look graphique pour les relances.
      .text(body)
    // Reply-To pointe sur l'utilisateur Rubis : si le client final répond
    // à la relance, sa réponse arrive chez le patron de la TPE, pas dans
    // notre boîte transactionnelle.
    if (user?.email) {
      m.replyTo(user.email, user.fullName ?? user.email)
    }
  })
}

type CheckinPayload = {
  invoice: Invoice
  client: Client
  user: User
  paidUrl: string
  pendingUrl: string
}

/**
 * Envoie le check-in à l'**utilisateur** (pas au client). Lui demande
 * si la facture a été payée, avec 2 liens publics qui modifient l'état
 * côté API et redirigent ensuite vers le SPA.
 *
 * Texte brut V1. Un template HTML viendra quand on aura figé le look
 * graphique (cf. ADR-021).
 */
export async function sendCheckinEmail({
  invoice,
  client,
  user,
  paidUrl,
  pendingUrl,
}: CheckinPayload) {
  const subject = `Facture ${invoice.numero} — payée par ${client.name} ?`
  const body = `Bonjour ${user.fullName ?? ''},

La facture ${invoice.numero} (${formatAmountFr(invoice.amountTtcCents)}) émise pour ${client.name}
arrive à échéance aujourd'hui (${formatDateFr(invoice.dueDate.toJSDate())}).

Avant que Rubis n'envoie la première relance, dites-nous où vous en êtes :

✓  J'ai été payé(e), pas besoin de relancer :
   ${paidUrl}

→  Toujours en attente, lance la relance comme prévu :
   ${pendingUrl}

Ces liens expirent dans 24h.

Merci,
L'équipe Rubis`

  const mailer = mail.use(env.get('MAIL_DRIVER', 'smtp'))
  await mailer.send((m) => {
    m.from(env.get('MAIL_FROM_ADDRESS', 'relances@rubis-sur-l-ongle.fr'), env.get('MAIL_FROM_NAME', "Rubis Sur l'Ongle"))
      .to(user.email, user.fullName ?? user.email)
      .subject(subject)
      .text(body)
  })
}
