"use client";

import { useState } from "react";
import { Popover, PopoverButton, PopoverPanel } from "@headlessui/react";
import { MoreVertical, Plus, Star } from "lucide-react";
import type { FolderWire } from "@/app/lib/portfolioHomeView";

export type RailView = "all" | "starred" | { folderId: string };

// Cards set this dataTransfer type on drag; rail items accept it as a drop.
const PORTFOLIO_DRAG_TYPE = "application/x-portfolio";

export type FolderRailProps = {
  folders: FolderWire[]; // already ordered by position
  view: RailView;
  totalCount: number;
  starredCount: number;
  attentionTotal: number;
  countOf: (folderId: string) => number;
  attentionOf: (folderId: string) => number;
  onSelect: (view: RailView) => void;
  onReorder: (orderedIds: string[]) => void;
  onCreate: (name: string) => void;
  onRename: (folderId: string, name: string) => void;
  onDelete: (folderId: string) => void;
  // Drag-to-file: a card dropped on a folder / Starred / All portfolios.
  onDropToFolder: (portfolioId: string, folderId: string | null) => void;
  onDropToStarred: (portfolioId: string) => void;
};

function AttentionBadge({ count }: { count: number }) {
  if (!count) return null;
  return (
    <span
      title={`${count} need attention`}
      className="rounded-full bg-red-100 px-2 py-px text-[11px] font-semibold text-red-800 tabular-nums"
    >
      ⚠ {count}
    </span>
  );
}

function railItemClasses(active: boolean) {
  return `flex w-full min-w-0 items-center gap-2 rounded-lg px-2.5 py-1.5 text-left text-sm ${
    active ? "bg-[#e4e9f1] font-semibold" : "hover:bg-[#e9edf3]"
  }`;
}

const dropHighlight = "ring-2 ring-inset ring-brandmidblue rounded-lg";

