import { useCallback, useRef, useState, useEffect } from "react";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogFooter,
  DialogDescription,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Badge } from "@/components/ui/badge";
import { Separator } from "@/components/ui/separator";
import {
  AlertCircle,
  Loader2,
  Lock,
  Calendar,
  Trash2,
  Search,
  History,
  MessageSquarePlus,
  Clock3,
} from "lucide-react";
import { ColorPicker } from "./ColorPicker";
import { LinkList } from "./LinkList";
import { SearchableSelect } from "./SearchableSelect";
import { SearchableMultiSelect } from "./SearchableMultiSelect";
import { ProjectPricingPanel } from "./ProjectPricingPanel";
import { MESES, type Status } from "@/data/lists";
import { useAppLists } from "@/lib/appLists";
import {
  addProjectActivityNote,
  loadProjectActivities,
  loadProjectPricingItems,
  useProjects,
  type Project,
  type ProjectActivity,
  type ProjectPricingItemInput,
} from "@/lib/store";
import { useAuth } from "@/context/AuthContext";
import { colorHex } from "@/lib/colors";
import { cn } from "@/lib/utils";
import {
  canonicalOptionLabel,
  dedupeOptions,
  ensureOption,
  normalizeOptionKey,
} from "@/lib/optionUtils";
import { toast } from "sonner";

interface Props {
  open: boolean;
  onOpenChange: (v: boolean) => void;
  project?: Project | null; // editar; vacío = crear
  onDelete?: (project: Project) => void;
  deleting?: boolean;
}

const WALMART_CONNECT_CLIENT = "Walmart Connect WMC";
const WMC_CREATE_EXCLUDED_BU = new Set(["wmc"]);
const ACTIVITY_PAGE_SIZE = 15;

function formatActivityDate(timestamp: number) {
  return new Intl.DateTimeFormat("es-DO", {
    day: "2-digit",
    month: "short",
    year: "numeric",
    hour: "numeric",
    minute: "2-digit",
  }).format(new Date(timestamp));
}

function formatActivityDescription(description: string) {
  return description
    .split("\n")
    .map((line) => line.trim())
    .filter(Boolean);
}

function getPricingTotal(items: ProjectPricingItemInput[]) {
  return items.reduce((sum, item) => sum + Number(item.amount || 0), 0);
}

function toPricingInputItems(
  items: Awaited<ReturnType<typeof loadProjectPricingItems>>,
): ProjectPricingItemInput[] {
  return items.map((item) => ({
    id: item.id,
    source: item.source,
    category: item.category,
    serviceName: item.serviceName,
    workType: item.workType,
    complexityLevel: item.complexityLevel,
    referenceLabel: item.referenceLabel,
    referenceMin: item.referenceMin,
    referenceMax: item.referenceMax,
    amount: item.amount,
    description: item.description,
    tariffSectionId: item.tariffSectionId,
    tariffCatalogId: item.tariffCatalogId,
  }));
}

function hasManualInternalAmountOverride(
  savedAmount: number | null | undefined,
  items: ProjectPricingItemInput[],
) {
  if (!items.length || savedAmount == null) return false;

  const cleanSavedAmount = Number(savedAmount);

  if (!Number.isFinite(cleanSavedAmount) || cleanSavedAmount <= 0) return false;

  const calculatedTotal = getPricingTotal(items);

  return Math.abs(cleanSavedAmount - calculatedTotal) > 0.01;
}

function splitBrandValues(value: string | null | undefined, knownBrands: string[] = []) {
  const cleanValue = canonicalOptionLabel(value);

  if (!cleanValue) return [];

  const knownByKey = new Map(
    dedupeOptions(knownBrands).map((brand) => [normalizeOptionKey(brand), brand] as const),
  );
  const exactKnownBrand = knownByKey.get(normalizeOptionKey(cleanValue));

  if (exactKnownBrand) {
    return [exactKnownBrand];
  }

  const parts = cleanValue
    .split(/[,;]/)
    .map((brand) => canonicalOptionLabel(brand))
    .filter(Boolean);

  if (parts.length <= 1) {
    return dedupeOptions([exactKnownBrand || cleanValue]);
  }

  const parsedBrands: string[] = [];
  let index = 0;

  while (index < parts.length) {
    let matchedBrand = "";
    let nextIndex = index + 1;

    for (let end = parts.length; end > index; end -= 1) {
      const candidate = parts.slice(index, end).join(", ");
      const knownBrand = knownByKey.get(normalizeOptionKey(candidate));

      if (knownBrand) {
        matchedBrand = knownBrand;
        nextIndex = end;
        break;
      }
    }

    parsedBrands.push(matchedBrand || parts[index]);
    index = nextIndex;
  }

  return dedupeOptions(parsedBrands);
}

function joinBrandValues(values: string[]) {
  return dedupeOptions(values.map((brand) => canonicalOptionLabel(brand)).filter(Boolean)).join(
    ", ",
  );
}

