import type { PostgresJsDatabase } from 'drizzle-orm/postgres-js'
import { SettingsService } from './settings.service.js'

interface SendOpts {
  to: string
  subject: string
  html: string
  text?: string
}

interface EmailProvider {
  send(opts: SendOpts): Promise<void>
}

class ResendProvider implements EmailProvider {
  constructor(private db: PostgresJsDatabase<any>) {}

  async send(opts: SendOpts): Promise<void> {
    const apiKey = await SettingsService.get(this.db, 'email.resend_api_key')
      ?? process.env.RESEND_API_KEY
    const from = await SettingsService.get(this.db, 'email.from_address')
      ?? process.env.MAIL_FROM

    if (!apiKey) throw new Error('Resend API key not configured')
    if (!from) throw new Error('email.from_address not configured')

    const res = await fetch('https://api.resend.com/emails', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${apiKey}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        from,
        to: opts.to,
        subject: opts.subject,
        html: opts.html,
        ...(opts.text ? { text: opts.text } : {}),
      }),
    })

    if (!res.ok) {
      const body = await res.text()
      throw new Error(`Resend API error ${res.status}: ${body}`)
    }
  }
}

class SendGridProvider implements EmailProvider {
  constructor(private db: PostgresJsDatabase<any>) {}

  async send(opts: SendOpts): Promise<void> {
    const apiKey = await SettingsService.get(this.db, 'email.sendgrid_api_key')
    const from = await SettingsService.get(this.db, 'email.from_address')
      ?? process.env.MAIL_FROM

    if (!apiKey) throw new Error('SendGrid API key not configured')
    if (!from) throw new Error('email.from_address not configured')

    const res = await fetch('https://api.sendgrid.com/v3/mail/send', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${apiKey}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        personalizations: [{ to: [{ email: opts.to }] }],
        from: { email: from },
        subject: opts.subject,
        content: [
          { type: 'text/html', value: opts.html },
          ...(opts.text ? [{ type: 'text/plain', value: opts.text }] : []),
        ],
      }),
    })

    if (!res.ok) {
      const body = await res.text()
      throw new Error(`SendGrid API error ${res.status}: ${body}`)
    }
  }
}

class SmtpProvider implements EmailProvider {
  async send(_opts: SendOpts): Promise<void> {
    throw new Error('SMTP email provider is not yet implemented')
  }
}

class TestProvider implements EmailProvider {
  static lastEmail: SendOpts | null = null
  static emails: SendOpts[] = []

  async send(opts: SendOpts): Promise<void> {
    TestProvider.lastEmail = opts
    TestProvider.emails.push(opts)
  }

  static reset() {
    TestProvider.lastEmail = null
    TestProvider.emails = []
  }
}

export const EmailService = {
  async send(db: PostgresJsDatabase<any>, opts: SendOpts): Promise<void> {
    const provider = await SettingsService.get(db, 'email.provider')
      ?? process.env.MAIL_PROVIDER

    switch (provider) {
      case 'resend':
        return new ResendProvider(db).send(opts)
      case 'sendgrid':
        return new SendGridProvider(db).send(opts)
      case 'smtp':
        return new SmtpProvider().send(opts)
      case 'test':
        return new TestProvider().send(opts)
      default:
        throw new Error('Email provider not configured. Set email.provider in app_settings.')
    }
  },

  getTestEmails: () => TestProvider.emails,
  getLastTestEmail: () => TestProvider.lastEmail,
  resetTestEmails: () => TestProvider.reset(),
}
