﻿import { useCallback, useEffect, useState } from 'react';
import { resolveApiBase } from '../lib/api-base';

export interface SupplierRegion {
  code: string;
  name: string;
  po_count: number;
  total_value: number;
}

export interface SupplierSnapshot {
  id: number;
  name: string;
  code?: string | null;
  region?: string | null;  // Primary region name (e.g. "EASTERN REGION")
  regionCode?: string | null;  // Primary region code (e.g. "ER")
  regions?: SupplierRegion[];  // All regions this supplier delivers to
  phone?: string | null;
  address?: string | null;
}

export interface RegionOption {
  code: string;
  name: string;
  supplierCount: number;
}

export type SupplierRefreshResult =
  | { status: 'ok'; message: string; syncedAt: string; total: number }
  | { status: 'cooldown'; message: string; retryInMs: number }
  | { status: 'error'; message: string };

const CACHE_KEY = 'monrita_supplier_directory_v3';
const REFRESH_KEY = 'monrita_supplier_directory_refresh_v3';
const REGIONS_CACHE_KEY = 'monrita_supplier_regions_v1';
const MIN_REFRESH_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes
const PAGE_SIZE = 100;

const API_BASE = resolveApiBase();

const normaliseSupplierName = (name: string): string => {
  return name ? name.trim().toUpperCase() : 'UNKNOWN SUPPLIER';
};

const mapBackendSupplier = (item: any): SupplierSnapshot => {
  return {
    id: Number(item.id),
    name: normaliseSupplierName(item.name),
    code: item.code ?? null,
    region: item.primary_region ?? null,  // Use primary_region from backend
    regionCode: item.primary_region_code ?? null,
    regions: item.regions ?? [],
    phone: item.phone ?? item.contact_phone ?? null,
    address: item.address ?? null,
  };
};

interface FetchResult {
  suppliers: SupplierSnapshot[];
  regions: RegionOption[];
}

const fetchAllSuppliers = async (forceSync: boolean = false, onProgress?: (msg: string) => void): Promise<FetchResult> => {
  let accumulated: SupplierSnapshot[] = [];
  let allRegions: RegionOption[] = [];
  let page = 1;
  let lastPage = 1;

  // Initial Fetch
  do {
    // Only trigger heavy sync on the first page request, and only if forced
    const syncParam = (page === 1 && forceSync) ? '&sync=true' : '';
    const url = `${API_BASE}/suppliers?page=${page}&per_page=${PAGE_SIZE}${syncParam}`;
    
    if (onProgress) {
        if (forceSync && page === 1) {
            onProgress("Syncing with external directories... this may take up to 2 minutes");
        } else {
            onProgress(`Loading local cache page ${page}...`);
        }
    }

    const headers: HeadersInit = {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
    };
    if (typeof window !== 'undefined') {
        const token = localStorage.getItem('gcx_fshs_token');
        if (token) headers['Authorization'] = `Bearer ${token}`;
    }

    const response = await fetch(url, { headers });

    if (!response.ok) {
      if (response.status === 504 || response.status === 524) {
         throw new Error("Sync timed out. please try again later.");
      }
      throw new Error(`Backend API responded with status ${response.status}`);
    }
    
    // Check content type to avoid "Unexpected token <" HTML errors
    const type = response.headers.get("content-type");
    if (type && type.includes("text/html")) {
        throw new Error("Server returned HTML error (likely timeout or memory limit).");
    }

    const body = await response.json();
    
    // Handle Monrita Backend Response Structure: { data: [...], meta: { ... }, regions: [...] }
    const results = Array.isArray(body?.data) ? body.data : [];
    const meta = body?.meta;

    // Capture regions from first page response
    if (page === 1 && body?.regions) {
      allRegions = body.regions.map((r: any) => ({
        code: r.region_code,
        name: r.region_name,
        supplierCount: r.supplier_count || 0
      }));
    }

    accumulated = accumulated.concat(results.map(mapBackendSupplier));
    
    // Update pagination info
    lastPage = meta?.last_page ?? 1;
    page++;

  } while (page <= lastPage);

  // Client-side deduplication just in case
  const deduped = Array.from(new Map(accumulated.map((supplier) => [supplier.id, supplier])).values());
  return { suppliers: deduped, regions: allRegions };
};

