"use client";

import React, { useCallback, useMemo, useRef, useState } from "react";
import { ArrowDown, ArrowRight, CircleSlash2, GitBranch } from "lucide-react";
import { Button } from "@/components/ui/button";
import { useBuilderDispatch, useBuilderState } from "@/lib/admin/builder/context";
import { formatOverridePath, listOverridePaths } from "@/lib/admin/builder/variants";
import { AddScreenDialog } from "@/components/admin/builder/AddScreenDialog";
import type {
  ListOptionDefinition,
  NavigationConditionDefinition,
  ScreenDefinition,
  ScreenVariantDefinition,
} from "@/lib/funnel/types";
import { cn } from "@/lib/utils";

function DropIndicator({ isActive }: { isActive: boolean }) {
  return (
    <div
      className={cn(
        "mx-4 h-9 rounded-xl border-2 border-dashed border-primary/50 bg-primary/10 transition-all",
        isActive ? "opacity-100" : "pointer-events-none opacity-0"
      )}
    />
  );
}

const TEMPLATE_TITLES: Record<ScreenDefinition["template"], string> = {
  list: "Список",
  form: "Форма",
  info: "Инфо",
  date: "Дата",
  coupon: "Купон",
};

const OPERATOR_LABELS: Record<Exclude<NavigationConditionDefinition["operator"], undefined>, string> = {
  includesAny: "любой из",
  includesAll: "все из",
  includesExactly: "точное совпадение",
};

interface TransitionRowProps {
  type: "default" | "branch" | "end";
  label: string;
  targetLabel?: string;
  targetIndex?: number | null;
  optionSummaries?: { id: string; label: string }[];
  operator?: string;
}

function TransitionRow({
  type,
  label,
  targetLabel,
  targetIndex,
  optionSummaries = [],
  operator,
}: TransitionRowProps) {
  const Icon = type === "branch" ? GitBranch : type === "end" ? CircleSlash2 : ArrowDown;

  return (
    <div
      className={cn(
        "relative flex items-start gap-3 rounded-xl border p-3 text-xs transition-colors",
        type === "branch"
          ? "border-primary/40 bg-primary/5"
          : "border-border/60 bg-background/90"
      )}
    >
      <div
        className={cn(
          "mt-0.5 flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full",
          type === "branch" ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"
        )}
      >
        <Icon className="h-4 w-4" />
      </div>
      <div className="flex flex-1 flex-col gap-2">
        <div className="flex flex-wrap items-center gap-2">
          <span
            className={cn(
              "text-[11px] font-semibold uppercase tracking-wide",
              type === "branch" ? "text-primary" : "text-muted-foreground"
            )}
          >
            {label}
          </span>
          {operator && (
            <span className="rounded-full bg-primary/10 px-2 py-0.5 text-[10px] uppercase tracking-wide text-primary">
              {operator}
            </span>
          )}
        </div>
        {optionSummaries.length > 0 && (
          <div className="flex flex-wrap gap-1.5">
            {optionSummaries.map((option) => (
              <span
                key={option.id}
                className="rounded-full bg-primary/10 px-2 py-1 text-[11px] font-medium text-primary"
              >
                {option.label}
              </span>
            ))}
          </div>
        )}
        <div className="flex items-center gap-2 text-sm text-foreground">
          {type === "end" ? (
            <span className="text-muted-foreground">Завершение воронки</span>
          ) : (
            <>
              <ArrowRight className="h-4 w-4 text-muted-foreground" />
              {typeof targetIndex === "number" && (
                <span className="inline-flex items-center rounded-md bg-muted px-2 py-0.5 text-[10px] font-semibold uppercase text-muted-foreground">
                  #{targetIndex + 1}
                </span>
              )}
              <span className="font-semibold">
                {targetLabel ?? "Не выбрано"}
              </span>
            </>
          )}
        </div>
      </div>
    </div>
  );
}

