"use client";

import { useRef, useState } from "react";
import {
  ArrowRight,
  Barcode,
  Calendar,
  Circle as CircleIcon,
  Hash,
  Heading1,
  Highlighter,
  Image as ImageIcon,
  Minus,
  PanelBottom,
  PanelTop,
  PenLine,
  PenTool,
  QrCode,
  Square,
  Stamp,
  StickyNote,
  Table,
  Type,
} from "lucide-react";
import { toast } from "sonner";
import type { FabricObject } from "fabric";
import * as make from "@/lib/editor/objects";
import type { PageNumberFormat } from "@/lib/editor/objects";
import {
  BarcodeDialog,
  HeaderFooterDialog,
  PageNumberDialog,
  QrDialog,
  SignatureDialog,
  TableDialog,
  WatermarkDialog,
} from "./insert-dialogs";

interface PageDims {
  width: number;
  height: number;
}

export interface InsertApi {
  /** Add one object to the current page. */
  addObject: (factory: (dims: PageDims) => FabricObject | Promise<FabricObject>) => void;
  /** Add an object to every page (factory receives 1-based page number and total). */
  addToAllPages: (factory: (dims: PageDims, pageNo: number, total: number) => FabricObject) => void;
  isDrawing: boolean;
  setDrawing: (on: boolean, color: string, width: number) => void;
}

type DialogKind = "qr" | "barcode" | "table" | "watermark" | "header" | "footer" | "page-number" | "signature" | null;

function PanelButton({
  icon: Icon,
  label,
  active,
  onClick,
}: {
  icon: React.ComponentType<{ className?: string }>;
  label: string;
  active?: boolean;
  onClick: () => void;
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={`flex w-full items-center gap-2.5 rounded-md px-2.5 py-1.5 text-left text-sm transition-colors ${
        active
          ? "bg-brand-600 text-white"
          : "text-slate-700 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700"
      }`}
    >
      <Icon className="h-4 w-4 shrink-0" />
      {label}
    </button>
  );
}

function SectionLabel({ children }: { children: React.ReactNode }) {
  return (
    <p className="px-2.5 pb-1 pt-3 text-[11px] font-semibold uppercase tracking-wide text-slate-400 dark:text-slate-500">
      {children}
    </p>
  );
}

