import type { APIRequestContext } from '@playwright/test'
import fs from 'node:fs'
import path from 'node:path'

/**
 * Mock Email Message structure (compatible with MailpitMessage interface)
 */
export interface MockEmailMessage {
  ID: string
  From: { Address: string, Name: string }
  To: Array<{ Address: string, Name: string }>
  Subject: string
  Created: string
  Size: number
  Snippet: string
  Text?: string // Full text content
}

/**
 * Helper class for parsing mock email logs from server output
 * Provides the same interface as MailpitHelper for seamless test migration
 */
export class MockEmailHelper {
  private logFilePath: string
  private messages: MockEmailMessage[] = []
  private lastReadPosition = 0

  constructor(private request: APIRequestContext) {
    // Log file will be written by the dev server
    this.logFilePath = path.join(process.cwd(), 'test/e2e/logs/server.log')

    // Ensure log directory exists
    const logDir = path.dirname(this.logFilePath)
    if (!fs.existsSync(logDir)) {
      fs.mkdirSync(logDir, { recursive: true })
    }
  }

  /**
   * Read new log entries and parse email messages
   */
  private readNewLogEntries(): void {
    if (!fs.existsSync(this.logFilePath)) {
      return
    }

    const content = fs.readFileSync(this.logFilePath, 'utf-8')

    // Only process new content since last read
    const newContent = content.slice(this.lastReadPosition)
    this.lastReadPosition = content.length

    if (!newContent.trim()) {
      return
    }

    // Parse email entries from mock mode logs
    // Format:
    // 📧 Email Mock Mode - Email would be sent:
    // ┌─────────┬────────────────────────────────────┐
    // │ (index) │ Values                             │
    // ├─────────┼────────────────────────────────────┤
    // │ From    │ 'noreply@test.local'              │
    // │ To      │ 'test@example.com'                │
    // │ Subject │ 'Verify your email address'       │
    // └─────────┴────────────────────────────────────┘
    //
    // 📝 Text Content:
    // <text content here>
    // ----------------------------------------

    const emailBlockRegex = /📧 Email Mock Mode - Email would be sent:[\s\S]*?(?=📧 Email Mock Mode|$)/g
    const emailBlocks = newContent.match(emailBlockRegex) || []

    for (const block of emailBlocks) {
      const email = this.parseEmailBlock(block)
      if (email) {
        this.messages.push(email)
      }
    }
  }

  /**
   * Parse a single email block from logs
   */
  private parseEmailBlock(block: string): MockEmailMessage | null {
    try {
      // Extract From, To, Subject from console.table output
      const fromMatch = block.match(/│\s*From\s*│\s*'([^']+)'/)
      const toMatch = block.match(/│\s*To\s*│\s*'([^']+)'/)
      const subjectMatch = block.match(/│\s*Subject\s*│\s*'([^']+)'/)

      if (!fromMatch || !toMatch || !subjectMatch) {
        return null
      }

      const from = fromMatch[1]!
      const to = toMatch[1]!
      const subject = subjectMatch[1]!

      // Extract text content if present
      const textMatch = block.match(/📝 Text Content:\s*\n([\s\S]*?)\n\s*-{20,}/)
      const text = textMatch?.[1]?.trim() || ''

      // Generate a pseudo-ID based on timestamp and recipient
      const id = `mock-${Date.now()}-${to.replace(/[^a-z0-9]/gi, '-')}`

      return {
        ID: id,
        From: {
          Address: from,
          Name: from.split('@')[0] || ''
        },
        To: [{
          Address: to,
          Name: to.split('@')[0] || ''
        }],
        Subject: subject,
        Created: new Date().toISOString(),
        Size: text.length,
        Snippet: text.substring(0, 100),
        Text: text
      }
    } catch (error) {
      console.error('Error parsing email block:', error)
      return null
    }
  }

  /**
   * Get all messages (reads new log entries first)
   */
  async getMessages(): Promise<MockEmailMessage[]> {
    this.readNewLogEntries()
    return [...this.messages]
  }

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

    while (Date.now() - startTime < timeout) {
      this.readNewLogEntries()

      const filteredMessages = this.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'
   * Compatible with MailpitHelper interface
   */
  async getVerificationLink(messageId: string): Promise<string | null> {
    const message = this.messages.find(msg => msg.ID === messageId)
    if (!message || !message.Text) {
      return null
    }

    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 (clear in-memory message store)
   * Compatible with MailpitHelper interface
   */
  async deleteAllMessages(): Promise<void> {
    this.messages = []
    // Optionally reset log file to prevent it from growing indefinitely
    if (fs.existsSync(this.logFilePath)) {
      fs.writeFileSync(this.logFilePath, '', 'utf-8')
      this.lastReadPosition = 0
    }
  }
}

/**
 * Create a MockEmailHelper instance
 * Compatible with createMailpitHelper factory function
 */
export function createMockEmailHelper(request: APIRequestContext): MockEmailHelper {
  return new MockEmailHelper(request)
}
