"use client";

import {
  createContext,
  type ReactNode,
  useContext,
  useEffect,
  useState,
} from "react";

import type { ViewPreferenceItem } from "@/lib/view-preferences";

const STORAGE_KEY = "propertypilot-hidden-view-items-v1";

type ViewPreferencesContextValue = {
  hiddenIds: string[];
  ready: boolean;
  hideItem: (id: string) => void;
  showItem: (id: string) => void;
  resetItems: () => void;
};

const ViewPreferencesContext =
  createContext<ViewPreferencesContextValue | null>(null);

function useViewPreferences() {
  const context = useContext(ViewPreferencesContext);

  if (!context) {
    throw new Error("useViewPreferences must be used inside ViewPreferencesProvider");
  }

  return context;
}

function readHiddenIds() {
  try {
    const stored = window.localStorage.getItem(STORAGE_KEY);
    const parsed = stored ? JSON.parse(stored) : [];

    return Array.isArray(parsed)
      ? parsed.filter((item): item is string => typeof item === "string")
      : [];
  } catch {
    return [];
  }
}

function groupItems(items: ViewPreferenceItem[]) {
  const groupedItems: Array<[string, ViewPreferenceItem[]]> = [];

  for (const item of items) {
    const group = groupedItems.find(([name]) => name === item.group);

    if (group) {
      group[1].push(item);
    } else {
      groupedItems.push([item.group, [item]]);
    }
  }

  return groupedItems;
}

export function ViewPreferencesProvider({ children }: { children: ReactNode }) {
  const [ready, setReady] = useState(false);
  const [hiddenIds, setHiddenIds] = useState<string[]>([]);

  useEffect(() => {
    const frame = window.requestAnimationFrame(() => {
      setHiddenIds(readHiddenIds());
      setReady(true);
    });

    return () => window.cancelAnimationFrame(frame);
  }, []);

  useEffect(() => {
    if (ready) {
      window.localStorage.setItem(STORAGE_KEY, JSON.stringify(hiddenIds));
    }
  }, [hiddenIds, ready]);

  function hideItem(id: string) {
    setHiddenIds((current) => (current.includes(id) ? current : [...current, id]));
  }

  function showItem(id: string) {
    setHiddenIds((current) => current.filter((item) => item !== id));
  }

  function resetItems() {
    setHiddenIds([]);
  }

  return (
    <ViewPreferencesContext.Provider
      value={{ hiddenIds, ready, hideItem, showItem, resetItems }}
    >
      {children}
    </ViewPreferencesContext.Provider>
  );
}

export function ViewSettingsSection({ items }: { items: ViewPreferenceItem[] }) {
  const { hiddenIds, ready, resetItems, showItem, hideItem } = useViewPreferences();
  const hiddenCount = hiddenIds.length;
  const groupedItems = groupItems(items);

  return (
    <div>
      <div className="flex items-start justify-between gap-3">
        <div>
          <p className="text-sm font-semibold text-foreground">Customise view</p>
          <p className="mt-1 text-xs leading-5 text-muted">
            Untick anything you do not want on the dashboard.
          </p>
        </div>
        <button
          className="text-xs font-semibold text-primary transition hover:text-foreground disabled:cursor-not-allowed disabled:text-muted"
          disabled={!ready || hiddenCount === 0}
          onClick={resetItems}
          type="button"
        >
          Restore all
        </button>
      </div>

      <div className="mt-4 max-h-[360px] space-y-4 overflow-y-auto pr-1">
        {groupedItems.map(([group, groupItems]) => (
          <div key={group}>
            <p className="mb-2 font-mono text-[11px] uppercase tracking-[0.22em] text-muted">
              {group}
            </p>
            <div className="space-y-2">
              {groupItems.map((item) => {
                const checked = !hiddenIds.includes(item.id);

                return (
                  <label
                    className="flex cursor-pointer items-center justify-between gap-3 rounded-[16px] border border-border bg-surface px-3 py-2 text-sm text-foreground transition hover:border-primary/30"
                    key={item.id}
                  >
                    <span>{item.label}</span>
                    <input
                      checked={checked}
                      className="h-4 w-4 accent-primary"
                      onChange={(event) =>
                        event.target.checked ? showItem(item.id) : hideItem(item.id)
                      }
                      type="checkbox"
                    />
                  </label>
                );
              })}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

export function HideableTile({
  anchorId,
  id,
  label,
  children,
}: {
  anchorId?: string;
  id: string;
  label: string;
  children: ReactNode;
}) {
  const { hiddenIds, ready, hideItem } = useViewPreferences();

  if (ready && hiddenIds.includes(id)) {
    return null;
  }

  return (
    <div className="group/hideable relative scroll-mt-36" id={anchorId}>
      <button
        aria-label={`Hide ${label}`}
        className="absolute right-3 top-3 z-10 rounded-full border border-border bg-white/88 px-3 py-1 text-xs font-semibold text-muted opacity-0 shadow-sm backdrop-blur transition hover:border-danger/25 hover:text-danger focus:opacity-100 focus:outline-none focus:ring-4 focus:ring-primary/10 group-hover/hideable:opacity-100"
        onClick={() => hideItem(id)}
        type="button"
      >
        Hide
      </button>
      {children}
    </div>
  );
}

export function CustomiseViewPanel({ items }: { items: ViewPreferenceItem[] }) {
  const { hiddenIds } = useViewPreferences();
  const [open, setOpen] = useState(false);
  const hiddenCount = hiddenIds.length;

  return (
    <div className="relative z-[80]">
      <button
        className="rounded-full border border-border bg-surface-strong px-4 py-2.5 text-sm font-semibold text-foreground transition hover:border-primary/35 hover:text-primary"
        onClick={() => setOpen((current) => !current)}
        type="button"
      >
        Customise view
        {hiddenCount > 0 ? ` (${hiddenCount} hidden)` : ""}
      </button>

      {open ? (
        <div className="absolute right-0 top-[calc(100%+0.75rem)] z-[100] w-[min(92vw,420px)] rounded-[26px] border border-border bg-surface-strong p-4 shadow-[0_24px_80px_rgba(15,35,29,0.16)] backdrop-blur">
          <ViewSettingsSection items={items} />
        </div>
      ) : null}
    </div>
  );
}
