import { NextRequest, NextResponse } from "next/server";
import { eq, inArray } from "drizzle-orm";
import { z } from "zod";
import { db } from "@/db";
import { clients, comments, tasks, phases, deliverables, projects } from "@/db/schema";
import { rateLimit } from "@/lib/rate-limit";

const commentSchema = z.object({
  token:       z.string().min(1),
  entity_type: z.enum(["task", "deliverable", "general", "phase"]),
  entity_id:   z.string().min(1),
  body:        z.string().min(1, "Il commento non può essere vuoto").max(2000),
});

export async function POST(request: NextRequest) {
  const ip = request.headers.get("x-forwarded-for") ?? "unknown";
  if (!rateLimit(`comment:${ip}`, 10, 60_000)) {
    return NextResponse.json({ error: "Troppe richieste" }, { status: 429 });
  }

  try {
    const body = await request.json();
    const parsed = commentSchema.safeParse(body);

    if (!parsed.success) {
      return NextResponse.json(
        { error: parsed.error.issues[0].message },
        { status: 400 }
      );
    }

    const { token, entity_type, entity_id, body: commentBody } = parsed.data;

    // Validate token
    const clientRows = await db
      .select({ id: clients.id })
      .from(clients)
      .where(eq(clients.token, token))
      .limit(1);

    if (clientRows.length === 0) {
      return NextResponse.json({ error: "Accesso non consentito" }, { status: 403 });
    }

    const clientId = clientRows[0].id;

    if (entity_type === "general") {
      // General messages: entity_id must be the client's own id
      if (entity_id !== clientId) {
        return NextResponse.json({ error: "Accesso non consentito" }, { status: 403 });
      }
    } else {
      // Scope phases through projects → client
      const clientProjects = await db
        .select({ id: projects.id })
        .from(projects)
        .where(eq(projects.client_id, clientId));
      const projectIds = clientProjects.map((p) => p.id);

      if (projectIds.length === 0) {
        return NextResponse.json({ error: "Accesso non consentito" }, { status: 403 });
      }

      const phasesForClient = await db
        .select({ id: phases.id })
        .from(phases)
        .where(inArray(phases.project_id, projectIds));
      const phaseIds = phasesForClient.map((p) => p.id);

      if (phaseIds.length === 0) {
        return NextResponse.json({ error: "Accesso non consentito" }, { status: 403 });
      }

      const taskRows = await db
        .select({ id: tasks.id })
        .from(tasks)
        .where(inArray(tasks.phase_id, phaseIds));

      if (entity_type === "phase") {
        // Phase: entity_id must be one of the client's phases
        if (!phasesForClient.find((p) => p.id === entity_id)) {
          return NextResponse.json({ error: "Accesso non consentito" }, { status: 403 });
        }
      } else if (entity_type === "task") {
        if (!taskRows.find((r) => r.id === entity_id)) {
          return NextResponse.json({ error: "Accesso non consentito" }, { status: 403 });
        }
      } else {
        // deliverable
        const taskIds = taskRows.map((r) => r.id);
        if (taskIds.length === 0) {
          return NextResponse.json({ error: "Accesso non consentito" }, { status: 403 });
        }
        const delivRows = await db
          .select({ id: deliverables.id })
          .from(deliverables)
          .where(inArray(deliverables.task_id, taskIds));
        if (!delivRows.find((r) => r.id === entity_id)) {
          return NextResponse.json({ error: "Accesso non consentito" }, { status: 403 });
        }
      }
    }

    await db.insert(comments).values({
      entity_type,
      entity_id,
      author: "client",
      body: commentBody,
    });

    return NextResponse.json({ success: true }, { status: 201 });
  } catch (err) {
    console.error("/api/client/comment error:", err);
    return NextResponse.json({ error: "Errore interno" }, { status: 500 });
  }
}