import { getPayload } from 'payload'
import config from '@payload-config'
import { sendTenantEmail, sendTestEmail } from '@/lib/email/tenant-email-service'
import { enqueueEmail, isQueueAvailable } from '@/lib/queue'
import { NextRequest, NextResponse } from 'next/server'
import { logRateLimit, logAccessDenied } from '@/lib/audit/audit-service'
import {
  emailLimiter,
  rateLimitHeaders,
  validateIpAccess,
  createSafeLogger,
  validateCsrf,
} from '@/lib/security'

const RATE_LIMIT_MAX = 10
const logger = createSafeLogger('API:SendEmail')

interface UserWithTenants {
  id: number
  isSuperAdmin?: boolean
  tenants?: Array<{
    tenant: { id: number } | number
  }>
}

/**
 * Prüft ob User Zugriff auf den angegebenen Tenant hat
 */
function userHasAccessToTenant(user: UserWithTenants, tenantId: number): boolean {
  // Super Admins haben Zugriff auf alle Tenants
  if (user.isSuperAdmin) {
    return true
  }

  // Prüfe ob User dem Tenant zugeordnet ist
  if (!user.tenants || user.tenants.length === 0) {
    return false
  }

  return user.tenants.some((t) => {
    const userTenantId = typeof t.tenant === 'object' ? t.tenant.id : t.tenant
    return userTenantId === tenantId
  })
}

/**
 * POST /api/send-email
 *
 * Sendet eine E-Mail über den Tenant-spezifischen E-Mail-Service.
 * Erfordert Authentifizierung und Zugriff auf den Tenant.
 *
 * Body:
 * - tenantId: string | number (erforderlich)
 * - to: string | string[] (erforderlich)
 * - subject: string (erforderlich)
 * - html?: string
 * - text?: string
 * - replyTo?: string
 * - test?: boolean (sendet Test-E-Mail)
 *
 * Security:
 * - IP-Allowlist (optional via SEND_EMAIL_ALLOWED_IPS env)
 * - Rate-Limiting (10 emails per minute per user)
 * - Authentication required
 * - Tenant access control
 */
