// Setup routes:
//
//   GET  /api/setup/templates — the industry template picker list for the
//        setup wizard ("What kind of work do you do?"). Pre-company, so it
//        lives OUTSIDE /api/c/ (no X-Company-Id needed) like /api/companies.
//        Returns picker copy ({key, label, blurb, examples}) PLUS each
//        template's full account list ({code, name, type, subtype}) so the
//        wizard's pre-create chart preview always shows exactly what the
//        fresh route below will stamp — one fetch, no separate per-template
//        endpoint, and no hardcoded client-side mirror that could drift (the
//        payload is ~330 small rows across all eight templates, trivially
//        cacheable). subtype was added in Chart Management Task 3 so the
//        preview can show the same standard subtype sections (Bank accounts
//        / Credit cards / ...) the chart screen shows after stamping.
//
//   POST /api/c/setup/fresh — "Start fresh" company setup (Task 4 of
//        docs/superpowers/plans/2026-07-31-local-app.md; template picker
//        added in docs/superpowers/plans/2026-08-02-chart-templates.md
//        Task 1). Inserts the chosen template's chart of accounts for the
//        company named by X-Company-Id, so a brand-new company never faces
//        an empty chart (CLAUDE.md §9). Accepts `templateKey` (default
//        'general'); the original `template: "small-business"` body keeps
//        working as an alias for 'general' so existing callers (sample
//        seeder, wizard, tests) are unaffected. Admin pool, one transaction:
//        the ZERO-accounts gate and every INSERT must see a consistent
//        snapshot, and RLS has nothing useful to add here (a fresh company's
//        chart is empty by definition — there's nothing to leak).

import type { FastifyInstance } from "fastify";
import { z } from "zod";
import type { Db } from "./db.js";
import { mapPgError } from "./errors.js";
import { CHART_TEMPLATES, CHART_TEMPLATES_BY_KEY } from "./templates/types.js";

const freshSetupSchema = z.object({
  templateKey: z.string().optional(),
  // Legacy field from the original single-template API.
  template: z.string().optional(),
});

const UNKNOWN_TEMPLATE = {
  status: 400,
  error: "That business type isn't one of the options — pick one from the list.",
};

const CONFLICTING_TEMPLATE_FIELDS = {
  status: 400,
  error: "Pick one business type — the request named two different ones.",
};

/** 'small-business' was the original (and only) key of the single-template
 *  API; it names the same chart the 'general' template stamps today. */
function normalizeTemplateKey(key: string): string {
  return key === "small-business" ? "general" : key;
}

const ALREADY_HAS_CHART = {
  status: 409,
  error: "This company already has a chart of accounts",
};

export function registerSetupRoutes(fastify: FastifyInstance, db: Db): void {
  fastify.get("/api/setup/templates", async () =>
    CHART_TEMPLATES.map(({ key, label, blurb, examples, accounts }) => ({
      key,
      label,
      blurb,
      examples,
      accounts: accounts.map(({ code, name, type, subtype }) => ({ code, name, type, subtype })),
    })),
  );

  fastify.post("/api/c/setup/fresh", async (request, reply) => {
    const companyId = request.companyId!;
    const parsed = freshSetupSchema.safeParse(request.body ?? {});
    if (!parsed.success) {
      return reply.code(400).send({
        error: parsed.error.issues.map((i) => i.message).join("; "),
      });
    }
    // Both fields naming DIFFERENT templates is a caller bug — refuse rather
    // than silently prefer one. Same template under both names (including
    // the 'small-business' alias for 'general') is fine.
    const { templateKey, template: legacyTemplate } = parsed.data;
    if (
      templateKey !== undefined && legacyTemplate !== undefined &&
      normalizeTemplateKey(templateKey) !== normalizeTemplateKey(legacyTemplate)
    ) {
      return reply
        .code(CONFLICTING_TEMPLATE_FIELDS.status)
        .send({ error: CONFLICTING_TEMPLATE_FIELDS.error });
    }
    const key = normalizeTemplateKey(templateKey ?? legacyTemplate ?? "general");
    const template = CHART_TEMPLATES_BY_KEY.get(key);
    if (!template) {
      return reply.code(UNKNOWN_TEMPLATE.status).send({ error: UNKNOWN_TEMPLATE.error });
    }

    const client = await db.adminPool.connect();
    try {
      await client.query("BEGIN");

      const existing = await client.query<{ n: string }>(
        "SELECT count(*) AS n FROM accounts WHERE company_id = $1", [companyId],
      );
      if (Number(existing.rows[0]!.n) > 0) {
        await client.query("ROLLBACK");
        return reply.code(ALREADY_HAS_CHART.status).send({ error: ALREADY_HAS_CHART.error });
      }

      for (const account of template.accounts) {
        // subtype: presentation grouping (migration 0016) — new companies
        // stamp fully-tagged charts.
        await client.query(
          "INSERT INTO accounts (company_id, code, name, type, subtype) VALUES ($1, $2, $3, $4, $5)",
          [companyId, account.code, account.name, account.type, account.subtype],
        );
      }

      await client.query("COMMIT");
      return reply.send({ accountsCreated: template.accounts.length });
    } catch (err) {
      await client.query("ROLLBACK").catch(() => {});
      const mapped = mapPgError(err);
      if (mapped.status === 500) {
        request.log.error({ err }, "fresh setup failed");
      }
      return reply.code(mapped.status).send({ error: mapped.message });
    } finally {
      client.release();
    }
  });
}