export default function FolderRail(props: FolderRailProps) {
  const [dragIndex, setDragIndex] = useState<number | null>(null);
  const [dropIndex, setDropIndex] = useState<number | null>(null);
  const [creating, setCreating] = useState(false);
  const [editingId, setEditingId] = useState<string | null>(null);
  // Two-step destructive confirm lives inside the menu popover, not a dialog:
  // removal only unfiles portfolios, so OS-modal weight isn't warranted.
  const [confirmingId, setConfirmingId] = useState<string | null>(null);
  // Which rail target a dragged card is hovering: folder id, "starred",
  // "all", or null.
  const [cardDropTarget, setCardDropTarget] = useState<string | null>(null);

  const isFolderView = (folderId: string) =>
    typeof props.view === "object" && props.view.folderId === folderId;

  const commitDrop = () => {
    if (dragIndex !== null && dropIndex !== null && dropIndex !== dragIndex) {
      const ids = props.folders.map((f) => f.id);
      const [moved] = ids.splice(dragIndex, 1);
      ids.splice(dropIndex, 0, moved);
      props.onReorder(ids);
    }
    setDragIndex(null);
    setDropIndex(null);
  };

  const cardDropHandlers = (
    targetKey: string,
    onDrop: (portfolioId: string) => void,
  ) => ({
    onDragOver: (e: React.DragEvent) => {
      if (!e.dataTransfer.types.includes(PORTFOLIO_DRAG_TYPE)) return;
      e.preventDefault();
      e.dataTransfer.dropEffect = "move";
      setCardDropTarget(targetKey);
    },
    onDragLeave: () =>
      setCardDropTarget((current) => (current === targetKey ? null : current)),
    onDrop: (e: React.DragEvent) => {
      const portfolioId = e.dataTransfer.getData(PORTFOLIO_DRAG_TYPE);
      if (!portfolioId) return;
      e.preventDefault();
      setCardDropTarget(null);
      onDrop(portfolioId);
    },
  });

  const nameForm = (
    defaultValue: string,
    onSubmit: (name: string) => void,
    onDone: () => void,
  ) => (
    <form
      className="flex-1 px-1"
      onSubmit={(e) => {
        e.preventDefault();
        const name = new FormData(e.currentTarget).get("name");
        if (typeof name === "string" && name.trim()) onSubmit(name.trim());
        onDone();
      }}
    >
      <input
        name="name"
        defaultValue={defaultValue}
        autoFocus
        maxLength={120}
        aria-label="Folder name"
        onBlur={onDone}
        onKeyDown={(e) => e.key === "Escape" && onDone()}
        className="w-full rounded-md border border-brandmidblue px-2 py-1 text-sm focus:outline-none focus:ring-2 focus:ring-brandmidblue/30"
      />
    </form>
  );

  return (
    <nav
      aria-label="Portfolio folders"
      className="w-full shrink-0 lg:sticky lg:top-5 lg:w-[230px]"
    >
      <div className="flex flex-col gap-0.5">
        <button
          type="button"
          onClick={() => props.onSelect("starred")}
          {...cardDropHandlers("starred", props.onDropToStarred)}
          className={`${railItemClasses(props.view === "starred")} ${
            cardDropTarget === "starred" ? dropHighlight : ""
          }`}
        >
          <Star
            size={14}
            className="shrink-0"
            fill="#f1bb06"
            strokeWidth={0}
            aria-hidden
          />
          <span className="flex-1 truncate">Starred</span>
          <span className="text-[13px] text-gray-600 tabular-nums">
            {props.starredCount}
          </span>
        </button>
        <button
          type="button"
          onClick={() => props.onSelect("all")}
          {...cardDropHandlers("all", (portfolioId) =>
            props.onDropToFolder(portfolioId, null),
          )}
          className={`${railItemClasses(props.view === "all")} ${
            cardDropTarget === "all" ? dropHighlight : ""
          }`}
        >
          <span className="flex-1 truncate">All portfolios</span>
          <AttentionBadge count={props.attentionTotal} />
          <span className="text-[13px] text-gray-600 tabular-nums">
            {props.totalCount}
          </span>
        </button>
      </div>

      <hr className="my-2.5 border-[#e2e7ee]" />

      <div className="mb-1.5 flex items-center px-2.5 text-xs font-semibold text-gray-500">
        Your folders
        <button
          type="button"
          onClick={() => setCreating(true)}
          className="ml-auto flex items-center gap-0.5 rounded-md px-1.5 py-1 font-semibold text-brandmidblue hover:bg-[#eceefb]"
        >
          <Plus size={13} aria-hidden /> New
        </button>
      </div>

      <ul className="flex flex-col gap-0.5">
        {props.folders.map((folder, index) => (
          <li
            key={folder.id}
            draggable={editingId !== folder.id}
            onDragStart={(e) => {
              // A card drag bubbling up must not start a folder reorder.
              if (e.dataTransfer.types.includes(PORTFOLIO_DRAG_TYPE)) return;
              setDragIndex(index);
            }}
            onDragOver={(e) => {
              if (dragIndex !== null) {
                e.preventDefault();
                setDropIndex(index);
              }
            }}
            onDrop={() => {
              if (dragIndex !== null) commitDrop();
            }}
            onDragEnd={() => {
              setDragIndex(null);
              setDropIndex(null);
            }}
            className={`group flex items-center rounded-lg ${
              dragIndex === index ? "opacity-40" : ""
            } ${
              dropIndex === index && dragIndex !== null && dragIndex !== index
                ? dropIndex < dragIndex
                  ? "shadow-[0_-2px_0_#3943b7]"
                  : "shadow-[0_2px_0_#3943b7]"
                : ""
            } ${editingId === folder.id ? "" : "cursor-grab"}`}
          >
            {editingId === folder.id ? (
              nameForm(
                folder.name,
                (name) => props.onRename(folder.id, name),
                () => setEditingId(null),
              )
            ) : (
              <>
                <button
                  type="button"
                  onClick={() => props.onSelect({ folderId: folder.id })}
                  {...cardDropHandlers(folder.id, (portfolioId) =>
                    props.onDropToFolder(portfolioId, folder.id),
                  )}
                  className={`${railItemClasses(isFolderView(folder.id))} ${
                    cardDropTarget === folder.id ? dropHighlight : ""
                  }`}
                >
                  <span className="flex-1 truncate">{folder.name}</span>
                  <AttentionBadge count={props.attentionOf(folder.id)} />
                  <span className="text-[13px] text-gray-600 tabular-nums">
                    {props.countOf(folder.id)}
                  </span>
                </button>
                <Popover className="shrink-0">
                  <PopoverButton
                    aria-label={`Folder options for ${folder.name}`}
                    onClick={() => setConfirmingId(null)}
                    className="grid place-items-center rounded-lg p-1.5 text-gray-500 opacity-0 hover:bg-gray-100 focus-visible:opacity-100 group-hover:opacity-100 data-[open]:opacity-100 data-[open]:bg-gray-100"
                  >
                    <MoreVertical size={15} aria-hidden />
                  </PopoverButton>
                  <PopoverPanel
                    focus
                    anchor={{ to: "bottom end", gap: 4 }}
                    className="z-20 min-w-[150px] rounded-lg border border-gray-200 bg-white p-1 shadow-md focus:outline-none"
                  >
                    {({ close }) =>
                      confirmingId === folder.id ? (
                        <div className="w-56 p-2">
                          <p className="mb-2 text-sm font-semibold text-gray-900">
                            Remove “{folder.name}”?
                          </p>
                          <p className="mb-3 text-[13px] text-gray-600">
                            {props.countOf(folder.id) === 0
                              ? "It's empty — no portfolios are affected."
                              : `Its ${props.countOf(folder.id)} portfolio${
                                  props.countOf(folder.id) === 1 ? "" : "s"
                                } will be unfiled, not deleted.`}
                          </p>
                          <div className="flex gap-2">
                            <button
                              type="button"
                              autoFocus
                              onClick={() => {
                                close();
                                setConfirmingId(null);
                                props.onDelete(folder.id);
                              }}
                              className="rounded-md bg-red-700 px-3 py-1.5 text-sm font-semibold text-white hover:bg-red-800"
                            >
                              Remove folder
                            </button>
                            <button
                              type="button"
                              onClick={() => setConfirmingId(null)}
                              className="rounded-md px-3 py-1.5 text-sm font-semibold text-gray-700 hover:bg-gray-100"
                            >
                              Cancel
                            </button>
                          </div>
                        </div>
                      ) : (
                        <>
                          {(
                            [
                              ["Move up", index > 0, -1],
                              [
                                "Move down",
                                index < props.folders.length - 1,
                                1,
                              ],
                            ] as const
                          ).map(([label, enabled, delta]) => (
                            <button
                              key={label}
                              type="button"
                              disabled={!enabled}
                              onClick={() => {
                                close();
                                const ids = props.folders.map((f) => f.id);
                                const [moved] = ids.splice(index, 1);
                                ids.splice(index + delta, 0, moved);
                                props.onReorder(ids);
                              }}
                              className="block w-full rounded-md px-2.5 py-1.5 text-left text-sm hover:bg-gray-50 disabled:cursor-default disabled:text-gray-400 disabled:hover:bg-transparent"
                            >
                              {label}
                            </button>
                          ))}
                          <div className="my-1 border-t border-gray-200" />
                          <button
                            type="button"
                            onClick={() => {
                              close();
                              setEditingId(folder.id);
                            }}
                            className="block w-full rounded-md px-2.5 py-1.5 text-left text-sm hover:bg-gray-50"
                          >
                            Rename
                          </button>
                          <button
                            type="button"
                            onClick={() => setConfirmingId(folder.id)}
                            className="block w-full rounded-md px-2.5 py-1.5 text-left text-sm text-red-700 hover:bg-red-50"
                          >
                            Remove folder…
                          </button>
                        </>
                      )
                    }
                  </PopoverPanel>
                </Popover>
              </>
            )}
          </li>
        ))}
        {creating && (
          <li className="flex items-center rounded-lg">
            {nameForm("", props.onCreate, () => setCreating(false))}
          </li>
        )}
      </ul>

      <p className="hidden px-2.5 pt-2 text-xs text-gray-500 lg:block">
        Folders are personal to you — teammates organise their own. Drag
        folders to reorder, or drop a portfolio card onto a folder to file it.
      </p>
    </nav>
  );
}