function splitCountryValues(value: string | null | undefined, knownCountries: string[] = []) {
  const cleanValue = canonicalOptionLabel(value);

  if (!cleanValue) return [];

  const knownByKey = new Map(
    dedupeOptions(knownCountries).map((country) => [normalizeOptionKey(country), country] as const),
  );
  const exactKnownCountry = knownByKey.get(normalizeOptionKey(cleanValue));

  if (exactKnownCountry) {
    return [exactKnownCountry];
  }

  const parts = cleanValue
    .split(/[,;]/)
    .map((country) => canonicalOptionLabel(country))
    .filter(Boolean);

  if (parts.length <= 1) {
    return dedupeOptions([exactKnownCountry || cleanValue]);
  }

  return dedupeOptions(
    parts.map((country) => knownByKey.get(normalizeOptionKey(country)) || country),
  );
}

function joinCountryValues(values: string[]) {
  return dedupeOptions(values.map((country) => canonicalOptionLabel(country)).filter(Boolean)).join(
    ", ",
  );
}

function isWalmartConnectClient(client: string | null | undefined) {
  return normalizeOptionKey(client) === normalizeOptionKey(WALMART_CONNECT_CLIENT);
}

const empty = (): Omit<Project, "id" | "createdAt"> => {
  const now = new Date();
  return {
    nombre: "",
    color: "blue",
    cliente: "",
    bu: "",
    cm: "",
    marca: "",
    solicitante: "",
    comentarios: "",
    briefLink: "",
    propuestaLinks: [],
    afLinks: [],
    status: "",
    monto: null,
    mes: MESES[now.getMonth()],
    anio: now.getFullYear(),
  };
};

