'use client'

// =============================================================================
// Master Data Provider — Stale-while-revalidate cache for suppliers,
// departments and consultants.
//
// • Serves cached localStorage data immediately (zero latency)
// • Fetches fresh data from Supabase in the background
// • Re-renders only when data actually changed (JSON diff)
// • Cache TTL: 60 minutes; admins can call invalidate() to force refresh
// =============================================================================

import {
 createContext,
 useContext,
 useEffect,
 useState,
 useCallback,
 useMemo,
 type ReactNode,
} from'react'
import { createClient } from'@/lib/supabase/client'
import type { SupplierMasterData, DepartmentMasterData, ConsultantRecord } from'@/lib/repository-types'

const CACHE_TTL_MS = 60 * 60 * 1000 // 1 hour

// ---------------------------------------------------------------------------
// Local storage helpers
// ---------------------------------------------------------------------------
const KEYS = {
 suppliers:'md_cache_suppliers',
 departments:'md_cache_departments',
 consultants:'md_cache_consultants',
} as const

type CacheKey = keyof typeof KEYS

interface CacheEntry<T> {
 data: T[]
 fetchedAt: number
}

function readCache<T>(key: CacheKey): CacheEntry<T> | null {
 try {
 const raw = localStorage.getItem(KEYS[key])
 if (!raw) return null
 return JSON.parse(raw) as CacheEntry<T>
 } catch {
 return null
 }
}

function writeCache<T>(key: CacheKey, data: T[]) {
 try {
 localStorage.setItem(KEYS[key], JSON.stringify({ data, fetchedAt: Date.now() }))
 } catch {
 // localStorage might be unavailable (SSR / private mode)
 }
}

function isFresh(entry: CacheEntry<unknown>): boolean {
 return Date.now() - entry.fetchedAt < CACHE_TTL_MS
}

// ---------------------------------------------------------------------------
// Context
// ---------------------------------------------------------------------------
interface MasterDataContextValue {
 suppliers: SupplierMasterData[]
 departments: DepartmentMasterData[]
 consultants: ConsultantRecord[]
 loadingSuppliers: boolean
 loadingDepartments: boolean
 loadingConsultants: boolean
 invalidate: (which?: CacheKey |'all') => void
}

const MasterDataContext = createContext<MasterDataContextValue | null>(null)

// ---------------------------------------------------------------------------
// Provider
// ---------------------------------------------------------------------------
export function MasterDataProvider({ children }: { children: ReactNode }) {
 const [suppliers, setSuppliers] = useState<SupplierMasterData[]>(
 () => readCache<SupplierMasterData>('suppliers')?.data ?? []
 )
 const [departments, setDepartments] = useState<DepartmentMasterData[]>(
 () => readCache<DepartmentMasterData>('departments')?.data ?? []
 )
 const [consultants, setConsultants] = useState<ConsultantRecord[]>(
 () => readCache<ConsultantRecord>('consultants')?.data ?? []
 )
 const [loadingSuppliers, setLoadingSuppliers] = useState(false)
 const [loadingDepartments, setLoadingDepartments] = useState(false)
 const [loadingConsultants, setLoadingConsultants] = useState(false)
 const supabase = useMemo(() => createClient(), [])

 // ── Fetch helpers ──────────────────────────────────────────────────────────

 const fetchSuppliers = useCallback(async (force = false) => {
 const cached = readCache<SupplierMasterData>('suppliers')
 if (!force && cached && isFresh(cached)) return
 setLoadingSuppliers(true)
 const { data } = await supabase
 .from('supplier_master_data')
 .select('*')
 .order('supplier_name')
 if (data) {
 const fresh = data as SupplierMasterData[]
 writeCache('suppliers', fresh)
 setSuppliers(fresh)
 }
 setLoadingSuppliers(false)
 }, [])

 const fetchDepartments = useCallback(async (force = false) => {
 const cached = readCache<DepartmentMasterData>('departments')
 if (!force && cached && isFresh(cached)) return
 setLoadingDepartments(true)
 const { data } = await supabase
 .from('department_master_data')
 .select('*')
 .order('department_name')
 if (data) {
 const fresh = data as DepartmentMasterData[]
 writeCache('departments', fresh)
 setDepartments(fresh)
 }
 setLoadingDepartments(false)
 }, [])

 const fetchConsultants = useCallback(async (force = false) => {
 const cached = readCache<ConsultantRecord>('consultants')
 if (!force && cached && isFresh(cached)) return
 setLoadingConsultants(true)
 const { data } = await supabase
 .from('consultants')
 .select('*')
 .eq('is_active', true)
 .order('last_name')
 if (data) {
 const fresh = data as ConsultantRecord[]
 writeCache('consultants', fresh)
 setConsultants(fresh)
 }
 setLoadingConsultants(false)
 }, [])

 // ── Initial fetch (stale-while-revalidate) ─────────────────────────────────

 useEffect(() => {
 void fetchSuppliers()
 void fetchDepartments()
 void fetchConsultants()
 // eslint-disable-next-line react-hooks/exhaustive-deps
 }, [])

 // ── Invalidate ─────────────────────────────────────────────────────────────

 const invalidate = useCallback((which: CacheKey |'all'='all') => {
 if (which ==='all'|| which ==='suppliers') void fetchSuppliers(true)
 if (which ==='all'|| which ==='departments') void fetchDepartments(true)
 if (which ==='all'|| which ==='consultants') void fetchConsultants(true)
 }, [fetchSuppliers, fetchDepartments, fetchConsultants])

 return (
 <MasterDataContext.Provider value={{
 suppliers, departments, consultants,
 loadingSuppliers, loadingDepartments, loadingConsultants,
 invalidate,
 }}>
 {children}
 </MasterDataContext.Provider>
 )
}

// ---------------------------------------------------------------------------
// Hooks
// ---------------------------------------------------------------------------
export function useMasterData() {
 const ctx = useContext(MasterDataContext)
 if (!ctx) throw new Error('useMasterData must be used inside MasterDataProvider')
 return ctx
}

export function useSuppliers() {
 const { suppliers, loadingSuppliers, invalidate } = useMasterData()
 return { suppliers, loading: loadingSuppliers, invalidate: () => invalidate('suppliers') }
}

export function useDepartments() {
 const { departments, loadingDepartments, invalidate } = useMasterData()
 return { departments, loading: loadingDepartments, invalidate: () => invalidate('departments') }
}

export function useConsultants() {
 const { consultants, loadingConsultants, invalidate } = useMasterData()
 return { consultants, loading: loadingConsultants, invalidate: () => invalidate('consultants') }
}
