import { NextResponse } from "next/server";
import { DepartmentKey, MarketingInitiativeType } from "@prisma/client";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import { canManageProjects, mapProjectInitiative } from "@/lib/projects/persistence";
import { marketingLocations } from "@/lib/projects/mock";

type CreateInitiativeBody = {
  name?: string;
  type?: string;
  isGlobal?: boolean;
  plannedCost?: number;
  actualCost?: number;
  targetTicketPrice?: number;
  actualTicketPrice?: number;
  metrics?: {
    target?: number;
    actual?: number;
    ticketsTarget?: number;
    ticketsActual?: number;
    revenueTarget?: number;
    revenueActual?: number;
  };
  metricSelection?: {
    score?: boolean;
    tickets?: boolean;
    revenue?: boolean;
  };
  locationIds?: string[];
  dueDate?: string;
};

const ALLOWED_TYPES = new Set<MarketingInitiativeType>([
  MarketingInitiativeType.evento,
  MarketingInitiativeType.campania,
  MarketingInitiativeType.cambio,
  MarketingInitiativeType.implementacion,
  MarketingInitiativeType.otro,
]);

function parseDate(value: string | undefined): Date | null {
  if (!value) {
    return null;
  }

  const parsed = new Date(value);
  if (Number.isNaN(parsed.getTime())) {
    return null;
  }

  return parsed;
}

export async function POST(request: Request) {
  const session = await getServerSession(authOptions);
  if (!session?.user) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  if (!canManageProjects(session.user.role, session.user.department)) {
    return NextResponse.json({ error: "Only owners or projects leaders can create initiatives." }, { status: 403 });
  }

  const body = (await request.json()) as CreateInitiativeBody;
  const name = body.name?.trim() || "Nueva iniciativa";
  const type = (body.type as MarketingInitiativeType | undefined) ?? MarketingInitiativeType.otro;
  const isGlobal = Boolean(body.isGlobal);
  const metricSelection = {
    score: body.metricSelection?.score ?? true,
    tickets: body.metricSelection?.tickets ?? false,
    revenue: body.metricSelection?.revenue ?? false,
  };
  const dueDate = parseDate(body.dueDate) ?? new Date(Date.now() + 14 * 24 * 60 * 60 * 1000);
  const safeMetrics = {
    target: Number(body.metrics?.target ?? 0) || 0,
    actual: Number(body.metrics?.actual ?? 0) || 0,
    ticketsTarget: Math.round(Number(body.metrics?.ticketsTarget ?? 0) || 0),
    ticketsActual: Math.round(Number(body.metrics?.ticketsActual ?? 0) || 0),
    revenueTarget: Number(body.metrics?.revenueTarget ?? 0) || 0,
    revenueActual: Number(body.metrics?.revenueActual ?? 0) || 0,
  };
  const plannedCost = Number(body.plannedCost ?? 0) || 0;
  const actualCost = Number(body.actualCost ?? 0) || 0;
  const targetTicketPrice = Number(body.targetTicketPrice ?? 0) || 0;
  const actualTicketPrice = Number(body.actualTicketPrice ?? 0) || 0;

  if (!ALLOWED_TYPES.has(type)) {
    return NextResponse.json({ error: "Invalid initiative type." }, { status: 400 });
  }

  if (!metricSelection.score && !metricSelection.tickets && !metricSelection.revenue) {
    return NextResponse.json({ error: "At least one KPI target must be enabled." }, { status: 400 });
  }
  if (
    safeMetrics.target < 0 ||
    safeMetrics.ticketsTarget < 0 ||
    safeMetrics.ticketsActual < 0 ||
    safeMetrics.revenueTarget < 0 ||
    plannedCost < 0 ||
    actualCost < 0 ||
    targetTicketPrice < 0 ||
    actualTicketPrice < 0
  ) {
    return NextResponse.json(
      { error: "Planned goals, counts, prices and costs must be non-negative. Actual outcomes can be negative." },
      { status: 400 }
    );
  }

  const locationSet = new Set(marketingLocations.map((location) => location.id));
  const requestedLocationIds = (body.locationIds ?? []).filter((value) => locationSet.has(value));
  const locationIds = isGlobal ? [] : requestedLocationIds.length > 0 ? requestedLocationIds : [marketingLocations[0].id];
  const isEvent = type === MarketingInitiativeType.evento;
  const revenueTarget = isEvent ? safeMetrics.ticketsTarget * targetTicketPrice : safeMetrics.revenueTarget;
  const revenueActual = isEvent ? safeMetrics.ticketsActual * actualTicketPrice : safeMetrics.revenueActual;

  const initiative = await prisma.marketingInitiative.create({
    data: {
      department: DepartmentKey.proyectos,
      name,
      type,
      status: "planning",
      isGlobal,
      trackScore: metricSelection.score,
      trackTickets: metricSelection.tickets,
      trackRevenue: metricSelection.revenue,
      target: safeMetrics.target,
      actual: safeMetrics.actual,
      ticketsTarget: safeMetrics.ticketsTarget,
      ticketsActual: safeMetrics.ticketsActual,
      revenueTarget,
      revenueActual,
      plannedCost,
      actualCost,
      targetTicketPrice,
      actualTicketPrice,
      projectsSchemaVersion: 2,
      ownerId: session.user.id,
      dueDate,
      updatedById: session.user.id,
      updatedByName: session.user.name ?? session.user.email,
      ...(locationIds.length > 0
        ? {
            locations: {
              createMany: {
                data: locationIds.map((locationId) => ({ locationId })),
              },
            },
          }
        : {}),
      edits: {
        create: {
          editedById: session.user.id,
          editedByName: session.user.name ?? session.user.email ?? "Usuario",
          summary: "Creación de iniciativa",
        },
      },
    },
    include: {
      contributors: true,
      locations: true,
      evidenceLinks: true,
      tasks: {
        include: { evidenceLinks: true },
      },
      milestones: {
        include: {
          checkpoints: {
            orderBy: { createdAt: "asc" },
          },
        },
        orderBy: [{ sortOrder: "asc" }, { dueDate: "asc" }],
      },
    },
  });

  return NextResponse.json({
    ok: true,
    initiative: mapProjectInitiative(initiative),
  });
}
