/**
 * Circuit breaker budget IA
 * Spec F §6 — seuil 20€/mois
 *
 * Avant chaque appel IA (worker ou chatbot) :
 *   const { blocked } = await checkBudget(config)
 *   if (blocked) throw createError({ statusCode: 503, ... })
 *
 * Paliers :
 *   >= 15€ → email Jules (géré par le worker)
 *   >= 18€ → flag budget_warning (bandeau site)
 *   >= 20€ → hard stop, HTTP 503
 */

export const BUDGET_MAX_EUR = 20
export const BUDGET_WARN_EUR = 18

export interface BudgetStatus {
  cumulEur: number
  blocked: boolean
  warning: boolean
}

/**
 * Calcule le cumul de dépenses IA du mois courant depuis stats_usage NocoDB.
 * Retourne blocked=true si le budget est atteint.
 */
export async function checkBudget(config: {
  nocodbUrl: string
  nocodbToken: string
  statsTableId: string
}): Promise<BudgetStatus> {
  const { nocodbUrl, nocodbToken, statsTableId } = config

  // Premier du mois courant à minuit UTC
  const now = new Date()
  const monthStart = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1))
  const monthStartIso = monthStart.toISOString()

  try {
    // Fetch toutes les entrées du mois courant (NocoDB v2)
    const url = `${nocodbUrl}/api/v2/tables/${statsTableId}/records`

    const res = await $fetch<{ list: { cout_eur: number | null; timestamp: string }[] }>(
      url,
      {
        headers: { 'xc-token': nocodbToken },
        query: {
          where: `(timestamp,gte,${monthStartIso})`,
          limit: 1000,
          fields: 'cout_eur,timestamp',
        },
      },
    )

    const rows = res?.list ?? []
    const cumulEur = rows.reduce((sum, row) => sum + (Number(row.cout_eur) || 0), 0)

    return {
      cumulEur,
      blocked: cumulEur >= BUDGET_MAX_EUR,
      warning: cumulEur >= BUDGET_WARN_EUR,
    }
  } catch (e) {
    // En cas d'erreur de lecture, on ne bloque PAS pour ne pas pénaliser les utilisateurs
    console.warn('[circuitBreaker] Erreur lecture stats_usage — budget non vérifié:', (e as Error).message)
    return { cumulEur: 0, blocked: false, warning: false }
  }
}

/**
 * Calcule le coût en EUR d'un appel Mistral Small.
 * Prix : $0.20/M tokens_in, $0.60/M tokens_out (converti en EUR @0.93)
 */
export function calcCoutMistralSmall(tokensIn: number, tokensOut: number): number {
  const usd = (tokensIn / 1_000_000) * 0.2 + (tokensOut / 1_000_000) * 0.6
  return usd * 0.93
}

/**
 * Calcule le coût en EUR d'un appel Mistral Nemo.
 * Prix : $0.02/M tokens_in, $0.04/M tokens_out (converti en EUR @0.93)
 */
export function calcCoutMistralNemo(tokensIn: number, tokensOut: number): number {
  const usd = (tokensIn / 1_000_000) * 0.02 + (tokensOut / 1_000_000) * 0.04
  return usd * 0.93
}
