"use client";

import React, { createContext, useContext, useEffect, useMemo, useState } from "react";
import { emptyEcommerceStore, type BrandRecord, type CategoryRecord, type EcommerceStore, type ProductRecord } from "@/data/ecommerceStore";
import type { Product } from "@/data/products";
import { api, getStoredToken, mediaOrPlaceholder, resolveMediaUrl, type ProductApi } from "@/lib/api";

interface StoreContextType {
  store: EcommerceStore;
  catalogProducts: Product[];
  catalogCategories: string[];
  refreshStore: () => Promise<void>;
  addCategory: (payload: Pick<CategoryRecord, "name" | "slug" | "image" | "parent_id">) => Promise<void>;
  addBrand: (payload: Pick<BrandRecord, "name" | "logo">) => Promise<void>;
  addProduct: (payload: Omit<ProductRecord, "id" | "created_at" | "updated_at">) => Promise<void>;
}

const StoreContext = createContext<StoreContextType | undefined>(undefined);
const STORAGE_KEY = "gns_glow_store_v1";

const safeReadStore = (): EcommerceStore => {
  if (typeof window === "undefined") return emptyEcommerceStore;
  const raw = window.localStorage.getItem(STORAGE_KEY);
  return raw ? (JSON.parse(raw) as EcommerceStore) : emptyEcommerceStore;
};

const mapApiProductToRecord = (product: ProductApi): ProductRecord => ({
  id: String(product.id),
  category_id: String(product.category_id),
  brand_id: String(product.brand_id),
  sku: product.sku || `SKU-${product.id}`,
  barcode: product.barcode || "",
  name: product.name,
  slug: product.slug || product.name.toLowerCase().replace(/\s+/g, "-"),
  description: product.description || "",
  cost_price: Number(product.cost_price || 0),
  selling_price: Number(product.selling_price || 0),
  sale_price: product.sale_price ? Number(product.sale_price) : undefined,
  stock: product.stock ?? 0,
  weight: Number(product.weight || 0),
  status: product.status === "inactive" ? "inactive" : "active",
  featured: Boolean(product.featured),
  created_at: product.created_at || new Date().toISOString(),
  updated_at: product.updated_at || new Date().toISOString(),
});

const toCatalogProducts = (db: EcommerceStore): Product[] =>
  db.products.filter((p) => p.status === "active").map((item) => {
    const category = db.categories.find((c) => c.id === item.category_id);
    const brand = db.brands.find((b) => b.id === item.brand_id);
    const image = mediaOrPlaceholder(
      db.product_images.find((img) => img.product_id === item.id && img.is_main)?.image ||
        db.product_images.find((img) => img.product_id === item.id)?.image,
    );
    const reviewItems = db.product_reviews.filter((r) => r.product_id === item.id);
    const avgRating = reviewItems.length ? Number((reviewItems.reduce((s, r) => s + r.rating, 0) / reviewItems.length).toFixed(1)) : 4.5;
    return {
      id: item.id,
      name: item.name,
      brand: brand?.name || "Unknown Brand",
      category: category?.name || "Uncategorized",
      price: item.sale_price || item.selling_price,
      originalPrice: item.sale_price ? item.selling_price : undefined,
      description: item.description,
      longDescription: item.description,
      features: [`SKU: ${item.sku}`, `Barcode: ${item.barcode}`, `Stock: ${item.stock}`, `Weight: ${item.weight} kg`],
      specifications: { SKU: item.sku, Barcode: item.barcode, Stock: String(item.stock), "Cost Price": `$${item.cost_price}` },
      colors: [{ name: "Default", hex: "#9ca3af", image }],
      rating: avgRating,
      reviews: reviewItems.length,
      badge: item.featured ? "Featured" : undefined,
    };
  });