export function InsertPanel({ api }: { api: InsertApi }) {
  const [dialog, setDialog] = useState<DialogKind>(null);
  const [brushColor, setBrushColor] = useState("#dc2626");
  const [brushWidth, setBrushWidth] = useState(3);
  const imageInputRef = useRef<HTMLInputElement>(null);

  function insertImage(file: File | undefined) {
    if (!file) return;
    if (file.size > 8 * 1024 * 1024) {
      toast.error("Image is too large (max 8 MB)");
      return;
    }
    const reader = new FileReader();
    reader.onload = () => api.addObject((dims) => make.makeImageFromDataUrl(dims, String(reader.result)));
    reader.readAsDataURL(file);
  }

  function toggleDraw() {
    api.setDrawing(!api.isDrawing, brushColor, brushWidth);
  }

  return (
    <aside className="flex w-52 shrink-0 flex-col overflow-y-auto border-r border-slate-200 bg-white py-2 dark:border-slate-700 dark:bg-slate-800">
      <SectionLabel>Insert</SectionLabel>
      <PanelButton icon={Type} label="Text" onClick={() => api.addObject((d) => make.makeText(d))} />
      <PanelButton icon={Heading1} label="Heading" onClick={() => api.addObject((d) => make.makeText(d, { heading: true }))} />
      <PanelButton icon={ImageIcon} label="Image" onClick={() => imageInputRef.current?.click()} />
      <PanelButton icon={Table} label="Table" onClick={() => setDialog("table")} />
      <PanelButton icon={PenTool} label="Signature" onClick={() => setDialog("signature")} />
      <PanelButton icon={QrCode} label="QR code" onClick={() => setDialog("qr")} />
      <PanelButton icon={Barcode} label="Barcode" onClick={() => setDialog("barcode")} />
      <PanelButton icon={Calendar} label="Date" onClick={() => api.addObject((d) => make.makeDate(d))} />

      <SectionLabel>Shapes</SectionLabel>
      <PanelButton icon={Square} label="Rectangle" onClick={() => api.addObject((d) => make.makeRect(d))} />
      <PanelButton icon={CircleIcon} label="Ellipse" onClick={() => api.addObject((d) => make.makeEllipse(d))} />
      <PanelButton icon={Minus} label="Line" onClick={() => api.addObject((d) => make.makeLine(d))} />
      <PanelButton icon={ArrowRight} label="Arrow" onClick={() => api.addObject((d) => make.makeArrow(d))} />

      <SectionLabel>Annotate</SectionLabel>
      <PanelButton icon={PenLine} label={api.isDrawing ? "Stop drawing" : "Draw (pen)"} active={api.isDrawing} onClick={toggleDraw} />
      {api.isDrawing && (
        <div className="mx-2.5 mb-1 flex items-center gap-2 rounded-md bg-slate-100 p-2 dark:bg-slate-700">
          <input
            type="color"
            aria-label="Pen color"
            value={brushColor}
            onChange={(e) => {
              setBrushColor(e.target.value);
              api.setDrawing(true, e.target.value, brushWidth);
            }}
            className="h-7 w-8 cursor-pointer rounded border-0 bg-transparent"
          />
          <input
            type="range"
            aria-label="Pen width"
            min={1}
            max={16}
            value={brushWidth}
            onChange={(e) => {
              const w = Number(e.target.value);
              setBrushWidth(w);
              api.setDrawing(true, brushColor, w);
            }}
            className="w-full"
          />
        </div>
      )}
      <PanelButton icon={Highlighter} label="Highlight" onClick={() => api.addObject((d) => make.makeHighlight(d))} />
      <PanelButton icon={StickyNote} label="Sticky note" onClick={() => api.addObject((d) => make.makeStickyNote(d))} />

      <SectionLabel>Document</SectionLabel>
      <PanelButton icon={Stamp} label="Watermark" onClick={() => setDialog("watermark")} />
      <PanelButton icon={PanelTop} label="Header" onClick={() => setDialog("header")} />
      <PanelButton icon={PanelBottom} label="Footer" onClick={() => setDialog("footer")} />
      <PanelButton icon={Hash} label="Page numbers" onClick={() => setDialog("page-number")} />

      <input
        ref={imageInputRef}
        type="file"
        accept="image/png,image/jpeg"
        className="hidden"
        onChange={(e) => {
          insertImage(e.target.files?.[0]);
          e.target.value = "";
        }}
      />

      {dialog === "qr" && (
        <QrDialog
          onClose={() => setDialog(null)}
          onInsert={(content) =>
            api.addObject(async (d) => {
              try {
                return await make.makeQrCode(d, content);
              } catch {
                toast.error("Could not generate the QR code");
                throw new Error("qr failed");
              }
            })
          }
        />
      )}
      {dialog === "barcode" && (
        <BarcodeDialog
          onClose={() => setDialog(null)}
          onInsert={(content, format) =>
            api.addObject(async (d) => {
              try {
                return await make.makeBarcode(d, content, format);
              } catch {
                toast.error(`"${content}" is not valid for the ${format} format`);
                throw new Error("barcode failed");
              }
            })
          }
        />
      )}
      {dialog === "table" && (
        <TableDialog onClose={() => setDialog(null)} onInsert={(rows, cols) => api.addObject((d) => make.makeTable(d, rows, cols))} />
      )}
      {dialog === "watermark" && (
        <WatermarkDialog
          onClose={() => setDialog(null)}
          onInsert={(text, opacity, allPages) => {
            if (allPages) api.addToAllPages((d) => make.makeWatermark(d, text, opacity));
            else api.addObject((d) => make.makeWatermark(d, text, opacity));
          }}
        />
      )}
      {(dialog === "header" || dialog === "footer") && (
        <HeaderFooterDialog
          where={dialog}
          onClose={() => setDialog(null)}
          onInsert={(text, allPages) => {
            const where = dialog;
            if (allPages) api.addToAllPages((d) => make.makeHeaderFooter(d, text, where));
            else api.addObject((d) => make.makeHeaderFooter(d, text, where));
          }}
        />
      )}
      {dialog === "page-number" && (
        <PageNumberDialog
          onClose={() => setDialog(null)}
          onInsert={(format: PageNumberFormat, position) =>
            api.addToAllPages((d, pageNo, total) => make.makePageNumber(d, pageNo, total, format, position))
          }
        />
      )}
      {dialog === "signature" && (
        <SignatureDialog
          onClose={() => setDialog(null)}
          onInsertImage={(dataUrl) => api.addObject((d) => make.makeImageFromDataUrl(d, dataUrl, "signature"))}
          onInsertTyped={(name) => api.addObject((d) => make.makeSignatureText(d, name))}
        />
      )}
    </aside>
  );
}