export function useSupplierDirectory() {
  const [suppliers, setSuppliers] = useState<SupplierSnapshot[]>([]);
  const [availableRegions, setAvailableRegions] = useState<RegionOption[]>([]);
  const [totalCount, setTotalCount] = useState(0);
  const [isRefreshing, setIsRefreshing] = useState(false);
  const [progressMessage, setProgressMessage] = useState<string>("");
  const [error, setError] = useState<string | null>(null);
  const [lastRefreshed, setLastRefreshed] = useState<Date | null>(null);

  // Load from LocalStorage on mount
  useEffect(() => {
    try {
      // Clear old cache versions
      localStorage.removeItem('monrita_supplier_directory_v2');
      localStorage.removeItem('monrita_supplier_directory_refresh_v2');
      
      const cachedRaw = localStorage.getItem(CACHE_KEY);
      const metaRaw = localStorage.getItem(REFRESH_KEY);
      const regionsRaw = localStorage.getItem(REGIONS_CACHE_KEY);

      if (cachedRaw) {
        const parsed = JSON.parse(cachedRaw);
        if (Array.isArray(parsed)) {
          setSuppliers(parsed);
          setTotalCount(parsed.length);
        }
      }

      if (regionsRaw) {
        const parsedRegions = JSON.parse(regionsRaw);
        if (Array.isArray(parsedRegions)) {
          setAvailableRegions(parsedRegions);
        }
      }

      if (metaRaw) {
        const meta = JSON.parse(metaRaw);
        if (meta.timestamp) {
          setLastRefreshed(new Date(meta.timestamp));
        }
      }
    } catch (err) {
      console.warn('Failed to load supplier directory from cache', err);
    }
  }, []);

  const refreshDirectory = useCallback(
    async (force = false): Promise<SupplierRefreshResult> => {
      const now = Date.now();
      const lastSync = lastRefreshed ? lastRefreshed.getTime() : 0;
      const elapsed = now - lastSync;

      if (force) {
        console.log("Forcing live supplier sync...");
      }

      if (!force && elapsed < MIN_REFRESH_INTERVAL_MS && suppliers.length > 0) {
        return {
          status: 'cooldown',
          message: `Directory is fresh. Retry in ${Math.ceil((MIN_REFRESH_INTERVAL_MS - elapsed) / 1000)}s`,
          retryInMs: MIN_REFRESH_INTERVAL_MS - elapsed,
        };
      }

      setIsRefreshing(true);
      setProgressMessage("Initializing...");
      setError(null);
      try {
        // Pass 'force' to fetch function to trigger backend sync
        const { suppliers: freshData, regions: freshRegions } = await fetchAllSuppliers(force, (msg) => setProgressMessage(msg));
        
        // Update State
        setSuppliers(freshData);
        setTotalCount(freshData.length);
        setAvailableRegions(freshRegions);
        setLastRefreshed(new Date(now));

        // Update Cache
        localStorage.setItem(CACHE_KEY, JSON.stringify(freshData));
        localStorage.setItem(REGIONS_CACHE_KEY, JSON.stringify(freshRegions));
        localStorage.setItem(REFRESH_KEY, JSON.stringify({ timestamp: now, count: freshData.length }));

        return {
          status: 'ok',
          message: `Successfully synced ${freshData.length} suppliers from backend.`,
          syncedAt: new Date(now).toISOString(),
          total: freshData.length,
        };
      } catch (error: any) {
        console.error('Supplier directory sync failed:', error);
        setError(error.message || 'Complete sync failed');
        return { status: 'error', message: error.message || 'Unknown error' };
      } finally {
        setIsRefreshing(false);
        setProgressMessage("");
      }
    },
    [lastRefreshed, suppliers.length]
  );

  const lookupSupplier = useCallback(
    (idOrName: number | string): SupplierSnapshot | undefined => {
      if (!suppliers.length) return undefined;
      
      // Try exact ID match
      if (typeof idOrName === 'number') {
        const found = suppliers.find((s) => s.id === idOrName);
        if (found) return found;
      }

      // Try fuzzy name match
      const query = String(idOrName).toLowerCase().trim();
      return suppliers.find(
        (s) => s.name.toLowerCase() === query || s.code?.toLowerCase() === query
      );
    },
    [suppliers]
  );

  const searchSuppliers = useCallback(
    (query: string): SupplierSnapshot[] => {
      if (!query) return suppliers.slice(0, 50); // Return top 50 if empty
      const term = query.toLowerCase().trim();
      return suppliers
        .filter(
          (s) =>
            s.name.toLowerCase().includes(term) ||
            s.code?.toLowerCase().includes(term) ||
            s.phone?.includes(term) ||
            s.region?.toLowerCase().includes(term) ||
            s.regionCode?.toLowerCase().includes(term)
        )
        .slice(0, 50);
    },
    [suppliers]
  );

  // Filter suppliers by region
  const filterByRegion = useCallback(
    (regionCode: string): SupplierSnapshot[] => {
      if (!regionCode) return suppliers;
      const code = regionCode.toUpperCase();
      return suppliers.filter(
        (s) => 
          s.regionCode === code || 
          s.regions?.some(r => r.code === code)
      );
    },
    [suppliers]
  );

  // Backward compatibility: expose stats object for existing UI code
  const supplierStats = { total: totalCount };

  return {
    suppliers,
    availableRegions,
    totalCount,
    isRefreshing,
    progressMessage,
    error,
    lastRefreshed,
    refreshDirectory,
    lookupSupplier,
    searchSuppliers,
    filterByRegion,
    // Backward compatibility aliases
    supplierStats,
    stats: supplierStats,
    refreshSuppliers: refreshDirectory,
  };
}
