"use client";

import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from "react";
import { readableProductName, readableUnit } from "../lib/catalog-editorial";
type CatalogSelection = { id: string; name: string; category: string; unit: string };

const STORAGE_KEY = "portal.quote.v1";

export type QuoteItem = {
  id: string;
  name: string;
  category: string;
  quantity: number;
  unit: string;
  note: string;
};

type QuoteContextValue = {
  items: QuoteItem[];
  itemCount: number;
  isReady: boolean;
  notice: string;
  addItem: (product: CatalogSelection) => void;
  updateQuantity: (id: string, quantity: number) => void;
  updateNote: (id: string, note: string) => void;
  removeItem: (id: string) => void;
  clearItems: () => void;
};

const QuoteContext = createContext<QuoteContextValue | null>(null);

function sanitizeItems(value: unknown): QuoteItem[] {
  if (!value || typeof value !== "object") return [];
  const maybeItems = (value as { items?: unknown }).items;
  if (!Array.isArray(maybeItems)) return [];

  return maybeItems
    .filter((item): item is QuoteItem => {
      if (!item || typeof item !== "object") return false;
      const candidate = item as Partial<QuoteItem>;
      return (
        typeof candidate.id === "string" &&
        typeof candidate.name === "string" &&
        typeof candidate.category === "string" &&
        typeof candidate.unit === "string" &&
        typeof candidate.quantity === "number" && Number.isFinite(candidate.quantity)
      );
    })
    .map((item) => ({
      ...item,
      name: readableProductName(item.name),
      unit: item.id === "erp-8333" ? "a confirmar" : readableUnit(item.unit),
      quantity: Math.min(999, Math.max(1, Math.round(item.quantity))),
      note: typeof item.note === "string" ? item.note.slice(0, 240) : "",
    }));
}

export function QuoteProvider({ children }: { children: ReactNode }) {
  const [items, setItems] = useState<QuoteItem[]>([]);
  const [isReady, setIsReady] = useState(false);
  const [notice, setNotice] = useState("");

  useEffect(() => {
    const timer = window.setTimeout(() => {
      try {
        const raw = window.localStorage.getItem(STORAGE_KEY);
        if (raw) setItems(sanitizeItems(JSON.parse(raw)));
      } catch {
        // Storage may be blocked by browser settings. Keep this session usable.
      } finally {
        setIsReady(true);
      }
    }, 0);
    return () => window.clearTimeout(timer);
  }, []);

  useEffect(() => {
    if (!isReady) return;
    try { window.localStorage.setItem(
      STORAGE_KEY,
      JSON.stringify({ version: 1, updatedAt: new Date().toISOString(), items }),
    ); } catch { /* The current in-memory list remains usable without storage. */ }
  }, [items, isReady]);

  const announce = useCallback((message: string) => {
    setNotice(message);
    window.setTimeout(() => setNotice(""), 2800);
  }, []);

  const addItem = useCallback(
    (product: CatalogSelection) => {
      setItems((current) => {
        const found = current.find((item) => item.id === product.id);
        if (found) {
          return current.map((item) =>
            item.id === product.id
              ? { ...item, name: product.name, category: product.category, unit: product.unit, quantity: Math.min(999, item.quantity + 1) }
              : item,
          );
        }
        return [
          ...current,
          {
            id: product.id,
            name: product.name,
            category: product.category,
            quantity: 1,
            unit: product.unit,
            note: "",
          },
        ];
      });
      announce(`${product.name} adicionado à lista.`);
    },
    [announce],
  );

  const updateQuantity = useCallback((id: string, quantity: number) => {
    setItems((current) =>
      current.map((item) =>
        item.id === id
          ? { ...item, quantity: Math.min(999, Math.max(1, Math.round(quantity || 1))) }
          : item,
      ),
    );
  }, []);

  const updateNote = useCallback((id: string, note: string) => {
    setItems((current) =>
      current.map((item) =>
        item.id === id ? { ...item, note: note.slice(0, 240) } : item,
      ),
    );
  }, []);

  const removeItem = useCallback(
    (id: string) => {
      setItems((current) => current.filter((item) => item.id !== id));
      announce("Item removido da lista.");
    },
    [announce],
  );

  const clearItems = useCallback(() => {
    setItems([]);
    announce("Lista limpa.");
  }, [announce]);

  const value = useMemo(
    () => ({
      items,
      itemCount: items.length,
      isReady,
      notice,
      addItem,
      updateQuantity,
      updateNote,
      removeItem,
      clearItems,
    }),
    [
      items,
      isReady,
      notice,
      addItem,
      updateQuantity,
      updateNote,
      removeItem,
      clearItems,
    ],
  );

  return (
    <QuoteContext.Provider value={value}>
      {children}
      <div className="toast" role="status" aria-live="polite" data-visible={Boolean(notice)}>
        {notice}
      </div>
    </QuoteContext.Provider>
  );
}

export function useQuote() {
  const context = useContext(QuoteContext);
  if (!context) throw new Error("useQuote must be used inside QuoteProvider");
  return context;
}
