import { randomUUID } from 'node:crypto';
import {
  demoSubmissionEnvelopeSchema,
  zodFieldErrors,
  type DemoSubmissionResult,
} from '@/lib/demo/schema';
import { submitDemoLead } from '@/lib/demo/service';
import { getIntegrationEnvironment } from '@/lib/integrations/environment';
import { isApplicationJson } from '@/lib/security/content-type';
import { NextResponse } from 'next/server';

const maximumBodyBytes = 16_384;
const responseHeaders = { 'Cache-Control': 'no-store', 'X-Content-Type-Options': 'nosniff' };

function failure(
  status: number,
  result: Extract<DemoSubmissionResult, { ok: false }>,
): NextResponse<DemoSubmissionResult> {
  return NextResponse.json(result, { status, headers: responseHeaders });
}

function isAllowedOrigin(
  request: Request,
  approvedOrigin: string | undefined,
  production: boolean,
) {
  const origin = request.headers.get('origin');
  if (!origin) return !production;
  const requestOrigin = new URL(request.url).origin;
  if (origin === requestOrigin) return true;
  return approvedOrigin ? origin === new URL(approvedOrigin).origin : false;
}

export async function POST(request: Request): Promise<NextResponse<DemoSubmissionResult>> {
  const correlationId = randomUUID();
  let environment;
  try {
    environment = getIntegrationEnvironment();
  } catch {
    return failure(503, {
      ok: false,
      category: 'configuration',
      formErrorCode: 'integration_environment_invalid',
      retryable: false,
      correlationId,
    });
  }

  if (request.headers.get('x-rdg-form') !== 'demo-v1') {
    return failure(403, {
      ok: false,
      category: 'validation',
      formErrorCode: 'invalid_request_marker',
      retryable: false,
      correlationId,
    });
  }

  if (!isAllowedOrigin(request, environment.SITE_ORIGIN, environment.NODE_ENV === 'production')) {
    return failure(403, {
      ok: false,
      category: 'validation',
      formErrorCode: 'invalid_origin',
      retryable: false,
      correlationId,
    });
  }

  const contentType = request.headers.get('content-type');
  if (!isApplicationJson(contentType)) {
    return failure(415, {
      ok: false,
      category: 'validation',
      formErrorCode: 'unsupported_content_type',
      retryable: false,
      correlationId,
    });
  }

  const declaredLength = Number(request.headers.get('content-length') ?? '0');
  if (Number.isFinite(declaredLength) && declaredLength > maximumBodyBytes) {
    return failure(413, {
      ok: false,
      category: 'validation',
      formErrorCode: 'request_too_large',
      retryable: false,
      correlationId,
    });
  }

  let body: unknown;
  try {
    const raw = await request.text();
    if (new TextEncoder().encode(raw).byteLength > maximumBodyBytes) {
      return failure(413, {
        ok: false,
        category: 'validation',
        formErrorCode: 'request_too_large',
        retryable: false,
        correlationId,
      });
    }
    body = JSON.parse(raw);
  } catch {
    return failure(400, {
      ok: false,
      category: 'validation',
      formErrorCode: 'malformed_json',
      retryable: false,
      correlationId,
    });
  }

  const parsed = demoSubmissionEnvelopeSchema.safeParse(body);
  if (!parsed.success) {
    return failure(400, {
      ok: false,
      category: 'validation',
      fieldErrors: zodFieldErrors(parsed.error),
      formErrorCode: 'validation_failed',
      retryable: false,
      correlationId,
    });
  }

  if (parsed.data.guard.honeypot.length > 0) {
    return failure(400, {
      ok: false,
      category: 'abuse',
      formErrorCode: 'request_rejected',
      retryable: false,
      correlationId,
    });
  }

  const scenarioHeader = request.headers.get('x-rdg-test-scenario');
  const testScenario =
    environment.NODE_ENV !== 'production' &&
    environment.DEMO_TEST_SCENARIOS_ENABLED &&
    ['success', 'duplicate', 'timeout', 'integration-error'].includes(scenarioHeader ?? '')
      ? (scenarioHeader as 'success' | 'duplicate' | 'timeout' | 'integration-error')
      : undefined;

  const result = await submitDemoLead(parsed.data.lead, {
    environment,
    ...(testScenario ? { testScenario } : {}),
  });

  const status = result.ok
    ? 202
    : result.category === 'timeout'
      ? 504
      : result.category === 'configuration'
        ? 503
        : result.category === 'duplicate'
          ? 409
          : 502;
  return NextResponse.json(result, { status, headers: responseHeaders });
}
