import { useRouter } from "next/navigation";
import { Suspense } from "react";
import { BackButton } from "@/app/BackButton";
import { UserBadge } from "@/app/UserBadge";
import { TrailOverviewStop } from "./TrailOverviewStop";
import { TrailRegisterDeferred } from "./TrailRegisterDeferred";
import { AccentButton } from "./AccentButton";
import { TextButton } from "@/components/TextButton";
import { startWalk, abandonWalk, forgetTrail, deleteTrail } from "@/data/actions";
import { AddButton } from "@/app/EditButtons";
import { useEditMode } from "./EditModeContext";
import { useAuthAction } from "@/auth/useAuthAction";
import type { TrailDetailData, TrailStop } from "@/data/queries";
import "./TrailOverview.css";

type Props = {
  trail: TrailDetailData;
  onModeChange: (mode: "walk") => void;
  canEdit: boolean;
  onDelete?: () => Promise<void> | void;
  onPublish?: () => Promise<void> | void;
  publishError?: string[] | null;
};

export function TrailOverview({
  trail,
  onModeChange,
  canEdit,
  onDelete,
  onPublish,
  publishError,
}: Props) {
  const router = useRouter();
  const requireAuth = useAuthAction();

  // Check if we're in edit mode
  const editContext = useEditMode();
  const isEditing = !!editContext;
  const updateTrail = editContext?.updateTrail;
  const updateStop = editContext?.updateStop;
  const addStop = editContext?.addStop;
  const deleteStop = editContext?.deleteStop;

  const visitedStopTids = trail.yourWalk?.visitedStops ?? [];
  const currentStopIndex = trail.stops.findIndex((s) => s.tid === visitedStopTids.at(-1));

  const canStartWalking = trail.header.title.trim() && trail.stops.some((s) => s.title?.trim());

  // Show add button when the last step has content and we have less than 12 steps
  const lastStop = trail.stops[trail.stops.length - 1];
  const shouldShowAddButton = lastStop?.title?.trim() && trail.stops.length < 12;

  const startWalkAction = requireAuth(async () => {
    if (!trail.yourWalk && !isEditing) {
      await startWalk(trail.header.uri, trail.header.cid);
    }
    onModeChange("walk");
  });

  const abandonAction = requireAuth(async () => {
    if (confirm("abandon this trail? your progress will be lost")) {
      if (trail.yourWalk) {
        await abandonWalk(trail.yourWalk!.uri);
      }
    }
  });

  const deleteTrailAction = requireAuth(async () => {
    if (confirm("delete this trail? it will be gone for everyone forever")) {
      await deleteTrail(trail.header.uri);
      router.push("/");
    }
  });

  const handleStopTitleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>, stopId: string) => {
    const currentIndex = trail.stops.findIndex((s) => s.tid === stopId);
    const inputs = document.querySelectorAll(".TrailOverviewStop-titleInput");
    const isCurrentEmpty = e.currentTarget.value === "";

    // Enter: Insert line before if at beginning, after if elsewhere (do nothing if empty)
    if (e.key === "Enter") {
      e.preventDefault();

      if (isCurrentEmpty) return;

      const cursorPosition = e.currentTarget.selectionStart || 0;
      const isAtBeginning = cursorPosition === 0;

      if (isAtBeginning) {
        const prevInput = inputs[currentIndex - 1] as HTMLInputElement;
        if (prevInput && prevInput.value === "") return;

        if (addStop && trail.stops.length < 12) {
          addStop(currentIndex - 1);
        }
      } else {
        const nextInput = inputs[currentIndex + 1] as HTMLInputElement;
        if (nextInput && nextInput.value === "") {
          nextInput.focus();
          return;
        }

        if (addStop && trail.stops.length < 12) {
          addStop(currentIndex);
          setTimeout(() => {
            const updatedInputs = document.querySelectorAll(".TrailOverviewStop-titleInput");
            const newInput = updatedInputs[currentIndex + 1] as HTMLInputElement;
            if (newInput) newInput.focus();
          }, 10);
        }
      }
    }

    // ArrowUp: Move to previous input
    if (e.key === "ArrowUp") {
      e.preventDefault();
      const prevInput = inputs[currentIndex - 1] as HTMLInputElement;
      if (prevInput) {
        prevInput.focus();
        prevInput.setSelectionRange(prevInput.value.length, prevInput.value.length);
      }
    }

    // ArrowDown: Move to next input
    if (e.key === "ArrowDown") {
      e.preventDefault();
      const nextInput = inputs[currentIndex + 1] as HTMLInputElement;
      if (nextInput) {
        nextInput.focus();
        nextInput.setSelectionRange(nextInput.value.length, nextInput.value.length);
      }
    }

    // Backspace: Delete current line if empty, or delete previous line if at beginning and prev is empty
    if (e.key === "Backspace" && deleteStop) {
      const cursorPosition = e.currentTarget.selectionStart || 0;
      const isAtBeginning = cursorPosition === 0;
      const prevInput = inputs[currentIndex - 1] as HTMLInputElement;

      if (isCurrentEmpty && currentIndex > 0) {
        e.preventDefault();
        deleteStop(stopId);
        if (prevInput) {
          setTimeout(() => {
            prevInput.focus();
            prevInput.setSelectionRange(prevInput.value.length, prevInput.value.length);
          }, 0);
        }
      } else if (
        isAtBeginning &&
        !isCurrentEmpty &&
        prevInput &&
        prevInput.value === "" &&
        currentIndex > 0
      ) {
        e.preventDefault();
        const prevStopId = trail.stops[currentIndex - 1].tid;
        deleteStop(prevStopId);
        setTimeout(() => {
          e.currentTarget.focus();
          e.currentTarget.setSelectionRange(0, 0);
        }, 0);
      }
    }
  };

  return (
    <div
      className="TrailOverview-wrapper"
      style={
        {
          "--accent-color": trail.header.accentColor,
          "--accent-color-transparent": `${trail.header.accentColor}15`,
          "--bg-color": trail.header.backgroundColor,
        } as React.CSSProperties
      }
    >
      <BackButton fallbackPath={isEditing ? "/drafts" : "/"} variant="top" />

      <div className="TrailOverview">
        <div className="TrailOverview-header">
          {isEditing ? (
            <>
              <input
                autoFocus={!trail.header.title}
                value={trail.header.title}
                onChange={(e) => updateTrail?.({ title: e.target.value })}
                className="TrailOverview-titleEdit"
                placeholder="name your trail"
              />
              <input
                autoFocus={!!trail.header.title && !trail.header.description}
                value={trail.header.description}
                onChange={(e) => updateTrail?.({ description: e.target.value })}
                className="TrailOverview-descriptionEdit"
                placeholder="describe it in a few words"
              />
            </>
          ) : (
            <>
              <h1 className="TrailOverview-title">
                <span>{trail.header.title}</span>
              </h1>
              <p className="TrailOverview-description">
                <span>{trail.header.description}</span>
              </p>
              <div className="TrailOverview-metaWrapper">
                <p className="TrailOverview-creator">
                  <span>
                    by{" "}
                    <UserBadge
                      handle={trail.header.creator.handle}
                      avatar={trail.header.creator.avatar}
                      name={trail.header.creator.handle}
                      showAvatar={false}
                    />
                  </span>
                </p>
                <div className="TrailOverview-meta">
                  <span>{trail.stops.length} stops</span>
                </div>
              </div>
            </>
          )}
        </div>

        <div className="TrailOverview-stops">
          <h2 className="TrailOverview-stopsTitle">on this trail:</h2>
          <ol className="TrailOverview-stopsList">
            {trail.stops.map((stop: TrailStop, index: number) => {
              const isCurrent = index === currentStopIndex;
              const isLocked = trail.yourWalk && !visitedStopTids.includes(stop.tid);
              return (
                <div key={stop.tid}>
                  <TrailOverviewStop
                    stop={stop}
                    index={index}
                    isEditing={isEditing}
                    isLocked={!!isLocked}
                    isCurrent={!!isCurrent}
                    totalStops={trail.stops.length}
                    onTitleChange={(stopId, title) => updateStop?.(stopId, { title })}
                    onDelete={(stopId) => deleteStop?.(stopId)}
                    onKeyDown={handleStopTitleKeyDown}
                  />
                </div>
              );
            })}
          </ol>
          {isEditing && addStop && (
            <div
              className={`TrailOverview-addStopContainer ${shouldShowAddButton ? "TrailOverview-addStopContainer--visible" : ""}`}
            >
              <AddButton
                onClick={() => {
                  const currentLength = trail.stops.length;
                  addStop();
                  setTimeout(() => {
                    const inputs = document.querySelectorAll(".TrailOverviewStop-titleInput");
                    const newInput = inputs[currentLength] as HTMLInputElement;
                    if (newInput) newInput.focus();
                  }, 10);
                }}
                title="add stop"
              />
            </div>
          )}
        </div>

        <div className="TrailOverview-actions">
          <AccentButton
            action={startWalkAction}
            size="large"
            disabled={isEditing && !canStartWalking}
          >
            {isEditing
              ? "design this trail"
              : trail.yourWalk
                ? "walk some more"
                : "walk this trail"}
          </AccentButton>
          {isEditing && onPublish && (
            <AccentButton action={onPublish} size="medium" pendingChildren="publishing...">
              publish trail
            </AccentButton>
          )}
          {isEditing && onDelete && (
            <span className="TrailOverview-abandonButton">
              <TextButton action={onDelete} pendingChildren="deleting...">
                delete draft
              </TextButton>
            </span>
          )}
          {!isEditing && trail.yourWalk && (
            <span className="TrailOverview-abandonButton">
              <TextButton action={abandonAction} pendingChildren="abandoning...">
                abandon
              </TextButton>
            </span>
          )}
          {!isEditing && !trail.yourWalk && canEdit && (
            <span className="TrailOverview-abandonButton">
              <TextButton action={deleteTrailAction} pendingChildren="deleting...">
                delete trail
              </TextButton>
            </span>
          )}
        </div>

        {publishError && publishError.length > 0 && (
          <div className="TrailOverview-publishError">
            <ul>
              {publishError.map((error, i) => (
                <li key={i}>{error}</li>
              ))}
            </ul>
          </div>
        )}

        {!isEditing && (
          <Suspense
            fallback={
              <div className="TrailRegister">
                <p className="TrailRegister-empty">loading...</p>
              </div>
            }
          >
            <TrailRegisterDeferred
              mode="walked"
              walkers={trail.walkers}
              onDelete={async () => {
                if (confirm("forget this trail? it will be like you never walked here")) {
                  await forgetTrail(trail.header.uri);
                }
              }}
            />
          </Suspense>
        )}
      </div>
    </div>
  );
}
