/**
 * API Route: Consent Management
 *
 * POST - Consent erfassen
 * GET  - Consent-Status abrufen
 */

import { NextRequest, NextResponse } from 'next/server'
import {
  ConsentEntry,
  ConsentStatistics,
  DataPointCategory,
  LegalBasis,
} from '@/lib/sdk/einwilligungen/types'
import { PREDEFINED_DATA_POINTS } from '@/lib/sdk/einwilligungen/catalog/loader'

// In-Memory Storage fuer Consents
const consentStorage = new Map<string, ConsentEntry[]>() // tenantId -> consents

// Hilfsfunktion: Generiere eindeutige ID
function generateId(): string {
  return `consent-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
}

/**
 * POST /api/sdk/v1/einwilligungen/consent
 *
 * Erfasst eine neue Einwilligung
 *
 * Body:
 * - userId: string - Benutzer-ID
 * - dataPointId: string - ID des Datenpunkts
 * - granted: boolean - Einwilligung erteilt?
 * - consentVersion?: string - Version der Einwilligung
 */
export async function POST(request: NextRequest) {
  try {
    const tenantId = request.headers.get('X-Tenant-ID')

    if (!tenantId) {
      return NextResponse.json(
        { error: 'Tenant ID required' },
        { status: 400 }
      )
    }

    const body = await request.json()
    const { userId, dataPointId, granted, consentVersion = '1.0.0' } = body

    if (!userId || !dataPointId || typeof granted !== 'boolean') {
      return NextResponse.json(
        { error: 'userId, dataPointId, and granted required' },
        { status: 400 }
      )
    }

    // Hole IP und User-Agent
    const ipAddress = request.headers.get('x-forwarded-for') || request.headers.get('x-real-ip') || null
    const userAgent = request.headers.get('user-agent') || null

    // Erstelle Consent-Eintrag
    const consent: ConsentEntry = {
      id: generateId(),
      userId,
      dataPointId,
      granted,
      grantedAt: new Date(),
      revokedAt: undefined,
      ipAddress: ipAddress || undefined,
      userAgent: userAgent || undefined,
      consentVersion,
    }

    // Hole bestehende Consents
    const tenantConsents = consentStorage.get(tenantId) || []

    // Pruefe auf bestehende Einwilligung fuer diesen Datenpunkt
    const existingIndex = tenantConsents.findIndex(
      (c) => c.userId === userId && c.dataPointId === dataPointId && !c.revokedAt
    )

    if (existingIndex !== -1) {
      if (!granted) {
        // Widerruf: Setze revokedAt
        tenantConsents[existingIndex].revokedAt = new Date()
      }
      // Bei granted=true: Keine Aenderung noetig, Consent existiert bereits
    } else if (granted) {
      // Neuer Consent
      tenantConsents.push(consent)
    }

    consentStorage.set(tenantId, tenantConsents)

    return NextResponse.json({
      success: true,
      consent: {
        id: consent.id,
        dataPointId: consent.dataPointId,
        granted: consent.granted,
        grantedAt: consent.grantedAt,
      },
    })
  } catch (error) {
    console.error('Error recording consent:', error)
    return NextResponse.json(
      { error: 'Failed to record consent' },
      { status: 500 }
    )
  }
}

/**
 * GET /api/sdk/v1/einwilligungen/consent
 *
 * Ruft Consent-Status und Statistiken ab
 *
 * Query Parameters:
 * - userId?: string - Fuer spezifischen Benutzer
 * - stats?: boolean - Statistiken inkludieren
 */
export async function GET(request: NextRequest) {
  try {
    const tenantId = request.headers.get('X-Tenant-ID')

    if (!tenantId) {
      return NextResponse.json(
        { error: 'Tenant ID required' },
        { status: 400 }
      )
    }

    const { searchParams } = new URL(request.url)
    const userId = searchParams.get('userId')
    const includeStats = searchParams.get('stats') === 'true'

    const tenantConsents = consentStorage.get(tenantId) || []

    if (userId) {
      // Spezifischer Benutzer
      const userConsents = tenantConsents.filter((c) => c.userId === userId)

      // Gruppiere nach Datenpunkt
      const consentMap: Record<string, { granted: boolean; grantedAt: Date; revokedAt?: Date }> = {}
      for (const consent of userConsents) {
        consentMap[consent.dataPointId] = {
          granted: consent.granted && !consent.revokedAt,
          grantedAt: consent.grantedAt,
          revokedAt: consent.revokedAt,
        }
      }

      return NextResponse.json({
        userId,
        consents: consentMap,
        totalConsents: Object.keys(consentMap).length,
        activeConsents: Object.values(consentMap).filter((c) => c.granted).length,
      })
    }

    // Statistiken fuer alle Consents
    if (includeStats) {
      const stats = calculateStatistics(tenantConsents)
      return NextResponse.json({
        statistics: stats,
        recentConsents: tenantConsents
          .sort((a, b) => new Date(b.grantedAt).getTime() - new Date(a.grantedAt).getTime())
          .slice(0, 10)
          .map((c) => ({
            id: c.id,
            userId: c.userId.substring(0, 8) + '...', // Anonymisiert
            dataPointId: c.dataPointId,
            granted: c.granted,
            grantedAt: c.grantedAt,
          })),
      })
    }

    // Standard: Alle Consents (anonymisiert)
    return NextResponse.json({
      totalConsents: tenantConsents.length,
      activeConsents: tenantConsents.filter((c) => c.granted && !c.revokedAt).length,
      revokedConsents: tenantConsents.filter((c) => c.revokedAt).length,
    })
  } catch (error) {
    console.error('Error fetching consents:', error)
    return NextResponse.json(
      { error: 'Failed to fetch consents' },
      { status: 500 }
    )
  }
}

/**
 * PUT /api/sdk/v1/einwilligungen/consent
 *
 * Batch-Update von Consents (z.B. Cookie-Banner)
 */
export async function PUT(request: NextRequest) {
  try {
    const tenantId = request.headers.get('X-Tenant-ID')

    if (!tenantId) {
      return NextResponse.json(
        { error: 'Tenant ID required' },
        { status: 400 }
      )
    }

    const body = await request.json()
    const { userId, consents, consentVersion = '1.0.0' } = body

    if (!userId || !consents || typeof consents !== 'object') {
      return NextResponse.json(
        { error: 'userId and consents object required' },
        { status: 400 }
      )
    }

    const ipAddress = request.headers.get('x-forwarded-for') || request.headers.get('x-real-ip') || null
    const userAgent = request.headers.get('user-agent') || null

    const tenantConsents = consentStorage.get(tenantId) || []
    const now = new Date()

    // Verarbeite jeden Consent
    for (const [dataPointId, granted] of Object.entries(consents)) {
      if (typeof granted !== 'boolean') continue

      const existingIndex = tenantConsents.findIndex(
        (c) => c.userId === userId && c.dataPointId === dataPointId && !c.revokedAt
      )

      if (existingIndex !== -1) {
        const existing = tenantConsents[existingIndex]
        if (existing.granted !== granted) {
          if (!granted) {
            // Widerruf
            tenantConsents[existingIndex].revokedAt = now
          } else {
            // Neuer Consent nach Widerruf
            tenantConsents.push({
              id: generateId(),
              userId,
              dataPointId,
              granted: true,
              grantedAt: now,
              ipAddress: ipAddress || undefined,
              userAgent: userAgent || undefined,
              consentVersion,
            })
          }
        }
      } else if (granted) {
        // Neuer Consent
        tenantConsents.push({
          id: generateId(),
          userId,
          dataPointId,
          granted: true,
          grantedAt: now,
          ipAddress: ipAddress || undefined,
          userAgent: userAgent || undefined,
          consentVersion,
        })
      }
    }

    consentStorage.set(tenantId, tenantConsents)

    // Zaehle aktive Consents fuer diesen User
    const activeConsents = tenantConsents.filter(
      (c) => c.userId === userId && c.granted && !c.revokedAt
    ).length

    return NextResponse.json({
      success: true,
      userId,
      activeConsents,
      updatedAt: now,
    })
  } catch (error) {
    console.error('Error updating consents:', error)
    return NextResponse.json(
      { error: 'Failed to update consents' },
      { status: 500 }
    )
  }
}

/**
 * Berechnet Consent-Statistiken
 */
function calculateStatistics(consents: ConsentEntry[]): ConsentStatistics {
  const activeConsents = consents.filter((c) => c.granted && !c.revokedAt)
  const revokedConsents = consents.filter((c) => c.revokedAt)

  // Gruppiere nach Kategorie (18 Kategorien A-R)
  const byCategory: Record<DataPointCategory, { total: number; active: number; revoked: number }> = {
    MASTER_DATA: { total: 0, active: 0, revoked: 0 },
    CONTACT_DATA: { total: 0, active: 0, revoked: 0 },
    AUTHENTICATION: { total: 0, active: 0, revoked: 0 },
    CONSENT: { total: 0, active: 0, revoked: 0 },
    COMMUNICATION: { total: 0, active: 0, revoked: 0 },
    PAYMENT: { total: 0, active: 0, revoked: 0 },
    USAGE_DATA: { total: 0, active: 0, revoked: 0 },
    LOCATION: { total: 0, active: 0, revoked: 0 },
    DEVICE_DATA: { total: 0, active: 0, revoked: 0 },
    MARKETING: { total: 0, active: 0, revoked: 0 },
    ANALYTICS: { total: 0, active: 0, revoked: 0 },
    SOCIAL_MEDIA: { total: 0, active: 0, revoked: 0 },
    HEALTH_DATA: { total: 0, active: 0, revoked: 0 },
    EMPLOYEE_DATA: { total: 0, active: 0, revoked: 0 },
    CONTRACT_DATA: { total: 0, active: 0, revoked: 0 },
    LOG_DATA: { total: 0, active: 0, revoked: 0 },
    AI_DATA: { total: 0, active: 0, revoked: 0 },
    SECURITY: { total: 0, active: 0, revoked: 0 },
  }

  for (const consent of consents) {
    const dataPoint = PREDEFINED_DATA_POINTS.find((dp) => dp.id === consent.dataPointId)
    if (dataPoint) {
      byCategory[dataPoint.category].total++
      if (consent.granted && !consent.revokedAt) {
        byCategory[dataPoint.category].active++
      }
      if (consent.revokedAt) {
        byCategory[dataPoint.category].revoked++
      }
    }
  }

  // Gruppiere nach Rechtsgrundlage (7 Rechtsgrundlagen)
  const byLegalBasis: Record<LegalBasis, { total: number; active: number }> = {
    CONTRACT: { total: 0, active: 0 },
    CONSENT: { total: 0, active: 0 },
    EXPLICIT_CONSENT: { total: 0, active: 0 },
    LEGITIMATE_INTEREST: { total: 0, active: 0 },
    LEGAL_OBLIGATION: { total: 0, active: 0 },
    VITAL_INTERESTS: { total: 0, active: 0 },
    PUBLIC_INTEREST: { total: 0, active: 0 },
  }

  for (const consent of consents) {
    const dataPoint = PREDEFINED_DATA_POINTS.find((dp) => dp.id === consent.dataPointId)
    if (dataPoint) {
      byLegalBasis[dataPoint.legalBasis].total++
      if (consent.granted && !consent.revokedAt) {
        byLegalBasis[dataPoint.legalBasis].active++
      }
    }
  }

  // Berechne Conversion Rate (Unique Users mit mindestens einem Consent)
  const uniqueUsers = new Set(consents.map((c) => c.userId))
  const usersWithActiveConsent = new Set(activeConsents.map((c) => c.userId))
  const conversionRate = uniqueUsers.size > 0
    ? (usersWithActiveConsent.size / uniqueUsers.size) * 100
    : 0

  return {
    totalConsents: consents.length,
    activeConsents: activeConsents.length,
    revokedConsents: revokedConsents.length,
    byCategory,
    byLegalBasis,
    conversionRate: Math.round(conversionRate * 10) / 10,
  }
}
