import { useEffect, useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { useLocation } from "wouter";
import {
  ArrowLeft,
  ArrowRight,
  StickyNote,
  Pin,
  Archive,
  ArchiveRestore,
  Trash2,
  Palette,
  Tag,
  Search,
  Plus,
  X,
  Check,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Badge } from "@/components/ui/badge";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover";
import {
  type Note,
  type NoteLabel,
  NOTE_COLORS,
  colorBg,
  useCreateLabel,
  useCreateNote,
  useDeleteLabel,
  useDeleteNote,
  useNoteLabels,
  useNotes,
  useUpdateLabel,
  useUpdateNote,
} from "@/lib/notes-api";

export default function NotesPage() {
  const { t, i18n } = useTranslation();
  const [, setLocation] = useLocation();
  const isRtl = i18n.language === "ar";
  const BackIcon = isRtl ? ArrowRight : ArrowLeft;

  const [view, setView] = useState<"active" | "archived">("active");
  const [search, setSearch] = useState("");
  const [labelFilter, setLabelFilter] = useState<number | null>(null);
  const [editing, setEditing] = useState<Note | null>(null);
  const [labelsDialogOpen, setLabelsDialogOpen] = useState(false);

  const { data: notes = [], isLoading } = useNotes(view === "archived");
  const { data: labels = [] } = useNoteLabels();

  const filtered = useMemo(() => {
    const q = search.trim().toLowerCase();
    return notes.filter((n) => {
      if (labelFilter && !n.labelIds.includes(labelFilter)) return false;
      if (!q) return true;
      return (
        n.title.toLowerCase().includes(q) ||
        n.content.toLowerCase().includes(q)
      );
    });
  }, [notes, search, labelFilter]);

  const pinned = filtered.filter((n) => n.isPinned);
  const others = filtered.filter((n) => !n.isPinned);

  return (
    <div className="min-h-screen os-bg flex flex-col" dir={isRtl ? "rtl" : "ltr"}>
      {/* Header */}
      <div className="glass-panel border-b border-slate-200/70 px-4 py-3 sticky top-0 z-20">
        <div className="flex items-center gap-3 flex-wrap">
          <button
            onClick={() => setLocation("/")}
            className="p-2 rounded-xl hover:bg-slate-100/60 text-muted-foreground hover:text-foreground transition-colors"
            aria-label={t("common.back", "Back")}
          >
            <BackIcon size={20} />
          </button>
          <div className="flex items-center gap-2">
            <StickyNote size={20} className="text-amber-500" />
            <h1 className="text-lg font-semibold text-foreground">
              {t("notes.title", "Notes")}
            </h1>
          </div>

          <div className="flex-1 min-w-[180px] max-w-md ms-auto relative">
            <Search
              size={16}
              className="absolute top-1/2 -translate-y-1/2 text-muted-foreground"
              style={isRtl ? { right: 10 } : { left: 10 }}
            />
            <Input
              value={search}
              onChange={(e) => setSearch(e.target.value)}
              placeholder={t("notes.searchPlaceholder", "Search notes")}
              className={isRtl ? "pe-9" : "ps-9"}
            />
          </div>

          <Button
            size="sm"
            variant="ghost"
            onClick={() => setLabelsDialogOpen(true)}
          >
            <Tag size={16} className="me-1" />
            {t("notes.labels", "Labels")}
          </Button>
        </div>

        {/* Tabs + label chips */}
        <div className="mt-3 flex items-center gap-2 flex-wrap">
          <div className="inline-flex rounded-xl bg-slate-100/70 p-1">
            <button
              onClick={() => setView("active")}
              className={`px-3 py-1 text-sm rounded-lg transition ${
                view === "active"
                  ? "bg-white shadow-sm text-foreground"
                  : "text-muted-foreground"
              }`}
            >
              {t("notes.tabs.active", "Notes")}
            </button>
            <button
              onClick={() => setView("archived")}
              className={`px-3 py-1 text-sm rounded-lg transition ${
                view === "archived"
                  ? "bg-white shadow-sm text-foreground"
                  : "text-muted-foreground"
              }`}
            >
              {t("notes.tabs.archived", "Archived")}
            </button>
          </div>
          {labels.length > 0 && (
            <div className="flex items-center gap-1.5 flex-wrap">
              <button
                onClick={() => setLabelFilter(null)}
                className={`text-xs px-2.5 py-1 rounded-full border transition ${
                  labelFilter === null
                    ? "bg-foreground text-background border-foreground"
                    : "border-slate-300/60 text-muted-foreground hover:border-foreground"
                }`}
              >
                {t("notes.allLabels", "All")}
              </button>
              {labels.map((l) => (
                <button
                  key={l.id}
                  onClick={() => setLabelFilter(l.id)}
                  className={`text-xs px-2.5 py-1 rounded-full border transition flex items-center gap-1 ${
                    labelFilter === l.id
                      ? "bg-foreground text-background border-foreground"
                      : "border-slate-300/60 text-muted-foreground hover:border-foreground"
                  }`}
                >
                  <Tag size={11} /> {l.name}
                </button>
              ))}
            </div>
          )}
        </div>
      </div>

      <div className="flex-1 px-4 py-6 max-w-6xl w-full mx-auto">
        {view === "active" && (
          <Composer labels={labels} />
        )}

        {isLoading ? (
          <div className="flex items-center justify-center py-20 text-muted-foreground">
            {t("common.loading", "Loading...")}
          </div>
        ) : filtered.length === 0 ? (
          <div className="flex flex-col items-center justify-center py-24 gap-3 text-muted-foreground">
            <StickyNote size={48} className="opacity-30" />
            <span>
              {view === "archived"
                ? t("notes.emptyArchived", "No archived notes")
                : t("notes.empty", "Your notes will appear here")}
            </span>
          </div>
        ) : (
          <div className="space-y-6 mt-6">
            {pinned.length > 0 && (
              <Section
                title={t("notes.pinned", "Pinned")}
                notes={pinned}
                labels={labels}
                onEdit={setEditing}
              />
            )}
            <Section
              title={pinned.length > 0 ? t("notes.others", "Others") : ""}
              notes={others}
              labels={labels}
              onEdit={setEditing}
            />
          </div>
        )}
      </div>

      {editing && (
        <EditNoteDialog
          note={editing}
          labels={labels}
          onClose={() => setEditing(null)}
        />
      )}

      <LabelsDialog
        open={labelsDialogOpen}
        onClose={() => setLabelsDialogOpen(false)}
        labels={labels}
      />
    </div>
  );
}

function Section({
  title,
  notes,
  labels,
  onEdit,
}: {
  title: string;
  notes: Note[];
  labels: NoteLabel[];
  onEdit: (n: Note) => void;
}) {
  if (notes.length === 0) return null;
  return (
    <div>
      {title && (
        <h2 className="text-xs uppercase tracking-wider text-muted-foreground mb-2">
          {title}
        </h2>
      )}
      <div
        className="gap-3 [column-fill:_balance]"
        style={{ columnWidth: 230 }}
      >
        {notes.map((n) => (
          <NoteCard key={n.id} note={n} labels={labels} onEdit={onEdit} />
        ))}
      </div>
    </div>
  );
}

function NoteCard({
  note,
  labels,
  onEdit,
}: {
  note: Note;
  labels: NoteLabel[];
  onEdit: (n: Note) => void;
}) {
  const { t } = useTranslation();
  const update = useUpdateNote();
  const del = useDeleteNote();
  const noteLabels = labels.filter((l) => note.labelIds.includes(l.id));

  return (
    <div
      className={`break-inside-avoid mb-3 rounded-xl border border-black/5 shadow-sm p-3 cursor-pointer transition hover:shadow-md group ${colorBg(
        note.color,
      )}`}
      onClick={() => onEdit(note)}
    >
      <div className="flex items-start justify-between gap-2">
        <div className="flex-1 min-w-0">
          {note.title && (
            <div className="font-semibold text-sm text-foreground break-words">
              {note.title}
            </div>
          )}
          {note.content && (
            <div className="text-sm text-foreground/80 mt-1 whitespace-pre-wrap break-words line-clamp-[12]">
              {note.content}
            </div>
          )}
        </div>
        <button
          onClick={(e) => {
            e.stopPropagation();
            update.mutate({ id: note.id, isPinned: !note.isPinned });
          }}
          className={`shrink-0 p-1 rounded-md hover:bg-black/5 ${
            note.isPinned ? "text-amber-600" : "text-muted-foreground opacity-0 group-hover:opacity-100"
          }`}
          aria-label={t("notes.pin", "Pin")}
        >
          <Pin size={16} className={note.isPinned ? "fill-amber-500" : ""} />
        </button>
      </div>

      {noteLabels.length > 0 && (
        <div className="flex flex-wrap gap-1 mt-2">
          {noteLabels.map((l) => (
            <Badge key={l.id} variant="secondary" className="text-[10px] py-0 px-1.5">
              {l.name}
            </Badge>
          ))}
        </div>
      )}

      <div
        className="flex items-center gap-1 mt-2 opacity-0 group-hover:opacity-100 transition"
        onClick={(e) => e.stopPropagation()}
      >
        <ColorPicker
          value={note.color}
          onChange={(c) => update.mutate({ id: note.id, color: c })}
        />
        <LabelMenu
          labels={labels}
          selected={note.labelIds}
          onChange={(ids) => update.mutate({ id: note.id, labelIds: ids })}
        />
        <button
          onClick={() =>
            update.mutate({ id: note.id, isArchived: !note.isArchived })
          }
          className="p-1 rounded-md hover:bg-black/5 text-muted-foreground"
          aria-label={
            note.isArchived
              ? t("notes.unarchive", "Unarchive")
              : t("notes.archive", "Archive")
          }
        >
          {note.isArchived ? <ArchiveRestore size={15} /> : <Archive size={15} />}
        </button>
        <button
          onClick={() => {
            if (confirm(t("notes.deleteConfirm", "Delete this note?"))) {
              del.mutate(note.id);
            }
          }}
          className="p-1 rounded-md hover:bg-black/5 text-muted-foreground hover:text-destructive"
          aria-label={t("notes.delete", "Delete")}
        >
          <Trash2 size={15} />
        </button>
      </div>
    </div>
  );
}

function ColorPicker({
  value,
  onChange,
}: {
  value: string;
  onChange: (c: string) => void;
}) {
  return (
    <Popover>
      <PopoverTrigger asChild>
        <button
          className="p-1 rounded-md hover:bg-black/5 text-muted-foreground"
          aria-label="Color"
        >
          <Palette size={15} />
        </button>
      </PopoverTrigger>
      <PopoverContent className="w-auto p-2">
        <div className="grid grid-cols-5 gap-1.5">
          {NOTE_COLORS.map((c) => (
            <button
              key={c.id}
              onClick={() => onChange(c.id)}
              className={`w-7 h-7 rounded-full border border-black/10 ${c.bg} ${
                value === c.id ? "ring-2 ring-offset-1 " + c.ring : ""
              }`}
              aria-label={c.id}
            />
          ))}
        </div>
      </PopoverContent>
    </Popover>
  );
}

function LabelMenu({
  labels,
  selected,
  onChange,
}: {
  labels: NoteLabel[];
  selected: number[];
  onChange: (ids: number[]) => void;
}) {
  const { t } = useTranslation();
  const create = useCreateLabel();
  const [name, setName] = useState("");

  const toggle = (id: number) => {
    if (selected.includes(id)) onChange(selected.filter((x) => x !== id));
    else onChange([...selected, id]);
  };

  return (
    <Popover>
      <PopoverTrigger asChild>
        <button
          className="p-1 rounded-md hover:bg-black/5 text-muted-foreground"
          aria-label="Labels"
        >
          <Tag size={15} />
        </button>
      </PopoverTrigger>
      <PopoverContent className="w-56 p-2">
        <div className="space-y-1 max-h-48 overflow-y-auto">
          {labels.length === 0 && (
            <div className="text-xs text-muted-foreground px-2 py-1">
              {t("notes.noLabelsYet", "No labels yet")}
            </div>
          )}
          {labels.map((l) => (
            <button
              key={l.id}
              onClick={() => toggle(l.id)}
              className="w-full flex items-center justify-between px-2 py-1 text-sm rounded hover:bg-slate-100"
            >
              <span className="flex items-center gap-2">
                <Tag size={12} /> {l.name}
              </span>
              {selected.includes(l.id) && <Check size={14} />}
            </button>
          ))}
        </div>
        <div className="mt-2 flex gap-1 border-t pt-2">
          <Input
            value={name}
            onChange={(e) => setName(e.target.value)}
            placeholder={t("notes.newLabel", "New label")}
            className="h-8 text-sm"
            onKeyDown={(e) => {
              if (e.key === "Enter" && name.trim()) {
                create.mutate(name.trim(), { onSuccess: () => setName("") });
              }
            }}
          />
          <Button
            size="sm"
            variant="ghost"
            disabled={!name.trim()}
            onClick={() =>
              create.mutate(name.trim(), { onSuccess: () => setName("") })
            }
          >
            <Plus size={14} />
          </Button>
        </div>
      </PopoverContent>
    </Popover>
  );
}

function Composer({ labels }: { labels: NoteLabel[] }) {
  const { t } = useTranslation();
  const [open, setOpen] = useState(false);
  const [title, setTitle] = useState("");
  const [content, setContent] = useState("");
  const [color, setColor] = useState("default");
  const [labelIds, setLabelIds] = useState<number[]>([]);
  const create = useCreateNote();
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!open) return;
    const onClick = (e: MouseEvent) => {
      if (!ref.current?.contains(e.target as Node)) {
        save();
      }
    };
    document.addEventListener("mousedown", onClick);
    return () => document.removeEventListener("mousedown", onClick);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [open, title, content, color, labelIds]);

  const reset = () => {
    setTitle("");
    setContent("");
    setColor("default");
    setLabelIds([]);
    setOpen(false);
  };

  const save = () => {
    if (!title.trim() && !content.trim()) {
      reset();
      return;
    }
    create.mutate(
      { title: title.trim(), content: content.trim(), color, labelIds },
      { onSuccess: reset },
    );
  };

  return (
    <div
      ref={ref}
      className={`max-w-xl mx-auto rounded-xl border border-black/10 shadow-sm p-3 transition ${colorBg(
        color,
      )}`}
    >
      {open ? (
        <>
          <Input
            autoFocus
            value={title}
            onChange={(e) => setTitle(e.target.value)}
            placeholder={t("notes.titlePlaceholder", "Title")}
            className="border-0 bg-transparent shadow-none focus-visible:ring-0 px-1 font-semibold"
          />
          <Textarea
            value={content}
            onChange={(e) => setContent(e.target.value)}
            placeholder={t("notes.contentPlaceholder", "Take a note...")}
            className="border-0 bg-transparent shadow-none focus-visible:ring-0 px-1 mt-1 min-h-[80px] resize-none"
          />
          <div className="flex items-center gap-1 mt-2">
            <ColorPicker value={color} onChange={setColor} />
            <LabelMenu
              labels={labels}
              selected={labelIds}
              onChange={setLabelIds}
            />
            <div className="ms-auto">
              <Button size="sm" variant="ghost" onClick={save}>
                {t("notes.save", "Save")}
              </Button>
            </div>
          </div>
        </>
      ) : (
        <button
          onClick={() => setOpen(true)}
          className="w-full text-start text-muted-foreground py-1 px-1"
        >
          {t("notes.takeNote", "Take a note...")}
        </button>
      )}
    </div>
  );
}