export function ProjectDialog({ open, onOpenChange, project, onDelete, deleting = false }: Props) {
  const { add, update } = useProjects();
  const { lists, loading: listsLoading, error: listsError, refresh: refreshLists } = useAppLists();
  const { isGerardo, canDeleteProjects, canManageInternalPricing } = useAuth();
  const isEdit = !!project;

  const [form, setForm] = useState<Omit<Project, "id" | "createdAt">>(empty());
  const [selectedWmcCountries, setSelectedWmcCountries] = useState<string[]>([]);
  const [saving, setSaving] = useState(false);
  const [wmcCountrySearch, setWmcCountrySearch] = useState("");
  const [savingStep, setSavingStep] = useState<string | null>(null);
  const [formError, setFormError] = useState<string | null>(null);
  const [activityItems, setActivityItems] = useState<ProjectActivity[]>([]);
  const [activityLoading, setActivityLoading] = useState(false);
  const [activityError, setActivityError] = useState<string | null>(null);
  const [activityNote, setActivityNote] = useState("");
  const [activityHasMore, setActivityHasMore] = useState(false);
  const [activityLoadingMore, setActivityLoadingMore] = useState(false);
  const [addingActivityNote, setAddingActivityNote] = useState(false);
  const [pricingItems, setPricingItems] = useState<ProjectPricingItemInput[]>([]);
  const [pricingLoading, setPricingLoading] = useState(false);
  const [pricingError, setPricingError] = useState<string | null>(null);
  const [internalAmountManuallyEdited, setInternalAmountManuallyEdited] = useState(false);
  const saveInFlightRef = useRef(false);

  const selectedBrands = splitBrandValues(form.marca, lists.marcas);
  const selectedCountries = splitCountryValues(form.bu, lists.bus);
  const clienteOptions = dedupeOptions(ensureOption(lists.clientes, form.cliente));
  const marcaOptions = dedupeOptions([...lists.marcas, ...selectedBrands]);
  const buOptions = dedupeOptions([...lists.bus, ...selectedCountries]);
  const statusOptions = dedupeOptions(ensureOption(lists.status, form.status)) as Status[];
  const filteredWmcBuOptions = buOptions.filter((b) => {
    const key = normalizeOptionKey(b);
    return !WMC_CREATE_EXCLUDED_BU.has(key) && key.includes(normalizeOptionKey(wmcCountrySearch));
  });
  const pricingTotal = getPricingTotal(pricingItems);

  useEffect(() => {
    setFormError(null);
    setSavingStep(null);

    if (project) {
      const { id: _i, createdAt: _c, ...rest } = project;
      const cleanBu = canonicalOptionLabel(rest.bu);
      setForm({
        ...rest,
        bu: cleanBu,
      });
      setSelectedWmcCountries(cleanBu ? [cleanBu] : []);
      setWmcCountrySearch("");
      setActivityItems([]);
      setActivityHasMore(false);
      setActivityError(null);
      setActivityNote("");
      setPricingItems([]);
      setPricingError(null);
      setInternalAmountManuallyEdited(false);
    } else if (open) {
      setForm(empty());
      setSelectedWmcCountries([]);
      setWmcCountrySearch("");
      setActivityItems([]);
      setActivityHasMore(false);
      setActivityError(null);
      setActivityNote("");
      setPricingItems([]);
      setPricingError(null);
      setInternalAmountManuallyEdited(false);
    }
  }, [project, open]);

  const refreshActivity = useCallback(async () => {
    if (!project?.id) return;

    try {
      setActivityLoading(true);
      setActivityError(null);
      const items = await loadProjectActivities(project.id, ACTIVITY_PAGE_SIZE + 1);
      setActivityItems(items.slice(0, ACTIVITY_PAGE_SIZE));
      setActivityHasMore(items.length > ACTIVITY_PAGE_SIZE);
    } catch (error) {
      console.warn("No se pudo cargar el historial del proyecto:", error);
      setActivityError(
        "No se pudo cargar el historial. Revisa que el SQL de actividad esté ejecutado en Supabase.",
      );
      setActivityItems([]);
      setActivityHasMore(false);
    } finally {
      setActivityLoading(false);
    }
  }, [project?.id]);

  const loadMoreActivity = useCallback(async () => {
    if (!project?.id || activityLoadingMore || !activityHasMore) return;

    try {
      setActivityLoadingMore(true);
      setActivityError(null);
      const items = await loadProjectActivities(
        project.id,
        ACTIVITY_PAGE_SIZE + 1,
        activityItems.length,
      );
      setActivityItems((current) => [...current, ...items.slice(0, ACTIVITY_PAGE_SIZE)]);
      setActivityHasMore(items.length > ACTIVITY_PAGE_SIZE);
    } catch (error) {
      console.warn("No se pudo cargar más historial del proyecto:", error);
      setActivityError("No se pudo cargar más actividad. Inténtalo nuevamente.");
    } finally {
      setActivityLoadingMore(false);
    }
  }, [activityHasMore, activityItems.length, activityLoadingMore, project?.id]);

  useEffect(() => {
    if (!open || !project?.id) return;

    void refreshActivity();
  }, [open, project?.id, refreshActivity]);

  useEffect(() => {
    if (!open || !project?.id || !canManageInternalPricing) return;

    let cancelled = false;

    const loadPricing = async () => {
      try {
        setPricingLoading(true);
        setPricingError(null);
        const items = await loadProjectPricingItems(project.id);
        const inputItems = toPricingInputItems(items);

        if (!cancelled) {
          setInternalAmountManuallyEdited(
            hasManualInternalAmountOverride(project.monto, inputItems),
          );
          setPricingItems(inputItems);
        }
      } catch (error) {
        console.warn("No se pudo cargar el tarifario del proyecto:", error);

        if (!cancelled) {
          setPricingItems([]);
          setPricingError(
            "No se pudieron cargar los costos guardados. Revisa que el SQL del tarifario esté ejecutado en Supabase.",
          );
        }
      } finally {
        if (!cancelled) {
          setPricingLoading(false);
        }
      }
    };

    void loadPricing();

    return () => {
      cancelled = true;
    };
  }, [canManageInternalPricing, open, project?.id, project?.monto]);

  const set = <K extends keyof typeof form>(k: K, v: (typeof form)[K]) =>
    setForm((f) => ({ ...f, [k]: v }));

  // El tarifario es la única fuente editable del monto interno.
  // Conservamos overrides históricos al abrir un proyecto, pero en cuanto
  // el usuario modifica las líneas del tarifario el total vuelve a ser la fuente de verdad.
  const onPricingItemsChange = (nextItems: ProjectPricingItemInput[]) => {
    setInternalAmountManuallyEdited(false);
    setPricingItems(nextItems);

    const nextAmount = Number(getPricingTotal(nextItems).toFixed(2));
    setForm((current) =>
      current.monto === nextAmount ? current : { ...current, monto: nextAmount },
    );
  };

  useEffect(() => {
    if (!canManageInternalPricing || !pricingItems.length || internalAmountManuallyEdited) return;

    const nextAmount = Number(pricingTotal.toFixed(2));
    setForm((current) =>
      current.monto === nextAmount ? current : { ...current, monto: nextAmount },
    );
  }, [canManageInternalPricing, internalAmountManuallyEdited, pricingItems.length, pricingTotal]);

  const getCountryManager = (bu: string) => {
    const direct = lists.buCm[bu];
    if (direct) return direct;

    const buKey = normalizeOptionKey(bu);
    const match = Object.entries(lists.buCm).find(([key]) => normalizeOptionKey(key) === buKey);

    return match?.[1] ?? "";
  };

  // BU → Country Manager automático desde Supabase tablero_cdc_app_lists, con fallback local.
  const onCountries = (countries: string[]) => {
    const cleanCountries = dedupeOptions(
      countries.map((country) => canonicalOptionLabel(country)).filter(Boolean),
    );
    const managers = dedupeOptions(cleanCountries.map(getCountryManager).filter(Boolean));

    setForm((f) => ({
      ...f,
      bu: joinCountryValues(cleanCountries),
      cm: managers.join(", "),
    }));
  };

  const onCliente = (cliente: string) => {
    const cleanCliente = canonicalOptionLabel(cliente);

    setForm((f) => ({
      ...f,
      cliente: cleanCliente,
      ...(isWalmartConnectClient(cleanCliente) && !isEdit
        ? { bu: "", cm: "" }
        : f.cliente && isWalmartConnectClient(f.cliente)
          ? { bu: "", cm: "" }
          : {}),
    }));

    if (!isWalmartConnectClient(cleanCliente)) {
      setSelectedWmcCountries([]);
      setWmcCountrySearch("");
    }
  };

  const isWalmartConnectCreate = !isEdit && isWalmartConnectClient(form.cliente);
  const selectedCreateCountries = isWalmartConnectCreate ? selectedWmcCountries : selectedCountries;
  const isMultiCountryCreate = !isEdit && selectedCreateCountries.length > 1;

  const toggleWmcCountry = (country: string, checked: boolean) => {
    const cleanCountry = canonicalOptionLabel(country);

    setSelectedWmcCountries((current) => {
      if (checked) {
        return dedupeOptions([...current, cleanCountry]);
      }

      return current.filter(
        (item) => normalizeOptionKey(item) !== normalizeOptionKey(cleanCountry),
      );
    });
  };

  const selectedWmcCountryManagers = selectedWmcCountries.map((country) => ({
    country,
    manager: getCountryManager(country),
  }));
  const selectedCountryManagers = selectedCountries.map((country) => ({
    country,
    manager: getCountryManager(country),
  }));

  const requiredOk =
    form.nombre.trim() &&
    form.cliente &&
    form.marca &&
    form.solicitante.trim() &&
    (isWalmartConnectCreate ? selectedWmcCountries.length > 0 : selectedCountries.length > 0);

  const showSaveToast = (result: Awaited<ReturnType<typeof add>>) => {
    if (result.sheetSyncStatus === "synced") {
      toast.success(isEdit ? "Proyecto actualizado" : "Proyecto creado", {
        description: "Se guardó y se sincronizó con el Google Sheet.",
      });
      return;
    }

    if (result.sheetSyncStatus === "skipped") {
      toast.success(isEdit ? "Proyecto actualizado" : "Proyecto creado", {
        description: "Se guardó. La sincronización con Google Sheet no está configurada.",
      });
      return;
    }

    toast.warning("Proyecto guardado con aviso", {
      description: result.sheetSyncMessage,
    });
  };

  const addActivityNote = async () => {
    if (!project?.id || !activityNote.trim() || addingActivityNote) return;

    try {
      setAddingActivityNote(true);
      const result = await addProjectActivityNote(project.id, activityNote);
      set("comentarios", result.comments);
      setActivityNote("");
      await refreshActivity();

      if (result.sheetSyncStatus === "synced") {
        toast.success("Comentario agregado al historial", {
          description: "También se actualizó la columna Comentarios del Google Sheet.",
        });
      } else if (result.sheetSyncStatus === "skipped") {
        toast.success("Comentario agregado al historial", {
          description:
            "Se guardó como comentario interno. La sincronización con Sheet no está configurada.",
        });
      } else {
        toast.warning("Comentario agregado con aviso", {
          description: result.sheetSyncMessage,
        });
      }
    } catch (error) {
      console.error("Error agregando comentario al historial:", error);
      const message =
        error instanceof Error ? error.message : "No se pudo agregar el comentario al historial.";
      toast.error("No se pudo agregar el comentario", { description: message });
    } finally {
      setAddingActivityNote(false);
    }
  };

  const submit = async () => {
    if (!requiredOk || saving || saveInFlightRef.current) return;

    saveInFlightRef.current = true;

    const safeForm = isGerardo
      ? form
      : canManageInternalPricing
        ? {
            ...form,
            status: project?.status ?? "",
          }
        : {
            ...form,
            status: project?.status ?? "",
            monto: project?.monto ?? null,
          };

    try {
      setSaving(true);
      setFormError(null);
      setSavingStep("Guardando y sincronizando con Google Sheet…");

      const createCountries = selectedCreateCountries;
      const createCountryManagers = dedupeOptions(
        createCountries.map(getCountryManager).filter(Boolean),
      );

      const result =
        isEdit && project
          ? await update(project.id, {
              ...safeForm,
              pricingItems: canManageInternalPricing ? pricingItems : undefined,
            })
          : await add({
              ...safeForm,
              // Un proyecto multipaís se conserva como UN solo proyecto.
              // Los países y sus CM viajan en el mismo registro y el workflow
              // existente hace upsert de una única fila usando Project ID.
              bu: joinCountryValues(createCountries),
              cm: createCountryManagers.join(", "),
              id: crypto.randomUUID(),
              createdAt: Date.now(),
              pricingItems: canManageInternalPricing ? pricingItems : undefined,
            });

      showSaveToast(result);

      onOpenChange(false);
    } catch (error) {
      console.error("Error guardando proyecto:", error);
      const message =
        error instanceof Error
          ? error.message
          : "No se pudo guardar el proyecto. Revisa los permisos o intenta de nuevo.";

      setFormError(message);
      toast.error("No se pudo guardar el proyecto", {
        description: message,
      });
    } finally {
      saveInFlightRef.current = false;
      setSaving(false);
      setSavingStep(null);
    }
  };

  const closed = !!form.status;

  return (
    <Dialog
      open={open}
      onOpenChange={(nextOpen) => {
        if (saving || saveInFlightRef.current) return;
        onOpenChange(nextOpen);
      }}
    >
      <DialogContent className="max-w-3xl max-h-[92vh] overflow-y-auto p-0 gap-0">
        {/* Pestaña de color superior */}
        <div
          className="h-2.5 w-full rounded-t-lg"
          style={{ backgroundColor: colorHex(form.color) }}
        />

        <div className="px-7 pt-6 pb-7">
          <DialogHeader className="space-y-3">
            <div className="flex items-start justify-between gap-4">
              <div className="flex-1">
                <DialogTitle className="text-2xl tracking-tight">
                  {isEdit ? form.nombre || "Sin título" : "Nuevo proyecto"}
                </DialogTitle>
                <DialogDescription className="mt-1 flex items-center gap-2 text-xs">
                  <Calendar className="w-3.5 h-3.5" />
                  {form.mes} · {form.anio}
                  {closed && (
                    <Badge variant="secondary" className="ml-2">
                      Cerrado
                    </Badge>
                  )}
                </DialogDescription>
              </div>
            </div>
          </DialogHeader>

          <div className="grid grid-cols-1 md:grid-cols-2 gap-5 mt-6">
            {/* Nombre */}
            <div className="md:col-span-2 space-y-1.5">
              <Label>
                Nombre del proyecto <span className="text-destructive">*</span>
              </Label>
              <Input
                value={form.nombre}
                onChange={(e) => set("nombre", e.target.value)}
                placeholder="Ej: Promoción Día de las Madres"
                className="h-10"
              />
            </div>

            {/* Color */}
            <div className="md:col-span-2 space-y-2">
              <Label>Etiqueta de color</Label>
              <ColorPicker value={form.color} onChange={(c) => set("color", c)} />
            </div>

            <Separator className="md:col-span-2 my-1" />

            {(listsLoading || listsError) && (
              <div
                className={cn(
                  "md:col-span-2 flex items-center justify-between gap-3 rounded-xl border px-3 py-2 text-xs",
                  listsError
                    ? "border-amber-300/50 bg-amber-50 text-amber-900"
                    : "border-border bg-muted/30 text-muted-foreground",
                )}
              >
                <span className="flex items-center gap-2">
                  {listsLoading ? (
                    <>
                      <Loader2 className="h-3.5 w-3.5 animate-spin" />
                      Cargando listas…
                    </>
                  ) : (
                    <>
                      <AlertCircle className="h-3.5 w-3.5" />
                      No se pudieron cargar las listas. Se usaron opciones locales.
                    </>
                  )}
                </span>

                {listsError && (
                  <button
                    type="button"
                    onClick={() => void refreshLists()}
                    className="font-medium text-amber-950 underline-offset-4 hover:underline"
                  >
                    Reintentar
                  </button>
                )}
              </div>
            )}

            {/* Cliente */}
            <div className="space-y-1.5">
              <Label>
                Cliente <span className="text-destructive">*</span>
              </Label>
              <SearchableSelect
                value={form.cliente}
                options={clienteOptions}
                onValueChange={onCliente}
                placeholder="Seleccionar…"
                searchPlaceholder="Buscar cliente…"
                emptyText="No se encontró ese cliente."
              />
            </div>

            {/* Marca */}
            <div className="space-y-1.5">
              <Label>
                Marca <span className="text-destructive">*</span>
              </Label>
              <SearchableMultiSelect
                values={selectedBrands}
                options={marcaOptions}
                onValuesChange={(values) => set("marca", joinBrandValues(values))}
                placeholder="Seleccionar una o varias marcas…"
                searchPlaceholder="Buscar marca…"
                emptyText="No se encontró esa marca."
                summaryLabel="marcas seleccionadas"
              />
            </div>

            {/* BU */}
            {isWalmartConnectCreate ? (
              <div className="md:col-span-2 space-y-2 rounded-xl border border-primary/20 bg-primary/5 p-3">
                <div className="flex flex-col gap-1 sm:flex-row sm:items-center sm:justify-between">
                  <Label>
                    BU Solicita (Países) <span className="text-destructive">*</span>
                  </Label>
                  <span className="text-xs font-medium text-primary">
                    {selectedWmcCountries.length} seleccionado(s)
                  </span>
                </div>
                <p className="text-xs text-muted-foreground">
                  Para Walmart Connect WMC puedes seleccionar varios países. Todos quedarán
                  asociados a un solo proyecto y una sola fila del Sheet.
                </p>
                <div className="relative">
                  <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
                  <Input
                    value={wmcCountrySearch}
                    onChange={(e) => setWmcCountrySearch(e.target.value)}
                    placeholder="Buscar país…"
                    className="h-9 pl-9 bg-card"
                  />
                </div>
                <div className="grid grid-cols-1 gap-2 sm:grid-cols-2 lg:grid-cols-3">
                  {filteredWmcBuOptions.map((b) => {
                    const checked = selectedWmcCountries.some(
                      (country) => normalizeOptionKey(country) === normalizeOptionKey(b),
                    );
                    const manager = getCountryManager(b);

                    return (
                      <label
                        key={b}
                        className={cn(
                          "flex cursor-pointer items-start gap-2 rounded-lg border bg-card px-3 py-2 text-sm transition-colors",
                          checked
                            ? "border-primary/50 bg-primary/10"
                            : "border-border hover:bg-muted/40",
                        )}
                      >
                        <Checkbox
                          checked={checked}
                          onCheckedChange={(value) => toggleWmcCountry(b, value === true)}
                          className="mt-0.5"
                        />
                        <span className="leading-tight">
                          <span className="block font-medium">{b}</span>
                          <span className="text-xs text-muted-foreground">
                            CM: {manager || "—"}
                          </span>
                        </span>
                      </label>
                    );
                  })}
                </div>
              </div>
            ) : (
              <div className="md:col-span-2 space-y-1.5">
                <Label>
                  BU Solicita (Países) <span className="text-destructive">*</span>
                </Label>
                <SearchableMultiSelect
                  values={selectedCountries}
                  options={buOptions}
                  onValuesChange={onCountries}
                  placeholder="Seleccionar uno o varios países…"
                  searchPlaceholder="Buscar país…"
                  emptyText="No se encontró ese país."
                  summaryLabel="países seleccionados"
                />
                <p className="text-xs text-muted-foreground">
                  Si seleccionas varios países, todos quedarán asociados a un solo proyecto y una sola
                  fila del Sheet.
                </p>
              </div>
            )}

            {/* CM autocompletado */}
            <div className={cn("space-y-1.5", isWalmartConnectCreate && "md:col-span-2")}>
              <Label className="flex items-center gap-1.5">
                Country Manager <span className="text-xs text-muted-foreground">(automático)</span>
              </Label>
              {isWalmartConnectCreate ? (
                <div className="min-h-10 rounded-md border border-border bg-muted/30 px-3 py-2 text-sm">
                  {selectedWmcCountryManagers.length === 0 ? (
                    <span className="text-muted-foreground">Selecciona uno o más países.</span>
                  ) : (
                    <div className="flex flex-wrap gap-1.5">
                      {selectedWmcCountryManagers.map(({ country, manager }) => (
                        <Badge key={country} variant="secondary" className="font-normal">
                          {country}: {manager || "—"}
                        </Badge>
                      ))}
                    </div>
                  )}
                </div>
              ) : (
                <div className="min-h-10 rounded-md border border-border bg-muted/30 px-3 py-2 text-sm">
                  {selectedCountryManagers.length === 0 ? (
                    <span className="text-muted-foreground">Selecciona uno o más países.</span>
                  ) : (
                    <div className="flex flex-wrap gap-1.5">
                      {selectedCountryManagers.map(({ country, manager }) => (
                        <Badge key={country} variant="secondary" className="font-normal">
                          {country}: {manager || "—"}
                        </Badge>
                      ))}
                    </div>
                  )}
                </div>
              )}
            </div>

            {isMultiCountryCreate && canManageInternalPricing && (
              <div className="md:col-span-2 rounded-xl border border-amber-300/50 bg-amber-50 px-3 py-2 text-xs text-amber-900">
                Si seleccionas varios países, el total de la estimación interna corresponde al proyecto
                completo y no se multiplica por país.
              </div>
            )}

            {/* Solicitante */}
            <div className="space-y-1.5">
              <Label>
                Solicitado por <span className="text-destructive">*</span>
              </Label>
              <Input
                value={form.solicitante}
                onChange={(e) => set("solicitante", e.target.value)}
                placeholder="Nombre de quien solicita"
                className="h-10"
              />
            </div>

            <ProjectActivityPanel
              isEdit={isEdit}
              items={activityItems}
              loading={activityLoading}
              error={activityError}
              note={activityNote}
              hasMore={activityHasMore}
              loadingMore={activityLoadingMore}
              addingNote={addingActivityNote}
              onNoteChange={setActivityNote}
              onAddNote={addActivityNote}
              onRefresh={refreshActivity}
              onLoadMore={loadMoreActivity}
            />

            <Separator className="md:col-span-2 my-1" />

            {/* Brief link único */}
            <div className="md:col-span-2 space-y-1.5">
              <Label>
                Link del Brief{" "}
                <span className="text-xs text-muted-foreground font-normal">
                  (carpeta de Fulgencio)
                </span>
              </Label>
              <Input
                value={form.briefLink}
                onChange={(e) => set("briefLink", e.target.value)}
                placeholder="https://drive.google.com/…"
                className="h-10"
              />
            </div>

            {/* Propuestas */}
            <div className="md:col-span-2">
              <LinkList
                label="Links de Propuestas"
                links={form.propuestaLinks}
                onChange={(v) => set("propuestaLinks", v)}
                emptyText="Aún no hay propuestas. Pega tantos links como necesites."
              />
            </div>

            {/* Artes Finales */}
            <div className="md:col-span-2">
              <LinkList
                label="Links de Artes Finales"
                prefix="AF"
                links={form.afLinks}
                onChange={(v) => set("afLinks", v)}
                emptyText="Aún no hay artes finales."
              />
            </div>

            <Separator className="md:col-span-2 my-1" />

            {canManageInternalPricing && (
              <ProjectPricingPanel
                client={form.cliente}
                items={pricingItems}
                onChange={onPricingItemsChange}
                loading={pricingLoading}
                error={pricingError}
              />
            )}

            <Separator className="md:col-span-2 my-1" />

            {/* Status: Director Creativo edita; el equipo solo visualiza */}
            <div className="space-y-1.5">
              <Label className="flex items-center gap-1.5 pl-1">
                Estatus
                {!isGerardo && <Lock className="w-3 h-3 text-muted-foreground" />}
              </Label>

              {isGerardo ? (
                <Select
                  value={form.status || "_none"}
                  onValueChange={(v) => set("status", (v === "_none" ? "" : v) as Status | "")}
                >
                  <SelectTrigger className="h-10">
                    <SelectValue placeholder="Sin estatus" />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value="_none">Sin estatus</SelectItem>
                    {statusOptions.map((s) => (
                      <SelectItem key={s} value={s}>
                        {s}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              ) : (
                <div className="h-10 px-3 flex items-center rounded-md border border-border bg-muted/30 text-sm text-foreground">
                  {form.status || "Sin estatus"}
                </div>
              )}

              {!isGerardo && (
                <p className="pl-1 text-[11px] text-muted-foreground">
                  Solo el Director Creativo puede cambiar el estatus.
                </p>
              )}
            </div>

          </div>

          {(formError || savingStep) && (
            <div
              className={cn(
                "mt-5 flex items-start gap-2 rounded-xl border px-3 py-2 text-sm",
                formError
                  ? "border-destructive/30 bg-destructive/5 text-destructive"
                  : "border-primary/20 bg-primary/5 text-primary",
              )}
            >
              {formError ? (
                <AlertCircle className="mt-0.5 h-4 w-4 flex-shrink-0" />
              ) : (
                <Loader2 className="mt-0.5 h-4 w-4 flex-shrink-0 animate-spin" />
              )}
              <span>{formError || savingStep}</span>
            </div>
          )}
        </div>

        <DialogFooter className="px-7 py-4 border-t bg-muted/30 rounded-b-lg sm:justify-between">
          <div className="flex w-full flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
            <div>
              {isEdit && project && canDeleteProjects && onDelete && (
                <Button
                  type="button"
                  variant="destructive"
                  onClick={() => onDelete(project)}
                  disabled={saving || deleting}
                  className="gap-1.5 rounded-full"
                >
                  {deleting ? (
                    <Loader2 className="h-4 w-4 animate-spin" />
                  ) : (
                    <Trash2 className="h-4 w-4" />
                  )}
                  {deleting ? "Eliminando…" : "Eliminar proyecto"}
                </Button>
              )}
            </div>

            <div className="flex justify-end gap-2">
              <Button
                variant="ghost"
                onClick={() => {
                  if (saving || saveInFlightRef.current) return;
                  onOpenChange(false);
                }}
                disabled={saving || deleting}
              >
                Cancelar
              </Button>
              <Button onClick={submit} disabled={!requiredOk || saving || deleting}>
                {saving && <Loader2 className="mr-1.5 h-4 w-4 animate-spin" />}
                {saving
                  ? "Guardando…"
                  : isEdit
                    ? "Guardar cambios"
                    : "Crear proyecto"}
              </Button>
            </div>
          </div>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

function ProjectActivityPanel({
  isEdit,
  items,
  loading,
  error,
  note,
  hasMore,
  loadingMore,
  addingNote,
  onNoteChange,
  onAddNote,
  onRefresh,
  onLoadMore,
}: {
  isEdit: boolean;
  items: ProjectActivity[];
  loading: boolean;
  error: string | null;
  note: string;
  hasMore: boolean;
  loadingMore: boolean;
  addingNote: boolean;
  onNoteChange: (value: string) => void;
  onAddNote: () => Promise<void>;
  onRefresh: () => Promise<void>;
  onLoadMore: () => Promise<void>;
}) {
  return (
    <div className="md:col-span-2 rounded-2xl border border-border bg-muted/20 p-4">
      <div className="mb-3 flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between">
        <div className="flex items-start gap-2.5">
          <span className="mt-0.5 flex h-8 w-8 items-center justify-center rounded-full bg-primary/10 text-primary">
            <History className="h-4 w-4" />
          </span>
          <div>
            <h3 className="text-sm font-semibold">Actividad del proyecto</h3>
            <p className="text-xs text-muted-foreground">
              Comentarios y movimientos recientes con fecha.
            </p>
          </div>
        </div>

        {isEdit && (
          <Button
            type="button"
            variant="ghost"
            size="sm"
            onClick={() => void onRefresh()}
            disabled={loading}
            className="h-8 rounded-full px-2.5 text-xs text-muted-foreground hover:text-foreground"
          >
            {loading ? <Loader2 className="mr-1 h-3.5 w-3.5 animate-spin" /> : null}
            Actualizar
          </Button>
        )}
      </div>

      {!isEdit ? (
        <div className="rounded-xl border border-dashed border-border bg-card/70 px-3 py-3 text-sm text-muted-foreground">
          El historial se activará cuando el proyecto sea creado.
        </div>
      ) : (
        <div className="space-y-3">
          <div className="rounded-xl border border-border bg-card p-3">
            <Label className="text-xs font-medium">Agregar comentario o solicitud adicional</Label>
            <div className="mt-2 flex flex-col gap-2 sm:flex-row">
              <Textarea
                value={note}
                onChange={(event) => onNoteChange(event.target.value)}
                placeholder="Ej: CM pidió ajustar artes, agregar una marca o cambiar una fecha…"
                rows={2}
                className="min-h-[64px] flex-1 resize-none"
              />
              <Button
                type="button"
                onClick={() => void onAddNote()}
                disabled={!note.trim() || addingNote}
                className="gap-1.5 rounded-full sm:self-end"
              >
                {addingNote ? (
                  <Loader2 className="h-4 w-4 animate-spin" />
                ) : (
                  <MessageSquarePlus className="h-4 w-4" />
                )}
                Agregar
              </Button>
            </div>
          </div>

          {error && (
            <div className="flex items-start gap-2 rounded-xl border border-amber-300/50 bg-amber-50 px-3 py-2 text-xs text-amber-900">
              <AlertCircle className="mt-0.5 h-3.5 w-3.5 flex-shrink-0" />
              <span>{error}</span>
            </div>
          )}

          {loading && items.length === 0 ? (
            <div className="flex items-center gap-2 rounded-xl border border-border bg-card px-3 py-3 text-sm text-muted-foreground">
              <Loader2 className="h-4 w-4 animate-spin" />
              Cargando actividad…
            </div>
          ) : items.length === 0 ? (
            <div className="rounded-xl border border-border bg-card px-3 py-3 text-sm text-muted-foreground">
              Aún no hay actividad registrada. Los próximos comentarios o cambios quedarán aquí.
            </div>
          ) : (
            <div className="space-y-2">
              <div className="flex items-center justify-between gap-3 px-0.5 text-[11px] text-muted-foreground">
                <span>Mostrando los movimientos más recientes.</span>
                <span>{items.length} visibles</span>
              </div>

              <div className="max-h-[440px] space-y-2 overflow-y-auto pr-1">
                {items.map((item) => {
                  const lines = formatActivityDescription(item.description);

                  return (
                    <div
                      key={item.id}
                      className="rounded-xl border border-border bg-card px-3 py-3 shadow-sm"
                    >
                      <div className="flex flex-col gap-1 sm:flex-row sm:items-start sm:justify-between">
                        <div>
                          <p className="text-sm font-medium">{item.title}</p>
                          <p className="text-xs text-muted-foreground">
                            {item.actorName}
                            {item.actorEmail ? ` · ${item.actorEmail}` : ""}
                          </p>
                        </div>
                        <span className="inline-flex items-center gap-1 text-xs text-muted-foreground">
                          <Clock3 className="h-3.5 w-3.5" />
                          {formatActivityDate(item.createdAt)}
                        </span>
                      </div>

                      {lines.length > 0 && (
                        <div className="mt-2 space-y-1 text-sm text-muted-foreground">
                          {lines.map((line) => (
                            <p key={line}>{line}</p>
                          ))}
                        </div>
                      )}
                    </div>
                  );
                })}
              </div>

              {hasMore && (
                <div className="flex justify-center pt-1">
                  <Button
                    type="button"
                    variant="outline"
                    size="sm"
                    onClick={() => void onLoadMore()}
                    disabled={loadingMore}
                    className="rounded-full"
                  >
                    {loadingMore ? <Loader2 className="mr-1.5 h-4 w-4 animate-spin" /> : null}
                    {loadingMore ? "Cargando…" : "Cargar más"}
                  </Button>
                </div>
              )}
            </div>
          )}
        </div>
      )}
    </div>
  );
}
