import type { APIRequestContext } from '@playwright/test'

/**
 * Mailpit API helper for E2E email testing
 */

export interface MailpitMessage {
  ID: string
  From: { Address: string, Name: string }
  To: Array<{ Address: string, Name: string }>
  Subject: string
  Created: string
  Size: number
  Snippet: string
}

interface MailpitSearchResponse {
  total: number
  unread: number
  count: number
  messages: MailpitMessage[]
}

/**
 * Helper class for interacting with Mailpit API
 */
export class MailpitHelper {
  private baseURL = 'http://localhost:8025/api/v1'

  constructor(private request: APIRequestContext) {}

  /**
   * Get all messages
   */
  async getMessages(): Promise<MailpitMessage[]> {
    const response = await this.request.get(`${this.baseURL}/messages`)
    const data: MailpitSearchResponse = await response.json()
    return data.messages || []
  }

  /**
   * Wait for an email to be received (with timeout)
   */
  async waitForEmail(
    email: string,
    options: { timeout?: number, subject?: string | RegExp } = {}
  ): Promise<MailpitMessage> {
    const timeout = options.timeout || 10000
    const startTime = Date.now()

    while (Date.now() - startTime < timeout) {
      const messages = await this.getMessages()
      const filteredMessages = messages.filter(msg =>
        msg.To.some(recipient => recipient.Address.toLowerCase() === email.toLowerCase())
      )

      if (filteredMessages.length > 0) {
        // If subject filter is provided, find matching message
        if (options.subject) {
          const subjectRegex = options.subject instanceof RegExp
            ? options.subject
            : new RegExp(options.subject, 'i')

          const match = filteredMessages.find(msg => subjectRegex.test(msg.Subject))
          if (match) return match
        } else {
          const firstMessage = filteredMessages[0]
          if (firstMessage) return firstMessage
        }
      }

      // Wait a bit before checking again
      await new Promise(resolve => setTimeout(resolve, 500))
    }

    throw new Error(`Timeout waiting for email to ${email}${options.subject ? ` with subject matching ${options.subject}` : ''}`)
  }

  /**
   * Get verification link from an email
   * Looks for URLs containing 'verify' or 'verification'
   */
  async getVerificationLink(messageId: string): Promise<string | null> {
    const message = await this.request.get(`${this.baseURL}/message/${messageId}`).then(r => r.json())
    const urlRegex = /https?:\/\/[^\s<>"]+/g
    const urls = message.Text.match(urlRegex) || []

    // Find URL that looks like a verification link
    const verificationUrl = urls.find((url: string) =>
      url.includes('/verify')
      || url.includes('verification')
      || url.includes('token=')
      || url.includes('callbackURL')
    )

    return verificationUrl || null
  }

  /**
   * Delete all messages (clean inbox)
   */
  async deleteAllMessages(): Promise<void> {
    await this.request.delete(`${this.baseURL}/messages`)
  }
}

/**
 * Create a MailpitHelper instance
 */
export function createMailpitHelper(request: APIRequestContext): MailpitHelper {
  return new MailpitHelper(request)
}
