import { createNeonRequestDbScope } from '@/server/db/client';
import type { DrizzleClient } from '@/server/db/client';
import { eq } from 'drizzle-orm';
import { e2eFactoryRuns } from '@/server/db/schema';
import { env, type MultidealEnv } from '@/server/env';
import { createFactoryEngine } from './core';
import { assertFactoryHandlerContract } from './contract';
import { createDbFactoryStore } from './db-store';
import { createCommerceFactoryHandlers } from './commerce';
import { createLlmFactoryHandlers } from './llm';
import { createImageFactoryHandlers } from './image';
import { createPromotionFactoryHandlers } from './promotion';
import { createActorProfileFactoryHandlers } from './actor-profile';
import { createAffiliateFactoryHandlers } from './affiliate';
import { captureCaught } from '@/lib/observability';
import { disarmPersonalOfferAlarm } from '@/server/do-client';

type FactoryDatabaseEnv = Pick<
  MultidealEnv,
  'DATABASE_URL' | 'ENVIRONMENT' | 'E2E_FACTORY_DATABASE_URL'
>;

// Factory teardown deletes rows while the app still has in-flight work for the
// same run (outbox drain, DO alarms, late SSR requests). Postgres aborts one of
// the two transactions; re-running the whole transaction re-reads current state.
const FACTORY_TX_RETRY_DELAYS_MS = [50, 150, 400];
const CONCURRENCY_ABORT_CODES = new Set(['40P01', '40001']);

const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

function isConcurrencyAbort(error: unknown): boolean {
  let current: unknown = error;
  for (let depth = 0; current && depth < 4; depth += 1) {
    const candidate = current as { code?: unknown; cause?: unknown };
    if (typeof candidate.code === 'string' && CONCURRENCY_ABORT_CODES.has(candidate.code))
      return true;
    current = candidate.cause;
  }
  return false;
}

export function factoryDatabaseAllowed(config: FactoryDatabaseEnv = env): boolean {
  if (
    !config.DATABASE_URL ||
    !config.E2E_FACTORY_DATABASE_URL ||
    !['development', 'preview', 'test'].includes(config.ENVIRONMENT ?? '')
  ) {
    return false;
  }
  try {
    return new URL(config.DATABASE_URL).href === new URL(config.E2E_FACTORY_DATABASE_URL).href;
  } catch (error) {
    captureCaught(error, { scope: 'e2e-factory.database-host', severity: 'warning' });
    return false;
  }
}

export function createFactoryRuntime() {
  if (!factoryDatabaseAllowed() || !env.DATABASE_URL || !env.PII_KEY || !env.QR_SECRET) {
    throw new Error('Factory database environment unavailable');
  }
  const attempt = async <T>(runId: string, work: (tx: DrizzleClient) => Promise<T>) => {
    const scope = createNeonRequestDbScope({ DATABASE_URL: env.DATABASE_URL! });
    try {
      return await scope.db.transaction(async (tx) => {
        await tx.insert(e2eFactoryRuns).values({ runId }).onConflictDoNothing();
        await tx
          .update(e2eFactoryRuns)
          .set({ touchedAt: new Date() })
          .where(eq(e2eFactoryRuns.runId, runId));
        return work(tx);
      });
    } finally {
      await scope.close();
    }
  };
  const serialized = async <T>(runId: string, work: (tx: DrizzleClient) => Promise<T>) => {
    for (let index = 0; ; index += 1) {
      try {
        return await attempt(runId, work);
      } catch (error) {
        if (index >= FACTORY_TX_RETRY_DELAYS_MS.length || !isConcurrencyAbort(error)) throw error;
        captureCaught(error, { scope: 'e2e-factory.tx-retry', severity: 'info' });
        await sleep(FACTORY_TX_RETRY_DELAYS_MS[index]!);
      }
    }
  };
  const engine = (tx: DrizzleClient) => {
    const store = createDbFactoryStore(tx);
    const handlers = {
      ...createCommerceFactoryHandlers({
        db: tx,
        store,
        piiKey: env.PII_KEY!,
        qrSecret: env.QR_SECRET!,
        testStripeAccountId: env.E2E_STRIPE_CONNECT_ACCOUNT_ID,
        paymentProvider: env.PAYMENT_PROVIDER,
        disarmPersonalOfferAlarm: (requestId) => disarmPersonalOfferAlarm(env, requestId),
      }),
      ...createLlmFactoryHandlers({
        db: tx,
        store,
        databaseUrl: env.DATABASE_URL!,
        piiKey: env.PII_KEY!,
      }),
      ...createImageFactoryHandlers({ db: tx, store }),
      ...createPromotionFactoryHandlers({ db: tx, store }),
      ...createActorProfileFactoryHandlers({ db: tx, store, piiKey: env.PII_KEY! }),
      ...createAffiliateFactoryHandlers({ db: tx, store }),
    };
    assertFactoryHandlerContract(handlers);
    return createFactoryEngine(store, handlers);
  };
  return {
    execute: (command: Parameters<ReturnType<typeof engine>['execute']>[0]) =>
      serialized(command.runId, (tx) => engine(tx).execute(command)),
    readback: (input: Parameters<ReturnType<typeof engine>['readback']>[0]) =>
      serialized(input.runId, (tx) => engine(tx).readback(input)),
    cleanupRun: (runId: string) => serialized(runId, (tx) => engine(tx).cleanupRun(runId)),
  };
}
