process.env.SECRET_ENC_KEY = process.env.SECRET_ENC_KEY || 'unit-test-enc-key'
process.env.DB_HOST = '127.0.0.1'
process.env.DB_PORT = '59999'

const { test, after, beforeEach } = require('node:test')
const assert = require('node:assert/strict')

const nodemailer = require('nodemailer')
const emailConfig = require('../src/model/emailConfig/emailConfig.model')
const authProviders = require('../src/model/authProviders/authProviders.model')
const settings = require('../src/model/settings/settings.model')
const mailer = require('../src/utils/mailer')
const db = require('../src/utils/db')

after(() => db.close())

// Restore a clean slate of stubs before each test.
beforeEach(() => {
  emailConfig.recordStatus = async () => {}
  settings.get = async () => 'contact@example.com'
})

test('unconfigured → mailto fallback (never throws)', async () => {
  emailConfig.getWithSecret = async () => null
  emailConfig.getSafe = async () => ({ senderEmail: null, hasRefreshToken: false, enabled: false })

  const r = await mailer.sendContactMessage({ name: 'Ann', email: 'ann@player.com', message: 'hi' })
  assert.deepEqual(r, { sent: false, fallback: 'mailto', email: 'contact@example.com' })
})

test('configured → builds a Gmail OAuth2 transport and sends', async () => {
  let transportCfg = null
  let sent = null
  nodemailer.createTransport = (cfg) => {
    transportCfg = cfg
    return { sendMail: async (opts) => { sent = opts; return { messageId: '1' } } }
  }
  emailConfig.getWithSecret = async () => ({ refreshToken: 'rt-123', senderEmail: 'shard@gmail.com', senderName: 'UOMysticmoon' })
  authProviders.getWithSecret = async (id) => {
    assert.equal(id, 'google')
    return { client_id: 'cid', client_secret: 'csec' }
  }

  const r = await mailer.sendContactMessage({ name: 'Ann', email: 'ann@player.com', message: 'hi there' })
  assert.equal(r.sent, true)

  // Transport is Gmail SMTP over XOAUTH2 with the reused Google client + stored refresh token.
  assert.equal(transportCfg.host, 'smtp.gmail.com')
  assert.equal(transportCfg.port, 465)
  assert.equal(transportCfg.secure, true)
  assert.equal(transportCfg.auth.type, 'OAuth2')
  assert.equal(transportCfg.auth.user, 'shard@gmail.com')
  assert.equal(transportCfg.auth.clientId, 'cid')
  assert.equal(transportCfg.auth.clientSecret, 'csec')
  assert.equal(transportCfg.auth.refreshToken, 'rt-123')

  // From uses the display name; To is the contact_email setting; replyTo is the sender.
  assert.equal(sent.from, '"UOMysticmoon" <shard@gmail.com>')
  assert.equal(sent.to, 'contact@example.com')
  assert.equal(sent.replyTo, 'ann@player.com')
})

test('send failure propagates and is recorded', async () => {
  let recorded = null
  emailConfig.recordStatus = async (s) => { recorded = s }
  nodemailer.createTransport = () => ({ sendMail: async () => { throw new Error('smtp boom') } })
  emailConfig.getWithSecret = async () => ({ refreshToken: 'rt', senderEmail: 'shard@gmail.com', senderName: null })
  authProviders.getWithSecret = async () => ({ client_id: 'cid', client_secret: 'csec' })

  await assert.rejects(() => mailer.sendContactMessage({ name: 'A', email: 'a@b.com', message: 'x' }), /smtp boom/)
  assert.equal(recorded.status, 'error')
})