function EditNoteDialog({
  note,
  labels,
  onClose,
}: {
  note: Note;
  labels: NoteLabel[];
  onClose: () => void;
}) {
  const { t } = useTranslation();
  const [title, setTitle] = useState(note.title);
  const [content, setContent] = useState(note.content);
  const [color, setColor] = useState(note.color);
  const [labelIds, setLabelIds] = useState<number[]>(note.labelIds);
  const update = useUpdateNote();

  const save = () => {
    update.mutate(
      { id: note.id, title: title.trim(), content: content.trim(), color, labelIds },
      { onSuccess: onClose },
    );
  };

  return (
    <Dialog open onOpenChange={(o) => !o && save()}>
      <DialogContent
        className={`max-w-lg ${colorBg(color)}`}
        onInteractOutside={(e) => {
          e.preventDefault();
          save();
        }}
      >
        <DialogHeader>
          <DialogTitle className="sr-only">
            {t("notes.editTitle", "Edit note")}
          </DialogTitle>
        </DialogHeader>
        <Input
          value={title}
          onChange={(e) => setTitle(e.target.value)}
          placeholder={t("notes.titlePlaceholder", "Title")}
          className="border-0 bg-transparent shadow-none focus-visible:ring-0 px-1 font-semibold text-base"
        />
        <Textarea
          value={content}
          onChange={(e) => setContent(e.target.value)}
          placeholder={t("notes.contentPlaceholder", "Take a note...")}
          className="border-0 bg-transparent shadow-none focus-visible:ring-0 px-1 min-h-[160px]"
        />
        <div className="flex items-center gap-1 mt-2">
          <ColorPicker value={color} onChange={setColor} />
          <LabelMenu labels={labels} selected={labelIds} onChange={setLabelIds} />
          <div className="ms-auto">
            <Button size="sm" onClick={save}>
              {t("notes.save", "Save")}
            </Button>
          </div>
        </div>
      </DialogContent>
    </Dialog>
  );
}