function TemplateSummary({ screen }: { screen: ScreenDefinition }) {
  switch (screen.template) {
    case "list": {
      return (
        <div className="space-y-2 text-xs text-muted-foreground">
          <div className="flex flex-wrap items-center gap-2">
            <span className="inline-flex items-center rounded-full bg-primary/10 px-2 py-0.5 text-primary">
              Выбор: {screen.list.selectionType === "single" ? "один" : "несколько"}
            </span>
          </div>
          <div>
            <p className="font-medium text-foreground">Варианты ({screen.list.options.length})</p>
            <div className="mt-2 flex flex-wrap gap-2">
              {screen.list.options.map((option) => (
                <span
                  key={option.id}
                  className="inline-flex items-center gap-1 rounded-lg bg-primary/5 px-2 py-1 text-[11px] text-primary"
                >
                  {option.emoji && <span className="text-base leading-none">{option.emoji}</span>}
                  <span className="font-medium">{option.label}</span>
                </span>
              ))}
            </div>
          </div>
        </div>
      );
    }
    case "form": {
      return (
        <div className="space-y-2 text-xs text-muted-foreground">
          <div className="flex flex-wrap gap-2">
            <span className="inline-flex items-center rounded-full bg-primary/10 px-2 py-0.5 text-primary">
              Полей: {screen.fields.length}
            </span>
            {screen.bottomActionButton?.text && (
              <span className="inline-flex items-center rounded-full bg-muted px-2 py-0.5 text-muted-foreground">
                {screen.bottomActionButton.text}
              </span>
            )}
          </div>
          {screen.validationMessages && (
            <div className="rounded-lg border border-border/50 bg-background/80 p-2">
              <p className="text-[11px] text-muted-foreground">
                Настроены пользовательские сообщения валидации
              </p>
            </div>
          )}
        </div>
      );
    }
    case "coupon": {
      return (
        <div className="space-y-2 text-xs text-muted-foreground">
          <p>
            <span className="font-medium">Промо:</span> {screen.coupon.promoCode.text}
          </p>
          <p className="text-muted-foreground/80">{screen.coupon.offer.title.text}</p>
        </div>
      );
    }
    case "date": {
      return (
        <div className="space-y-2 text-xs text-muted-foreground">
          <p className="font-medium">Формат даты:</p>
          <div className="flex flex-wrap gap-2">
            {screen.dateInput.monthLabel && <span className="rounded bg-muted px-2 py-0.5">{screen.dateInput.monthLabel}</span>}
            {screen.dateInput.dayLabel && <span className="rounded bg-muted px-2 py-0.5">{screen.dateInput.dayLabel}</span>}
            {screen.dateInput.yearLabel && <span className="rounded bg-muted px-2 py-0.5">{screen.dateInput.yearLabel}</span>}
          </div>
          {screen.dateInput.validationMessage && (
            <p className="text-[11px] text-destructive">{screen.dateInput.validationMessage}</p>
          )}
        </div>
      );
    }
    case "info": {
      return (
        <div className="space-y-2 text-xs text-muted-foreground">
          {screen.description?.text && <p>{screen.description.text}</p>}
          {screen.icon?.value && (
            <div className="inline-flex items-center gap-2 rounded-lg bg-muted px-2 py-1">
              <span className="text-base">{screen.icon.value}</span>
              <span className="text-[11px] uppercase text-muted-foreground">Иконка</span>
            </div>
          )}
        </div>
      );
    }
    default:
      return null;
  }
}

