import { asc, eq } from "drizzle-orm";
import { apiError, requirePortalProfile } from "../_auth";
import { auditLogs, dues, members } from "../../../db/schema";

const AVENUES = new Set(["Avenue des Mimosas", "Avenue des Lauriers", "Avenue des Oliviers", "Bureau ASL"]);

function cleanText(value: unknown, max = 160) {
  return typeof value === "string" ? value.trim().slice(0, max) : "";
}

export async function GET() {
  try {
    const { profile, db } = await requirePortalProfile();
    if (profile.role !== "bureau") return Response.json({ members: [profile] });
    const rows = await db
      .select()
      .from(members)
      .orderBy(asc(members.avenue), asc(members.addressNumber), asc(members.lastName));
    return Response.json({ members: rows });
  } catch (error) {
    return apiError(error);
  }
}

export async function POST(request: Request) {
  try {
    const { user, db } = await requirePortalProfile(true);
    const payload = (await request.json()) as Record<string, unknown>;
    const firstName = cleanText(payload.firstName, 80);
    const lastName = cleanText(payload.lastName, 80);
    const email = cleanText(payload.email, 180).toLowerCase();
    const avenue = cleanText(payload.avenue, 80);
    const lotReference = cleanText(payload.lotReference, 40).toUpperCase();
    if (!firstName || !lastName || !email || !email.includes("@") || !lotReference || !AVENUES.has(avenue)) {
      return Response.json({ error: "Nom, e-mail, référence de lot et avenue valides sont obligatoires." }, { status: 400 });
    }
    const role = payload.role === "bureau" ? "bureau" : "resident";
    const accessStatus = payload.accessStatus === "active" ? "active" : "invited";
    const [member] = await db
      .insert(members)
      .values({
        lotReference,
        firstName,
        lastName,
        email,
        phone: cleanText(payload.phone, 40),
        avenue,
        addressNumber: cleanText(payload.addressNumber, 20),
        role,
        accessStatus,
        notes: cleanText(payload.notes, 800),
      })
      .returning();

    const amountCents = Number.isFinite(Number(payload.amountCents)) ? Math.max(0, Math.round(Number(payload.amountCents))) : 32000;
    if (role === "resident" && amountCents > 0) {
      await db.insert(dues).values({ memberId: member.id, year: 2026, amountCents, dueDate: "2026-09-30" });
    }
    await db.insert(auditLogs).values({ actorEmail: user.email, action: "member.created", entityType: "member", entityId: member.id, detail: `${lotReference} · ${email}` });
    return Response.json({ member }, { status: 201 });
  } catch (error) {
    return apiError(error);
  }
}

export async function PATCH(request: Request) {
  try {
    const { user, db } = await requirePortalProfile(true);
    const payload = (await request.json()) as Record<string, unknown>;
    const id = Number(payload.id);
    if (!Number.isInteger(id) || id <= 0) return Response.json({ error: "Fiche invalide." }, { status: 400 });
    const updates: Partial<typeof members.$inferInsert> = { updatedAt: new Date().toISOString() };
    if (payload.firstName !== undefined) updates.firstName = cleanText(payload.firstName, 80);
    if (payload.lastName !== undefined) updates.lastName = cleanText(payload.lastName, 80);
    if (payload.email !== undefined) updates.email = cleanText(payload.email, 180).toLowerCase();
    if (payload.phone !== undefined) updates.phone = cleanText(payload.phone, 40);
    if (payload.addressNumber !== undefined) updates.addressNumber = cleanText(payload.addressNumber, 20);
    if (payload.notes !== undefined) updates.notes = cleanText(payload.notes, 800);
    if (payload.avenue !== undefined && AVENUES.has(cleanText(payload.avenue, 80))) updates.avenue = cleanText(payload.avenue, 80);
    if (payload.role === "resident" || payload.role === "bureau") updates.role = payload.role;
    if (["pending", "invited", "active", "suspended"].includes(String(payload.accessStatus))) updates.accessStatus = payload.accessStatus as "pending" | "invited" | "active" | "suspended";
    const [member] = await db.update(members).set(updates).where(eq(members.id, id)).returning();
    if (!member) return Response.json({ error: "Fiche introuvable." }, { status: 404 });
    await db.insert(auditLogs).values({ actorEmail: user.email, action: "member.updated", entityType: "member", entityId: member.id, detail: member.lotReference });
    return Response.json({ member });
  } catch (error) {
    return apiError(error);
  }
}