export async function POST(req: NextRequest) {
  try {
    // IP-Allowlist prüfen (falls konfiguriert)
    const ipCheck = validateIpAccess(req, 'sendEmail')
    if (!ipCheck.allowed) {
      logger.warn(`IP blocked: ${ipCheck.ip}`, { reason: ipCheck.reason })
      return NextResponse.json(
        { error: 'Access denied' },
        { status: 403 },
      )
    }

    // CSRF-Schutz für Browser-basierte Requests
    const csrfResult = validateCsrf(req)
    if (!csrfResult.valid) {
      logger.warn('CSRF validation failed', { reason: csrfResult.reason })
      return NextResponse.json(
        { error: 'CSRF validation failed' },
        { status: 403 },
      )
    }

    const payload = await getPayload({ config })

    // Authentifizierung prüfen (aus Cookie/Header)
    const { user } = await payload.auth({ headers: req.headers })

    if (!user) {
      return NextResponse.json({ error: 'Unauthorized - Login required' }, { status: 401 })
    }

    const typedUser = user as UserWithTenants

    // Rate Limiting prüfen (jetzt mit zentralem Limiter)
    const rateLimit = await emailLimiter.check(String(typedUser.id))
    if (!rateLimit.allowed) {
      // Audit: Rate-Limit-Ereignis loggen
      await logRateLimit(payload, '/api/send-email', typedUser.id, user.email as string)

      return NextResponse.json(
        {
          error: 'Rate limit exceeded',
          message: `Maximum ${RATE_LIMIT_MAX} emails per minute. Try again in ${rateLimit.retryAfter || 60} seconds.`,
        },
        {
          status: 429,
          headers: rateLimitHeaders(rateLimit, RATE_LIMIT_MAX),
        },
      )
    }

    const body = await req.json()
    const { tenantId, to, subject, html, text, replyTo, test, queued, priority } = body

    // Validierung
    if (!tenantId) {
      return NextResponse.json({ error: 'Missing required field: tenantId' }, { status: 400 })
    }

    const numericTenantId = Number(tenantId)
    if (isNaN(numericTenantId)) {
      return NextResponse.json({ error: 'Invalid tenantId: must be a number' }, { status: 400 })
    }

    // Zugriffskontrolle: User muss Zugriff auf den Tenant haben
    if (!userHasAccessToTenant(typedUser, numericTenantId)) {
      // Audit: Zugriffsverweigerung loggen
      await logAccessDenied(
        payload,
        `/api/send-email (tenantId: ${numericTenantId})`,
        typedUser.id,
        user.email as string,
      )

      return NextResponse.json(
        { error: 'Forbidden - You do not have access to this tenant' },
        { status: 403 },
      )
    }

    // Rate Limit Headers hinzufügen
    const rlHeaders = rateLimitHeaders(rateLimit, RATE_LIMIT_MAX)

    // Test-E-Mail senden
    if (test) {
      if (!to) {
        return NextResponse.json(
          { error: 'Missing required field: to (for test email)' },
          { status: 400 },
        )
      }

      const result = await sendTestEmail(payload, numericTenantId, to)

      if (result.success) {
        return NextResponse.json(
          {
            success: true,
            message: 'Test email sent successfully',
            messageId: result.messageId,
            logId: result.logId,
          },
          { headers: rlHeaders },
        )
      } else {
        return NextResponse.json(
          { success: false, error: result.error, logId: result.logId },
          { status: 500, headers: rlHeaders },
        )
      }
    }

    // Normale E-Mail senden
    if (!to || !subject) {
      return NextResponse.json(
        { error: 'Missing required fields: to, subject' },
        { status: 400 },
      )
    }

    if (!html && !text) {
      return NextResponse.json(
        { error: 'At least one of html or text is required' },
        { status: 400 },
      )
    }

    // Queued Email Sending (async via BullMQ)
    if (queued) {
      const queueAvailable = await isQueueAvailable()
      if (!queueAvailable) {
        return NextResponse.json(
          { error: 'Queue system unavailable. Use queued=false for direct sending.' },
          { status: 503, headers: rlHeaders },
        )
      }

      const job = await enqueueEmail({
        tenantId: numericTenantId,
        to,
        subject,
        html,
        text,
        replyTo,
        source: 'api',
        triggeredBy: String(typedUser.id),
        priority: priority || 'normal',
        correlationId: `api-${Date.now()}-${typedUser.id}`,
      })

      return NextResponse.json(
        {
          success: true,
          queued: true,
          message: 'Email queued successfully',
          jobId: job.id,
        },
        { headers: rlHeaders },
      )
    }

    // Direct Email Sending (synchronous)
    const result = await sendTenantEmail(payload, numericTenantId, {
      to,
      subject,
      html,
      text,
      replyTo,
      source: 'manual',
      metadata: { sentBy: typedUser.id },
    })

    if (result.success) {
      return NextResponse.json(
        {
          success: true,
          message: 'Email sent successfully',
          messageId: result.messageId,
          logId: result.logId,
        },
        { headers: rlHeaders },
      )
    } else {
      return NextResponse.json(
        { success: false, error: result.error, logId: result.logId },
        { status: 500, headers: rlHeaders },
      )
    }
  } catch (error) {
    logger.error('send-email error', error)
    return NextResponse.json(
      { error: error instanceof Error ? error.message : 'Unknown error' },
      { status: 500 },
    )
  }
}

/**
 * GET /api/send-email
 *
 * Gibt API-Dokumentation zurück.
 */
export async function GET() {
  return NextResponse.json({
    endpoint: '/api/send-email',
    method: 'POST',
    description: 'Send emails using the tenant-specific email service',
    authentication: 'Required (Cookie or Authorization header)',
    authorization: 'User must have access to the specified tenant',
    rateLimit: `${RATE_LIMIT_MAX} requests per minute per user`,
    body: {
      tenantId: 'number (required) - ID of the tenant',
      to: 'string | string[] (required) - Recipient email(s)',
      subject: 'string (required) - Email subject',
      html: 'string (optional) - HTML content',
      text: 'string (optional) - Plain text content',
      replyTo: 'string (optional) - Reply-to address',
      test: 'boolean (optional) - Send test email',
      queued: 'boolean (optional) - Queue email for async sending via BullMQ',
      priority: 'string (optional) - Priority for queued emails: high, normal, low',
    },
    response: {
      success: 'boolean',
      messageId: 'string (on direct send success)',
      jobId: 'string (on queued success)',
      logId: 'number (email log ID - direct send only)',
      error: 'string (on failure)',
    },
    examples: {
      sendEmail: {
        tenantId: 1,
        to: 'recipient@example.com',
        subject: 'Hello World',
        html: '<h1>Hello!</h1><p>This is a test email.</p>',
      },
      sendQueuedEmail: {
        tenantId: 1,
        to: 'recipient@example.com',
        subject: 'Hello World',
        html: '<h1>Hello!</h1><p>This is a queued email.</p>',
        queued: true,
        priority: 'high',
      },
      sendTestEmail: {
        tenantId: 1,
        to: 'test@example.com',
        test: true,
      },
    },
  })
}