function VariantSummary({
  screen,
  screenTitleMap,
  listOptionsMap,
}: {
  screen: ScreenDefinition;
  screenTitleMap: Record<string, string>;
  listOptionsMap: Record<string, ListOptionDefinition[]>;
}) {
  const variants = (
    screen as ScreenDefinition & {
      variants?: ScreenVariantDefinition<ScreenDefinition>[];
    }
  ).variants;

  if (!variants || variants.length === 0) {
    return null;
  }

  return (
    <div className="space-y-3">
      <div className="flex items-center gap-2">
        <span className="text-xs font-semibold uppercase text-muted-foreground">Варианты</span>
        <div className="h-px flex-1 bg-border/60" />
        <span className="text-[11px] uppercase text-muted-foreground/70">{variants.length}</span>
      </div>

      <div className="space-y-3">
        {variants.map((variant, index) => {
          const [condition] = variant.conditions ?? [];
          const controllingScreenId = condition?.screenId;
          const controllingScreenTitle = controllingScreenId
            ? screenTitleMap[controllingScreenId] ?? controllingScreenId
            : "Не выбрано";

          const options = controllingScreenId ? listOptionsMap[controllingScreenId] ?? [] : [];
          const optionSummaries = (condition?.optionIds ?? []).map((optionId) => ({
            id: optionId,
            label: getOptionLabel(options, optionId),
          }));

          const operatorKey = condition?.operator as
            | Exclude<NavigationConditionDefinition["operator"], undefined>
            | undefined;
          const operatorLabel = operatorKey ? OPERATOR_LABELS[operatorKey] ?? operatorKey : "includesAny";

          const overrideHighlights = listOverridePaths(variant.overrides ?? {});

          return (
            <div
              key={`${index}-${controllingScreenId ?? "none"}`}
              className="space-y-3 rounded-xl border border-primary/20 bg-primary/5 p-3"
            >
              <div className="flex items-center justify-between gap-3">
                <span className="text-xs font-semibold uppercase tracking-wide text-primary">Вариант {index + 1}</span>
                <span className="rounded-full bg-white/60 px-2 py-0.5 text-[10px] uppercase tracking-wide text-primary">
                  {operatorLabel}
                </span>
              </div>

              <div className="space-y-1 text-xs text-primary/90">
                <div>
                  <span className="font-semibold">Экран:</span> {controllingScreenTitle}
                </div>
                {optionSummaries.length > 0 ? (
                  <div className="flex flex-wrap gap-1.5">
                    {optionSummaries.map((option) => (
                      <span key={option.id} className="rounded-full bg-white/60 px-2 py-0.5 text-[11px] font-medium">
                        {option.label}
                      </span>
                    ))}
                  </div>
                ) : (
                  <div className="text-primary/70">Нет выбранных ответов</div>
                )}
              </div>

              <div className="space-y-1 text-xs text-primary/90">
                <span className="font-semibold">Изменяет:</span>
                <div className="flex flex-wrap gap-1.5">
                  {(overrideHighlights.length > 0 ? overrideHighlights : ["Без изменений"]).map((highlight) => (
                    <span
                      key={highlight}
                      className="rounded-lg bg-primary/10 px-2 py-0.5 text-[11px] font-medium text-primary"
                    >
                      {highlight === "Без изменений" ? highlight : formatOverridePath(highlight)}
                    </span>
                  ))}
                </div>
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function getOptionLabel(options: ListOptionDefinition[], optionId: string): string {
  const option = options.find((item) => item.id === optionId);
  return option ? option.label : optionId;
}

export function BuilderCanvas() {
  const { screens, selectedScreenId } = useBuilderState();
  const dispatch = useBuilderDispatch();

  const dragStateRef = useRef<{ screenId: string; dragStartIndex: number } | null>(null);
  const [dropIndex, setDropIndex] = useState<number | null>(null);
  const [addScreenDialogOpen, setAddScreenDialogOpen] = useState(false);

  const handleDragStart = useCallback((event: React.DragEvent, screenId: string, index: number) => {
    event.dataTransfer.effectAllowed = "move";
    event.dataTransfer.setData("text/plain", screenId);
    dragStateRef.current = { screenId, dragStartIndex: index };
    setDropIndex(index);
  }, []);

  const handleDragOverCard = useCallback((event: React.DragEvent<HTMLDivElement>, index: number) => {
    event.preventDefault();
    if (!dragStateRef.current) {
      return;
    }

    const rect = event.currentTarget.getBoundingClientRect();
    const offsetY = event.clientY - rect.top;
    const nextIndex = offsetY > rect.height / 2 ? index + 1 : index;
    setDropIndex(nextIndex);
  }, []);

  const handleDragOverList = useCallback(
    (event: React.DragEvent<HTMLDivElement>) => {
      if (!dragStateRef.current) {
        return;
      }
      event.preventDefault();
      if (event.target === event.currentTarget) {
        setDropIndex(screens.length);
      }
    },
    [screens.length]
  );

  const finalizeDrop = useCallback(
    (insertionIndex: number | null) => {
      if (!dragStateRef.current) {
        return;
      }

      const { dragStartIndex } = dragStateRef.current;
      const boundedIndex = Math.max(0, Math.min(insertionIndex ?? dragStartIndex, screens.length));
      let targetIndex = boundedIndex;

      if (targetIndex > dragStartIndex) {
        targetIndex -= 1;
      }

      if (dragStartIndex !== targetIndex) {
        dispatch({
          type: "reorder-screens",
          payload: {
            fromIndex: dragStartIndex,
            toIndex: targetIndex,
          },
        });
      }

      dragStateRef.current = null;
      setDropIndex(null);
    },
    [dispatch, screens.length]
  );

  const handleDrop = useCallback(
    (event: React.DragEvent<HTMLDivElement>) => {
      event.preventDefault();
      finalizeDrop(dropIndex);
    },
    [dropIndex, finalizeDrop]
  );

  const handleDragEnd = useCallback(() => {
    dragStateRef.current = null;
    setDropIndex(null);
  }, []);

  const handleSelectScreen = useCallback(
    (screenId: string) => {
      dispatch({ type: "set-selected-screen", payload: { screenId } });
    },
    [dispatch]
  );

  const handleAddScreen = useCallback(() => {
    setAddScreenDialogOpen(true);
  }, []);

  const handleAddScreenWithTemplate = useCallback((template: ScreenDefinition["template"]) => {
    dispatch({ type: "add-screen", payload: { template } });
  }, [dispatch]);

  const screenTitleMap = useMemo(() => {
    return screens.reduce<Record<string, string>>((accumulator, screen) => {
      accumulator[screen.id] = screen.title.text || screen.id;
      return accumulator;
    }, {});
  }, [screens]);

  const listOptionsMap = useMemo(() => {
    return screens.reduce<Record<string, ListOptionDefinition[]>>((accumulator, screen) => {
      if (screen.template === "list") {
        accumulator[screen.id] = screen.list.options;
      }
      return accumulator;
    }, {});
  }, [screens]);

  return (
    <>
    <div className="flex h-full flex-col">
      <div className="sticky top-0 z-30 flex items-center justify-between border-b border-border/60 bg-background/95 px-6 py-4 backdrop-blur-sm">
        <div>
          <h2 className="text-lg font-semibold">Экраны воронки</h2>
        </div>
        <Button variant="outline" className="w-8 h-8 p-0 flex items-center justify-center" onClick={handleAddScreen}>
          <span className="text-lg leading-none">+</span>
        </Button>
      </div>

      <div className="relative flex-1 overflow-auto bg-slate-50 p-6 dark:bg-slate-900">
        <div className="relative mx-auto max-w-4xl">
          <div className="absolute left-6 top-0 bottom-0 hidden w-px bg-border md:block" aria-hidden />
          <div
            className="space-y-6 pl-0 md:pl-12"
            onDragOver={handleDragOverList}
            onDrop={handleDrop}
          >
            {screens.map((screen, index) => {
              const isSelected = screen.id === selectedScreenId;
              const isDropBefore = dropIndex === index;
              const isDropAfter = dropIndex === screens.length && index === screens.length - 1;
              const rules = screen.navigation?.rules ?? [];
              const defaultNext = screen.navigation?.defaultNextScreenId;
              const isLast = index === screens.length - 1;
              const defaultTargetIndex = defaultNext
                ? screens.findIndex((candidate) => candidate.id === defaultNext)
                : null;

              return (
                <div key={screen.id} className="relative">
                  {isDropBefore && <DropIndicator isActive={isDropBefore} />}
                  <div className="flex items-start gap-4 md:gap-6">
                    <div className="relative hidden w-8 flex-shrink-0 md:flex md:flex-col md:items-center">
                      <span className="mt-1 h-3 w-3 rounded-full border-2 border-background bg-primary shadow" />
                      {!isLast && (
                        <div className="mt-2 flex h-full flex-col items-center">
                          <div className="flex-1 w-px bg-gradient-to-b from-primary/40 via-border/40 to-transparent" />
                          <ArrowDown className="mt-1 h-4 w-4 text-border/70" />
                        </div>
                      )}
                    </div>
                    <div
                      className={cn(
                        "relative flex-1 cursor-grab rounded-2xl border border-border/70 bg-background/95 p-5 shadow-sm transition-all hover:border-primary/40 hover:shadow-md",
                        isSelected && "border-primary/50 ring-2 ring-primary",
                        dragStateRef.current?.screenId === screen.id && "cursor-grabbing opacity-90"
                      )}
                      draggable
                      onDragStart={(event) => handleDragStart(event, screen.id, index)}
                      onDragOver={(event) => handleDragOverCard(event, index)}
                      onDragEnd={handleDragEnd}
                      onClick={() => handleSelectScreen(screen.id)}
                    >
                      <span className="absolute right-5 top-5 inline-flex items-center rounded-full bg-muted px-3 py-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground">
                        {TEMPLATE_TITLES[screen.template] ?? screen.template}
                      </span>
                      <div className="pr-28">
                        <div className="flex items-start gap-3">
                          <div className="flex h-9 w-9 items-center justify-center rounded-full bg-primary/10 text-sm font-semibold text-primary">
                            {index + 1}
                          </div>
                          <div className="flex flex-col gap-1">
                            <span className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
                              #{screen.id}
                            </span>
                            <span className="max-h-14 overflow-hidden break-words text-lg font-semibold leading-tight text-foreground">
                              {screen.title.text || "Без названия"}
                            </span>
                          </div>
                        </div>
                      </div>

                      {("subtitle" in screen && screen.subtitle?.text) && (
                        <p className="mt-3 max-h-12 overflow-hidden text-sm leading-snug text-muted-foreground">
                          {screen.subtitle.text}
                        </p>
                      )}

                      <div className="mt-4 space-y-5">
                        <TemplateSummary screen={screen} />

                        <VariantSummary
                          screen={screen}
                          screenTitleMap={screenTitleMap}
                          listOptionsMap={listOptionsMap}
                        />

                        <div className="space-y-3">
                          <div className="flex items-center gap-2">
                            <span className="text-xs font-semibold uppercase text-muted-foreground">Переходы</span>
                            <div className="h-px flex-1 bg-border/60" />
                          </div>

                          <div className="space-y-3">
                            <TransitionRow
                              type={defaultNext ? "default" : "end"}
                              label={defaultNext ? "По умолчанию" : "Завершение"}
                              targetLabel={defaultNext ? screenTitleMap[defaultNext] ?? defaultNext : undefined}
                              targetIndex={defaultNext && defaultTargetIndex !== -1 ? defaultTargetIndex : null}
                            />

                            {rules.map((rule, ruleIndex) => {
                              const condition = rule.conditions[0];
                              const optionSummaries =
                                screen.template === "list" && condition?.optionIds
                                  ? condition.optionIds.map((optionId) => ({
                                      id: optionId,
                                      label: getOptionLabel(screen.list.options, optionId),
                                    }))
                                  : [];

                              const operatorKey = condition?.operator as
                                | Exclude<NavigationConditionDefinition["operator"], undefined>
                                | undefined;
                              const operatorLabel = operatorKey
                                ? OPERATOR_LABELS[operatorKey] ?? operatorKey
                                : undefined;

                              const ruleTargetIndex = screens.findIndex(
                                (candidate) => candidate.id === rule.nextScreenId
                              );
                              const ruleTargetLabel = screenTitleMap[rule.nextScreenId] ?? rule.nextScreenId;

                              return (
                                <TransitionRow
                                  key={`${ruleIndex}-${rule.nextScreenId}`}
                                  type="branch"
                                  label="Вариативность"
                                  targetLabel={ruleTargetLabel}
                                  targetIndex={ruleTargetIndex !== -1 ? ruleTargetIndex : null}
                                  optionSummaries={optionSummaries}
                                  operator={operatorLabel}
                                />
                              );
                            })}
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                  {isDropAfter && <DropIndicator isActive={isDropAfter} />}
                </div>
              );
            })}

            {screens.length === 0 && (
              <div className="rounded-2xl border border-dashed border-border/60 bg-background/80 p-8 text-center text-sm text-muted-foreground">
                Добавьте первый экран, чтобы начать строить воронку.
              </div>
            )}

            <div className="pt-4">
              <Button variant="ghost" onClick={handleAddScreen} className="w-8 h-8 p-0 mx-auto flex items-center justify-center">
                +
              </Button>
            </div>
          </div>
        </div>
      </div>
    </div>

    <AddScreenDialog 
      open={addScreenDialogOpen}
      onOpenChange={setAddScreenDialogOpen}
      onAddScreen={handleAddScreenWithTemplate}
    />
    </>
  );
}