function LabelsDialog({
  open,
  onClose,
  labels,
}: {
  open: boolean;
  onClose: () => void;
  labels: NoteLabel[];
}) {
  const { t } = useTranslation();
  const [name, setName] = useState("");
  const [editingId, setEditingId] = useState<number | null>(null);
  const [editingName, setEditingName] = useState("");
  const create = useCreateLabel();
  const update = useUpdateLabel();
  const del = useDeleteLabel();

  return (
    <Dialog open={open} onOpenChange={(o) => !o && onClose()}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>{t("notes.manageLabels", "Manage labels")}</DialogTitle>
        </DialogHeader>
        <div className="flex gap-2">
          <Input
            value={name}
            onChange={(e) => setName(e.target.value)}
            placeholder={t("notes.newLabel", "New label")}
            onKeyDown={(e) => {
              if (e.key === "Enter" && name.trim()) {
                create.mutate(name.trim(), { onSuccess: () => setName("") });
              }
            }}
          />
          <Button
            disabled={!name.trim()}
            onClick={() =>
              create.mutate(name.trim(), { onSuccess: () => setName("") })
            }
          >
            <Plus size={16} />
          </Button>
        </div>
        <div className="space-y-1 max-h-72 overflow-y-auto">
          {labels.length === 0 && (
            <div className="text-sm text-muted-foreground py-4 text-center">
              {t("notes.noLabelsYet", "No labels yet")}
            </div>
          )}
          {labels.map((l) => (
            <div
              key={l.id}
              className="flex items-center gap-2 py-1.5 px-2 rounded hover:bg-slate-100 group"
            >
              <Tag size={14} className="text-muted-foreground" />
              {editingId === l.id ? (
                <>
                  <Input
                    value={editingName}
                    onChange={(e) => setEditingName(e.target.value)}
                    autoFocus
                    className="h-7"
                    onKeyDown={(e) => {
                      if (e.key === "Enter" && editingName.trim()) {
                        update.mutate(
                          { id: l.id, name: editingName.trim() },
                          { onSuccess: () => setEditingId(null) },
                        );
                      }
                      if (e.key === "Escape") setEditingId(null);
                    }}
                  />
                  <button
                    onClick={() => {
                      if (editingName.trim())
                        update.mutate(
                          { id: l.id, name: editingName.trim() },
                          { onSuccess: () => setEditingId(null) },
                        );
                    }}
                    className="p-1 text-muted-foreground hover:text-foreground"
                  >
                    <Check size={14} />
                  </button>
                  <button
                    onClick={() => setEditingId(null)}
                    className="p-1 text-muted-foreground hover:text-foreground"
                  >
                    <X size={14} />
                  </button>
                </>
              ) : (
                <>
                  <span
                    className="flex-1 text-sm cursor-pointer"
                    onClick={() => {
                      setEditingId(l.id);
                      setEditingName(l.name);
                    }}
                  >
                    {l.name}
                  </span>
                  <button
                    onClick={() => {
                      if (confirm(t("notes.deleteLabelConfirm", "Delete this label?"))) {
                        del.mutate(l.id);
                      }
                    }}
                    className="p-1 text-muted-foreground hover:text-destructive opacity-0 group-hover:opacity-100"
                  >
                    <Trash2 size={14} />
                  </button>
                </>
              )}
            </div>
          ))}
        </div>
      </DialogContent>
    </Dialog>
  );
}
