import { createServer } from "./app.js";
import { env } from "./config/env.js";
import { logger } from "./lib/logger.service.js";
import { techStepClassifier } from "./lib/recipe-matching/tech-step-matcher.js";
import { registerAllRecipeSources } from "./sources/index.js";

// Populates the recipe-source registry (recipe-source-registry.ts) before
// the app starts — see registerAllRecipeSources' doc comment for why this
// doesn't happen inside app.ts/createServer() itself.
registerAllRecipeSources();

/**
 * Trains the tech-step classifier (a `POST /v1/train` round-trip per locale
 * to `services/tech-step-intent-service` — see
 * `TechStepClassifierService.warmUp`) before accepting any traffic, so the
 * first real recipe save/preview isn't the one stuck waiting for it.
 *
 * Retried with exponential backoff: in Docker Compose, `app`'s own
 * `depends_on: tech-step-intent-service: condition: service_healthy`
 * (`docker-compose.yml`) already means that service is up by the time this
 * runs, but native dev (`pnpm dev:api`, no Compose ordering at all) can
 * easily start this before the intent service has finished loading its
 * spaCy models — a transient connection failure here shouldn't need a
 * manual restart. Still non-fatal after every attempt is exhausted: the
 * *next* real call retries training itself (see `_ensureTrained`'s own
 * retry-on-failure comment), same graceful-degrade posture as before this
 * retry loop existed.
 */
async function warmUpTechStepClassifier(): Promise<void> {
  const maxAttempts = 5;
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    try {
      await techStepClassifier.warmUp();
      return;
    } catch (err) {
      if (attempt === maxAttempts) {
        logger.error("Tech-step classifier warm-up failed after retries", {
          error: err instanceof Error ? err.message : String(err),
          attempts: attempt,
        });
        return;
      }
      const delayMs = 1000 * 2 ** (attempt - 1);
      await new Promise((resolve) => setTimeout(resolve, delayMs));
    }
  }
}

await warmUpTechStepClassifier();

const server = createServer();

server.listen(env.PORT, () => {
  logger.info("API listening", { port: env.PORT, nodeEnv: env.NODE_ENV });
});
