/**
 * Plan configuration REST endpoints.
 *
 * GET    /plans          — list all plans (from DB or defaults)
 * GET    /plans/:name    — get plan by name
 * POST   /plans          — create plan
 * PUT    /plans/:id      — update plan
 * POST   /plans/seed     — seed default plans into DB
 */

import type { FastifyInstance } from 'fastify';
import { getRequestProductId } from '../../lib/request-context.js';
import { BadRequestError, NotFoundError } from '../../lib/errors.js';
import * as repo from './repository.js';
import { CreatePlanSchema, UpdatePlanSchema, type PlanConfig } from './types.js';

export async function planRoutes(app: FastifyInstance) {
  // List plans
  app.get('/plans', async req => {
    const productId = getRequestProductId(req);
    return { plans: await repo.list(productId) };
  });

  // Get by name
  app.get('/plans/:name', async req => {
    const { name } = req.params as { name: string };
    const productId = getRequestProductId(req);
    const plan = await repo.getByName(name, productId);
    if (!plan) {
      // Fall back to defaults
      const defaults = repo.getDefaults(productId);
      const def = defaults.find(d => d.name === name);
      if (!def) throw new NotFoundError('Plan not found');
      return def;
    }
    return plan;
  });

  // Create plan
  app.post('/plans', async (req, reply) => {
    const parsed = CreatePlanSchema.safeParse(req.body);
    if (!parsed.success) {
      throw new BadRequestError(parsed.error.issues.map(i => i.message).join('; '));
    }
    const input = parsed.data;
    const now = new Date().toISOString();
    const productId = getRequestProductId(req);
    const doc: PlanConfig = {
      id: `plan_${productId}_${input.name}`,
      productId,
      ...input,
      createdAt: now,
      updatedAt: now,
    };
    const created = await repo.create(doc);
    reply.code(201);
    return created;
  });

  // Update plan
  app.put('/plans/:id', async req => {
    const { id } = req.params as { id: string };
    const parsed = UpdatePlanSchema.safeParse(req.body);
    if (!parsed.success) {
      throw new BadRequestError(parsed.error.issues.map(i => i.message).join('; '));
    }
    const updated = await repo.update(id, parsed.data);
    if (!updated) throw new NotFoundError('Plan not found');
    return updated;
  });

  // Seed defaults
  app.post('/plans/seed', async (req, reply) => {
    const productId = getRequestProductId(req);
    const defaults = repo.getDefaults(productId);
    const results: PlanConfig[] = [];
    for (const plan of defaults) {
      const existing = await repo.getByName(plan.name, productId);
      if (!existing) {
        results.push(await repo.create(plan));
      } else {
        results.push(existing);
      }
    }
    reply.code(201);
    return { plans: results };
  });
}
