import { CURRENT_ART9_MAIL_VERSION } from "../../utils/consent-texts";
import {
  writeConsentGrant,
  setMailConnectionConsent,
} from "../../db/consent";
import {
  countMailConnections,
  upsertMailConnection,
} from "../../db/mail";
import { getProfile } from "../../db/profile";
import { getPlanLimits } from "../../utils/plan-features";
import { detectImapProviderAsync } from "../../utils/imap-providers";
import { ImapFlow } from "imapflow";

/**
 * POST /api/mail-connections/:id
 *
 * Gateway-Endpoint für das Anlegen einer neuen MailConnection — mit Art. 9-Consent-Check.
 *
 * Wenn kein gültiger Consent vorliegt, antwortet der Endpoint mit 412 BEFORE
 * jede IMAP-Verbindung versucht wird. Das Frontend muss dann:
 *   1. Das Consent-Modal anzeigen (Art. 9-Text)
 *   2. User bestätigt → POST /api/mail-connections/consent
 *   3. Danach diesen Endpoint erneut aufrufen (mit consentVersion im Body)
 *
 * Body:
 *   email: string (required)
 *   password: string (required)
 *   consentVersion: string (required — muss CURRENT_ART9_MAIL_VERSION entsprechen)
 *   imapHost?: string
 *   imapPort?: number
 *   useTls?: boolean
 *   rejectUnauthorized?: boolean
 *
 * Response:
 *   200: { connected: true, email, provider, custom }
 *   412: { error: 'consent_required', consentVersion: string }  ← Frontend zeigt Modal
 *   400: { error: 'invalid_body' }
 *   401: { error: 'imap_auth_failed' }
 *   403: { error: 'plan_limit', ... }
 *
 * HINWEIS: Dieser Endpoint ersetzt NICHT connect.post.ts — er ist ein paralleler
 * Pfad mit explizitem Consent-Gate. Der bestehende /api/mail/connect bleibt
 * vorerst aktiv (Abwärtskompatibilität), sollte aber mittelfristig auf diesen
 * Endpoint migriert werden.
 */
export default defineEventHandler(async (event) => {
  const user = await requireUser(event);

  const body = await readBody(event).catch(() => null);

  if (!body) {
    throw createError({
      statusCode: 400,
      data: { error: "invalid_body" },
    });
  }

  const {
    email,
    password,
    consentVersion,
    imapHost: customImapHost,
    imapPort: customImapPort,
    useTls,
    rejectUnauthorized,
  } = body as {
    email?: string;
    password?: string;
    consentVersion?: string;
    imapHost?: string;
    imapPort?: number;
    useTls?: boolean;
    rejectUnauthorized?: boolean;
  };

  if (!email || !password) {
    throw createError({
      statusCode: 400,
      data: { error: "invalid_body" },
    });
  }

  // ── Art. 9-Consent-Gateway ────────────────────────────────────────────────
  // Keine Einwilligung → sofort 412, bevor IMAP-Verbindung aufgebaut wird.
  if (!consentVersion || consentVersion !== CURRENT_ART9_MAIL_VERSION) {
    throw createError({
      statusCode: 412,
      data: {
        error: "consent_required",
        consentVersion: CURRENT_ART9_MAIL_VERSION,
      },
    });
  }

  // ── Plan-Limit prüfen ─────────────────────────────────────────────────────
  const profile = await getProfile(user.id);
  const limits = getPlanLimits(profile?.plan ?? "free");

  if (limits.mailAgents !== Infinity) {
    const count = await countMailConnections(user.id);
    if (count >= limits.mailAgents) {
      throw createError({
        statusCode: 403,
        data: {
          error: "plan_limit",
          resource: "mail_accounts",
          current: count,
          limit: limits.mailAgents,
        },
      });
    }
  }

  // ── IMAP-Provider-Detection ───────────────────────────────────────────────
  const provider = await detectImapProviderAsync(email);
  const resolvedHost = customImapHost?.trim() || provider.host;
  const resolvedPort = customImapPort ?? provider.port;

  const useImplicitTls = useTls !== false;
  const tlsRejectUnauthorized = rejectUnauthorized !== false;
  const useStarttls = useTls === false;

  // ── IMAP-Verbindung testen ────────────────────────────────────────────────
  const client = new ImapFlow({
    host: resolvedHost,
    port: resolvedPort,
    secure: useImplicitTls,
    ...(useStarttls ? { requireTLS: true } : {}),
    auth: { user: email, pass: password },
    logger: false,
    tls: { rejectUnauthorized: tlsRejectUnauthorized },
  });

  try {
    await client.connect();
    await client.logout();
  } catch (err: any) {
    throw createError({
      statusCode: 401,
      data: {
        error: "imap_auth_failed",
        detail: err.message ?? "connection_failed",
      },
    });
  }

  // ── Consent-Zeitstempel & Audit-Log VOR dem Upsert ───────────────────────
  const now = new Date();
  const ipAddress =
    getHeader(event, "x-forwarded-for")?.split(",")[0]?.trim() ??
    getHeader(event, "x-real-ip") ??
    null;
  const userAgent = getHeader(event, "user-agent") ?? null;

  // MailConnection anlegen/updaten
  const connection = await upsertMailConnection({
    userId: user.id,
    email,
    provider: "imap",
    providerName: customImapHost ? resolvedHost : provider.name,
    imapHost: resolvedHost,
    imapPort: resolvedPort,
    passwordEncrypted: encrypt(password),
    rejectUnauthorized: tlsRejectUnauthorized,
    useStarttls,
  });

  // consent_at + version auf der Connection setzen
  await setMailConnectionConsent({
    connectionId: connection.id,
    userId: user.id,
    consentAt: now,
    consentVersion,
    consentIpAddress: ipAddress,
  });

  // Append-only Audit-Log
  await writeConsentGrant({
    userId: user.id,
    consentType: "art9-mail",
    consentVersion,
    consentAt: now,
    ipAddress,
    userAgent,
    mailConnectionId: connection.id,
  });

  return {
    connected: true,
    email,
    provider: customImapHost ? resolvedHost : provider.name,
    custom: !!customImapHost,
  };
});