export const StoreProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  // Always start empty so SSR HTML matches the first client render (avoids hydration mismatch).
  const [store, setStore] = useState<EcommerceStore>(emptyEcommerceStore);

  const persist = (nextStore: EcommerceStore) => {
    setStore(nextStore);
    if (typeof window !== "undefined") window.localStorage.setItem(STORAGE_KEY, JSON.stringify(nextStore));
  };

  const refreshStore = async () => {
    try {
      const [categories, brands, productsResponse] = await Promise.all([
        api.catalog.categories(),
        api.catalog.brands(),
        api.catalog.products(""),
      ]);
      // Fetch images in small batches to avoid flooding the API / locking the UI
      const productImages: Awaited<ReturnType<typeof api.catalog.productImages>> = [];
      const chunkSize = 8;
      for (let i = 0; i < productsResponse.data.length; i += chunkSize) {
        const chunk = productsResponse.data.slice(i, i + chunkSize);
        const imageCollections = await Promise.all(
          chunk.map((product) => api.catalog.productImages(product.id).catch(() => [])),
        );
        productImages.push(...imageCollections.flat());
      }
      const nextStore: EcommerceStore = {
        ...emptyEcommerceStore,
        categories: categories.map((category) => ({
          id: String(category.id),
          parent_id: category.parent_id ? String(category.parent_id) : undefined,
          name: category.name,
          slug: category.slug,
          image: resolveMediaUrl(category.image),
        })),
        brands: brands.map((brand) => ({
          id: String(brand.id),
          name: brand.name,
          logo: resolveMediaUrl(brand.logo),
        })),
        products: productsResponse.data.map(mapApiProductToRecord),
        product_images: productImages.map((image) => ({
          id: String(image.id),
          product_id: String(image.product_id),
          image: resolveMediaUrl(image.image),
          is_main: Boolean(image.is_main),
          sort_order: image.sort_order || 0,
        })),
      };
      persist(nextStore);
    } catch {
      // keep local state if API unavailable
    }
  };

  useEffect(() => {
    const cached = safeReadStore();
    if (cached.categories.length || cached.products.length) {
      setStore({
        ...cached,
        categories: cached.categories.map((c) => ({ ...c, image: resolveMediaUrl(c.image) })),
        brands: cached.brands.map((b) => ({ ...b, logo: resolveMediaUrl(b.logo) })),
        product_images: cached.product_images.map((img) => ({
          ...img,
          image: resolveMediaUrl(img.image),
        })),
      });
    }
    void refreshStore();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const addCategory: StoreContextType["addCategory"] = async (payload) => {
    const token = getStoredToken();
    await api.admin.createCategory(
      {
        parent_id: payload.parent_id ? Number(payload.parent_id) : null,
        name: payload.name,
        slug: payload.slug,
        image: payload.image || null,
      },
      token,
    );
    await refreshStore();
  };

  const addBrand: StoreContextType["addBrand"] = async (payload) => {
    const token = getStoredToken();
    await api.admin.createBrand(
      { name: payload.name, logo: payload.logo || null },
      token,
    );
    await refreshStore();
  };

  const addProduct: StoreContextType["addProduct"] = async (payload) => {
    const token = getStoredToken();
    await api.admin.createProduct(
      {
        category_id: Number(payload.category_id),
        brand_id: Number(payload.brand_id),
        sku: payload.sku,
        barcode: payload.barcode,
        name: payload.name,
        slug: payload.slug,
        description: payload.description,
        cost_price: payload.cost_price,
        selling_price: payload.selling_price,
        sale_price: payload.sale_price,
        stock: payload.stock,
        weight: payload.weight,
        status: payload.status,
        featured: payload.featured,
      },
      token,
    );
    await refreshStore();
  };

  const catalogProducts = useMemo(() => toCatalogProducts(store), [store]);
  const catalogCategories = useMemo(() => ["All", ...store.categories.map((c) => c.name)], [store.categories]);

  return <StoreContext.Provider value={{ store, catalogProducts, catalogCategories, refreshStore, addCategory, addBrand, addProduct }}>{children}</StoreContext.Provider>;
};

export const useStore = () => {
  const ctx = useContext(StoreContext);
  if (!ctx) throw new Error("useStore must be used within StoreProvider");
  return ctx;
};
