import { http, HttpResponse } from "msw";
import { z } from "zod";
import { MONTHLY_VOLUME_BUCKETS } from "@rubis/shared";
import { mockDb } from "../db";
import { userIdFromAuthHeader } from "./auth";

const apiBase = "*/api/v1";

const updateProfileSchema = z
  .object({
    fullName: z.string().min(2).max(120).optional(),
    email: z.string().email().optional(),
    signature: z.string().max(500).optional(),
  })
  .strict();

const updateOrgSchema = z
  .object({
    name: z.string().min(2).max(120).optional(),
    siret: z
      .string()
      .regex(/^\d{14}$/u)
      .or(z.literal(""))
      .optional()
      .transform((v) => (v === "" || v === undefined ? null : v)),
    monthlyVolumeBucket: z.enum(MONTHLY_VOLUME_BUCKETS).optional(),
  })
  .strict();

function unauthenticated() {
  return HttpResponse.json(
    { errors: [{ code: "unauthenticated", message: "Non authentifié" }] },
    { status: 401 },
  );
}

function notFound() {
  return HttpResponse.json(
    { errors: [{ code: "not_found", message: "Ressource introuvable" }] },
    { status: 404 },
  );
}

function validationError(issues: z.ZodIssue[]) {
  return HttpResponse.json(
    {
      errors: issues.map((i) => ({
        code: "validation_failed",
        message: i.message,
        field: i.path.join("."),
      })),
    },
    { status: 422 },
  );
}

export const onboardingHandlers = [
  // PATCH /api/v1/account/profile — fullName, email, signature
  http.patch(`${apiBase}/account/profile`, async ({ request }) => {
    const userId = userIdFromAuthHeader(request.headers.get("authorization"));
    if (!userId) return unauthenticated();

    const json = await request.json();
    const parsed = updateProfileSchema.safeParse(json);
    if (!parsed.success) return validationError(parsed.error.issues);

    const updated = mockDb.updateUser(userId, parsed.data);
    if (!updated) return notFound();
    return HttpResponse.json({ data: updated });
  }),

  // GET /api/v1/organizations/me — l'organisation de l'utilisateur courant
  http.get(`${apiBase}/organizations/me`, ({ request }) => {
    const userId = userIdFromAuthHeader(request.headers.get("authorization"));
    if (!userId) return unauthenticated();
    const user = mockDb.findUserById(userId);
    if (!user) return notFound();
    const org = mockDb.findOrgById(user.organizationId);
    if (!org) return notFound();
    return HttpResponse.json({ data: org });
  }),

  // PATCH /api/v1/organizations/me — pour l'organisation de l'utilisateur courant
  http.patch(`${apiBase}/organizations/me`, async ({ request }) => {
    const userId = userIdFromAuthHeader(request.headers.get("authorization"));
    if (!userId) return unauthenticated();
    const user = mockDb.findUserById(userId);
    if (!user) return notFound();

    const json = await request.json();
    const parsed = updateOrgSchema.safeParse(json);
    if (!parsed.success) return validationError(parsed.error.issues);

    const updated = mockDb.updateOrg(user.organizationId, parsed.data);
    if (!updated) return notFound();
    return HttpResponse.json({ data: updated });
  }),
];
