'use client';

import { createContext, useContext, useState, useCallback, useEffect, type ReactNode } from 'react';
import { KNOWN_PRODUCTS, PRODUCT_ID, type Product } from '@/lib/product-constants';

const STORAGE_KEY = 'tracker_selected_product';
const PRODUCT_CHANGED_EVENT = 'tracker:product-changed';

interface ProductContextValue {
  productId: string;
  productName: string;
  setProductId: (id: string) => void;
  products: readonly Product[];
}

const ProductContext = createContext<ProductContextValue | null>(null);

function getInitialProduct(): string {
  if (typeof window === 'undefined') return PRODUCT_ID;
  return localStorage.getItem(STORAGE_KEY) || PRODUCT_ID;
}

/** Map the platform-service product docs to the switcher's lightweight shape. */
function toProducts(docs: unknown): Product[] {
  if (!Array.isArray(docs)) return [];
  const out: Product[] = [];
  for (const d of docs) {
    if (!d || typeof d !== 'object') continue;
    const { productId, id, displayName, name } = d as Record<string, unknown>;
    const pid = typeof productId === 'string' ? productId : typeof id === 'string' ? id : null;
    if (!pid) continue;
    const label =
      typeof displayName === 'string' ? displayName : typeof name === 'string' ? name : pid;
    out.push({ id: pid, name: label });
  }
  return out;
}

export function ProductProvider({ children }: { children: ReactNode }) {
  const [productId, setProductIdState] = useState<string>(getInitialProduct);
  // Start from the configured list (env/default); replace with the caller's
  // owner-scoped projects once fetched. Falling back keeps dev/unauth working.
  const [products, setProducts] = useState<readonly Product[]>(KNOWN_PRODUCTS);

  useEffect(() => {
    function syncSelectedProduct() {
      setProductIdState(getInitialProduct());
    }

    window.addEventListener(PRODUCT_CHANGED_EVENT, syncSelectedProduct);
    window.addEventListener('storage', syncSelectedProduct);
    return () => {
      window.removeEventListener(PRODUCT_CHANGED_EVENT, syncSelectedProduct);
      window.removeEventListener('storage', syncSelectedProduct);
    };
  }, []);

  // Fetch the authenticated user's projects ("my projects") and use them as the
  // switcher list. Best-effort: any failure / empty result keeps the configured
  // fallback, so an unauthenticated or offline dashboard still renders.
  useEffect(() => {
    if (typeof window === 'undefined') return;
    const token = localStorage.getItem('tracker_token');
    if (!token) return;
    let cancelled = false;
    (async () => {
      try {
        const res = await fetch('/api/products/mine', {
          headers: { Authorization: `Bearer ${token}` },
        });
        if (!res.ok) return;
        const json: unknown = await res.json();
        const list = toProducts((json as { products?: unknown }).products);
        if (!cancelled && list.length > 0) setProducts(list);
      } catch {
        /* keep the configured fallback */
      }
    })();
    return () => {
      cancelled = true;
    };
  }, []);

  const setProductId = useCallback((id: string) => {
    setProductIdState(id);
    if (typeof window !== 'undefined') {
      localStorage.setItem(STORAGE_KEY, id);
      window.dispatchEvent(new Event(PRODUCT_CHANGED_EVENT));
    }
  }, []);

  const product = products.find(p => p.id === productId);
  const productName = product?.name ?? productId;

  return (
    <ProductContext.Provider value={{ productId, productName, setProductId, products }}>
      {children}
    </ProductContext.Provider>
  );
}

export function useProduct(): ProductContextValue {
  const ctx = useContext(ProductContext);
  if (!ctx) throw new Error('useProduct must be used within <ProductProvider>');
  return ctx;
}
