import React, { createContext, useContext, useState, useEffect, useMemo, useCallback } from 'react';
import confetti from 'canvas-confetti';
import {
  Listing,
  Category,
  PaymentTransaction,
  MenuItem,
  SiteSettings,
  DesignSettings,
  FrontendTexts,
  DeveloperProfile,
  FloatingScrollPopup,
  ContentPage,
  GatewayConfig,
  AppState,
  Language,
  Theme,
  TranslationsMap,
  VisitorSettings
} from '../types';
import {
  INITIAL_CATEGORIES,
  INITIAL_LISTINGS,
  INITIAL_PAYMENTS,
  INITIAL_MENU_ITEMS,
  INITIAL_SETTINGS,
  INITIAL_DESIGN,
  INITIAL_TEXTS,
  INITIAL_DEVELOPER,
  INITIAL_SCROLL_POPUP,
  INITIAL_GATEWAYS,
  INITIAL_PAGES
} from '../data/initialData';
import { INITIAL_TRANSLATIONS } from '../data/translations';

interface AppContextType {
  // State
  state: AppState;
  listings: Listing[];
  categories: Category[];
  payments: PaymentTransaction[];
  menuItems: MenuItem[];
  settings: SiteSettings;
  design: DesignSettings;
  texts: FrontendTexts;
  developer: DeveloperProfile;
  scrollPopup: FloatingScrollPopup;
  gateways: GatewayConfig[];
  pages: ContentPage[];
  rankedListings: Listing[];
  topListing: Listing | null;
  totalGeneratedMoney: number;
  totalPages: number;
  paginatedListings: Listing[];
  isAdminLoggedIn: boolean;
  language: Language;
  theme: Theme;
  translations: TranslationsMap;

  visitorSettings: VisitorSettings;

  // Theme & Language Helpers
  setTheme: (theme: Theme) => void;
  toggleTheme: () => void;
  setLanguage: (lang: Language) => void;
  t: (key: string, params?: Record<string, string | number>, defaultText?: string) => string;
  tCategory: (catSlugOrId: string, fallbackName?: string) => string;
  tNum: (num: number | string) => string;
  formatBidAgeI18n: (timestamp: string) => string;
  adminSaveTranslations: (newTranslations: TranslationsMap) => void;
  adminResetTranslations: () => void;

  // Actions
  setTimeFilter: (filter: 'all_time' | 'today') => void;
  setSelectedCategory: (categoryId: string) => void;
  setSearchQuery: (query: string) => void;
  setCurrentPage: (page: number) => void;
  openOutbidModal: (targetListing?: Listing | null) => void;
  closeOutbidModal: () => void;
  openCategoryModal: () => void;
  closeCategoryModal: () => void;
  openDeveloperModal: () => void;
  closeDeveloperModal: () => void;
  openContentModal: (modal: 'rules' | 'terms' | 'privacy' | 'stats') => void;
  closeContentModal: () => void;
  openAdmin: () => void;
  closeAdmin: () => void;
  adminLogin: (password: string) => boolean;
  adminLogout: () => void;

  // Interactions
  handleHeart: (listingId: string) => void;
  handleClick: (listingId: string) => void;
  handleManualRefresh: () => void;

  // Outbid & Payment Execution
  processOutbidPayment: (params: {
    targetListingId?: string;
    name: string;
    url: string;
    imageUrl: string;
    categoryId: string;
    additionalAmount?: number;
    bidAmount?: number;
    gateway: 'bkash' | 'nagad' | 'rocket' | 'sslcommerz' | 'shurjopay';
  }) => Promise<{ success: boolean; message: string; transactionId?: string; action?: string; checkoutUrl?: string }>;
  sandboxPaymentState: {
    isOpen: boolean;
    transactionId: string;
    gateway: 'bkash' | 'nagad' | 'rocket' | 'sslcommerz' | 'shurjopay';
    amount: number;
    listingName: string;
  } | null;
  closeSandboxModal: () => void;
  handleSandboxCompletion: (success: boolean, message: string, transactionId: string) => Promise<void>;

  // Admin CRUD
  adminSaveListing: (listing: Partial<Listing>) => void;
  adminDeleteListing: (id: string) => void;
  adminToggleListingStatus: (id: string) => void;
  
  adminSaveCategory: (category: Partial<Category>) => void;
  adminDeleteCategory: (id: string) => void;
  adminReorderCategories: (categories: Category[]) => void;
  adminMoveCategory: (id: string, direction: 'up' | 'down') => void;
  adminToggleCategoryStatus: (id: string) => void;
  adminSetCategoryOrder: (id: string, newOrder: number) => void;
  
  adminSaveDesign: (newDesign: DesignSettings) => void;
  adminSaveTexts: (newTexts: FrontendTexts) => void;
  adminSaveSettings: (newSettings: SiteSettings) => void;
  adminSaveDeveloper: (newDev: DeveloperProfile) => void;
  adminSaveScrollPopup: (newPopup: FloatingScrollPopup) => void;
  adminSaveGateways: (newGateways: GatewayConfig[]) => void;
  adminSaveMenuItems: (newItems: MenuItem[]) => void;
  adminSavePage: (page: ContentPage) => void;
  adminResetData: () => void;
  adminUpdateVisitorSettings: (settings: Partial<VisitorSettings>) => Promise<void>;
  adminResetVisitorStats: (type: 'active' | 'total' | 'all', customActive?: number, customTotal?: number) => Promise<void>;
  adminDeleteTransaction: (transactionId: string) => Promise<void>;
  adminClearAllTransactions: () => Promise<void>;
  adminResetListingStats: (listingId?: string, resetType?: 'clicks' | 'hearts' | 'bid' | 'all') => void;
  adminDeleteUserTransactions: (identifier: string) => Promise<void>;
}

const AppContext = createContext<AppContextType | undefined>(undefined);

export const AppProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  // Persistent storage state initializers
  const [listings, setListings] = useState<Listing[]>(() => {
    const saved = localStorage.getItem('topbd_listings');
    return saved ? JSON.parse(saved) : INITIAL_LISTINGS;
  });

  const [categories, setCategories] = useState<Category[]>(() => {
    const saved = localStorage.getItem('topbd_categories');
    return saved ? JSON.parse(saved) : INITIAL_CATEGORIES;
  });

  const [payments, setPayments] = useState<PaymentTransaction[]>(() => {
    const saved = localStorage.getItem('topbd_payments');
    return saved ? JSON.parse(saved) : INITIAL_PAYMENTS;
  });

  const [menuItems, setMenuItems] = useState<MenuItem[]>(() => {
    const saved = localStorage.getItem('topbd_menu');
    return saved ? JSON.parse(saved) : INITIAL_MENU_ITEMS;
  });

  const [settings, setSettings] = useState<SiteSettings>(() => {
    const saved = localStorage.getItem('topbd_settings');
    return saved ? JSON.parse(saved) : INITIAL_SETTINGS;
  });

  const [design, setDesign] = useState<DesignSettings>(() => {
    const saved = localStorage.getItem('topbd_design');
    return saved ? JSON.parse(saved) : INITIAL_DESIGN;
  });

  const [texts, setTexts] = useState<FrontendTexts>(() => {
    const saved = localStorage.getItem('topbd_texts');
    return saved ? JSON.parse(saved) : INITIAL_TEXTS;
  });

  const [developer, setDeveloper] = useState<DeveloperProfile>(() => {
    const saved = localStorage.getItem('topbd_developer');
    return saved ? JSON.parse(saved) : INITIAL_DEVELOPER;
  });

  const [scrollPopup, setScrollPopup] = useState<FloatingScrollPopup>(() => {
    const saved = localStorage.getItem('topbd_scroll_popup');
    return saved ? JSON.parse(saved) : INITIAL_SCROLL_POPUP;
  });

  const [gateways, setGateways] = useState<GatewayConfig[]>(() => {
    const saved = localStorage.getItem('topbd_gateways');
    if (saved) {
      try {
        const parsed: GatewayConfig[] = JSON.parse(saved);
        if (Array.isArray(parsed) && parsed.length > 0) {
          const map = new Map<string, GatewayConfig>();
          // 1. Seed initial defaults (including aamarpay)
          INITIAL_GATEWAYS.forEach(g => map.set(g.id, { ...g }));
          // 2. Overlay existing saved localStorage settings
          parsed.forEach(g => {
            if (g && g.id) {
              const existing = map.get(g.id);
              map.set(g.id, { ...(existing || {}), ...g });
            }
          });
          return Array.from(map.values());
        }
      } catch (e) {
        console.warn('Failed parsing saved gateways:', e);
      }
    }
    return INITIAL_GATEWAYS;
  });

  const [pages, setPages] = useState<ContentPage[]>(() => {
    const saved = localStorage.getItem('topbd_pages');
    return saved ? JSON.parse(saved) : INITIAL_PAGES;
  });

  const [visitorSettings, setVisitorSettings] = useState<VisitorSettings>({
    is_enabled: true,
    show_active_visitors: true,
    show_total_visitors: true,
    baseline_active: 0,
    baseline_total: 1317970,
  });

  const [language, setLanguageState] = useState<Language>(() => {
    const saved = localStorage.getItem('topbd_language');
    if (saved === 'en' || saved === 'bn') return saved;
    return 'en';
  });

  const [theme, setThemeState] = useState<Theme>(() => {
    const saved = localStorage.getItem('topbd_theme');
    if (saved === 'light' || saved === 'dark') return saved;
    return 'dark'; // Default theme is DARK as per existing design
  });

  const setTheme = (newTheme: Theme) => {
    setThemeState(newTheme);
  };

  const toggleTheme = () => {
    setThemeState(prev => (prev === 'dark' ? 'light' : 'dark'));
  };

  useEffect(() => {
    localStorage.setItem('topbd_theme', theme);
    const root = document.documentElement;
    root.classList.remove('dark', 'light');
    root.classList.add(theme);
    root.setAttribute('data-theme', theme);
  }, [theme]);

  const [translations, setTranslations] = useState<TranslationsMap>(() => {
    const saved = localStorage.getItem('topbd_translations');
    if (saved) {
      try {
        const parsed = JSON.parse(saved);
        // Merge with initial in case new keys exist
        return { ...INITIAL_TRANSLATIONS, ...parsed };
      } catch {
        return INITIAL_TRANSLATIONS;
      }
    }
    return INITIAL_TRANSLATIONS;
  });

  const [isAdminLoggedIn, setIsAdminLoggedIn] = useState<boolean>(() => {
    return sessionStorage.getItem('topbd_admin_auth') === 'true';
  });

  // Sandbox payment modal state
  const [sandboxPaymentState, setSandboxPaymentState] = useState<{
    isOpen: boolean;
    transactionId: string;
    gateway: 'bkash' | 'nagad' | 'rocket' | 'sslcommerz' | 'shurjopay' | 'aamarpay';
    amount: number;
    listingName: string;
  } | null>(null);

  const closeSandboxModal = () => {
    setSandboxPaymentState(null);
  };

  // Synchronize public gateways and handle payment callback return from URL on load
  useEffect(() => {
    // 1. Fetch live gateway configs from server
    fetch('/api/gateways/public')
      .then(res => res.json())
      .then(data => {
        if (data.success && Array.isArray(data.gateways) && data.gateways.length > 0) {
          setGateways(prev => {
            const map = new Map<string, GatewayConfig>();
            INITIAL_GATEWAYS.forEach(ig => map.set(ig.id, { ...ig }));
            prev.forEach(pg => map.set(pg.id, { ...(map.get(pg.id) || {}), ...pg }));
            data.gateways.forEach((sg: any) => {
              const cur = map.get(sg.id);
              map.set(sg.id, {
                ...(cur || sg),
                is_enabled: sg.is_enabled !== undefined ? sg.is_enabled : (cur?.is_enabled ?? true),
                mode: sg.mode || cur?.mode || 'test',
                name: sg.name || cur?.name || sg.id,
                allowed_channels: sg.allowed_channels || cur?.allowed_channels,
              });
            });
            return Array.from(map.values());
          });
          if (data.defaultGateway) {
            setSettings(prev => ({ ...prev, default_payment_gateway: data.defaultGateway }));
          }
        }
      })
      .catch(() => {
        // Fallback to local gateways
      });

    // 2. Check if user redirected back from a live payment gateway callback
    if (typeof window !== 'undefined') {
      const urlParams = new URLSearchParams(window.location.search);
      const paymentStatus = urlParams.get('payment_status');
      const txnId = urlParams.get('txn');

      if (txnId && paymentStatus) {
        // Query server to verify transaction status
        fetch(`/api/payments/status/${txnId}`)
          .then(res => res.json())
          .then(statusData => {
            if (statusData.success && statusData.transaction) {
              const txn = statusData.transaction;
              if (txn.status === 'paid') {
                activateVerifiedListing(txn);
              }
            }
          })
          .catch(() => {});

        // Clean query parameters from URL without reloading
        const cleanUrl = window.location.pathname;
        window.history.replaceState({}, document.title, cleanUrl);
      }
    }
  }, []);

  // UI state
  const [state, setState] = useState<AppState>(() => {
    const savedTotal = localStorage.getItem('topbd_total_visitors');
    return {
      timeFilter: 'all_time',
      selectedCategory: 'all',
      searchQuery: '',
      currentPage: 1,
      activeVisitors: 252,
      totalVisitors: savedTotal ? parseInt(savedTotal, 10) : 1317974,
      liveListingTarget: null,
      isOutbidModalOpen: false,
      isCategoryModalOpen: false,
      isDeveloperModalOpen: false,
      isStatsModalOpen: false,
      activeContentModal: null,
      isAdminOpen: false,
    };
  });

  // Heart support tracking session protection
  const [supportedListings, setSupportedListings] = useState<Set<string>>(new Set());

  // Fetch server-ranked listings whenever category, time filter, search, or page changes
  const fetchServerListings = useCallback(() => {
    const params = new URLSearchParams();
    if (state.selectedCategory && state.selectedCategory !== 'all') {
      params.append('category', state.selectedCategory);
    }
    if (state.timeFilter) {
      params.append('timeFilter', state.timeFilter);
    }
    if (state.searchQuery) {
      params.append('search', state.searchQuery);
    }
    params.append('page', state.currentPage.toString());
    params.append('limit', '50');

    fetch(`/api/listings?${params.toString()}`)
      .then(res => res.json())
      .then(data => {
        if (data.success && Array.isArray(data.listings) && data.listings.length > 0) {
          setListings(data.listings);
        }
      })
      .catch(() => {
        // Fallback to client-side state
      });
  }, [state.selectedCategory, state.timeFilter, state.searchQuery, state.currentPage]);

  useEffect(() => {
    fetchServerListings();
  }, [fetchServerListings]);

  // Save to LocalStorage on changes
  useEffect(() => {
    localStorage.setItem('topbd_total_visitors', state.totalVisitors.toString());
  }, [state.totalVisitors]);

  // Save to LocalStorage on changes
  useEffect(() => {
    localStorage.setItem('topbd_listings', JSON.stringify(listings));
  }, [listings]);

  useEffect(() => {
    localStorage.setItem('topbd_categories', JSON.stringify(categories));
  }, [categories]);

  useEffect(() => {
    localStorage.setItem('topbd_payments', JSON.stringify(payments));
  }, [payments]);

  useEffect(() => {
    localStorage.setItem('topbd_menu', JSON.stringify(menuItems));
  }, [menuItems]);

  useEffect(() => {
    localStorage.setItem('topbd_settings', JSON.stringify(settings));
  }, [settings]);

  useEffect(() => {
    localStorage.setItem('topbd_design', JSON.stringify(design));
    // Apply dynamic CSS variables to document root based on active theme
    const root = document.documentElement;
    root.style.setProperty('--primary-color', design.primary_color || '#006A4E');
    root.style.setProperty('--secondary-color', design.secondary_color || '#F42A41');
    root.style.setProperty('--border-radius', design.border_radius || '12px');
    root.style.setProperty('--footer-link-color', design.footer_link_color || '#E07A5F');
    root.style.setProperty('--footer-link-hover-color', design.footer_link_hover_color || '#F29479');

    if (theme === 'dark') {
      root.style.setProperty('--bg-color', design.background_color || '#0A0D0F');
      root.style.setProperty('--card-color', design.card_color || '#13181D');
      root.style.setProperty('--sub-card-bg', '#141A20');
      root.style.setProperty('--sub-card-hover', '#1C242C');
      root.style.setProperty('--input-bg', '#0A0D0F');
      root.style.setProperty('--text-color', design.text_color || '#F0F4F8');
      root.style.setProperty('--heading-color', '#FFFFFF');
      root.style.setProperty('--muted-text-color', design.muted_text_color || '#8A99A8');
      root.style.setProperty('--border-color', design.border_color || '#222A33');
      root.style.setProperty('--sub-border-color', '#1C242C');
      root.style.setProperty('--accent-color', design.accent_color || '#F59E0B');
      root.style.setProperty('--rank1-bg', design.rank1_bg || '#1C2422');
      root.style.setProperty('--rank1-border', design.rank1_border || '#EAB308');
      root.style.setProperty('--rank2-bg', design.rank2_bg || '#171E24');
      root.style.setProperty('--rank3-bg', design.rank3_bg || '#141B20');
      root.style.setProperty('--header-bg', design.header_bg || '#0A0D0FEE');
      root.style.setProperty('--footer-bg', design.footer_bg || '#07090B');
      root.style.setProperty('--footer-text-color', design.footer_text_color || '#A8A29E');
      root.style.setProperty('--modal-bg', '#13181D');
      root.style.setProperty('--modal-header-bg', '#0E1317');
      root.style.setProperty('--rank-badge-top-bg', 'rgba(69, 26, 3, 0.4)');
      root.style.setProperty('--rank-badge-top-border', 'rgba(146, 64, 14, 0.4)');
      root.style.setProperty('--rank-badge-top-text', '#D97706');
      root.style.setProperty('--banner-gradient-from', '#141B20');
      root.style.setProperty('--banner-gradient-to', '#0D1216');
    } else {
      root.style.setProperty('--bg-color', '#F8FAFC');
      root.style.setProperty('--card-color', '#FFFFFF');
      root.style.setProperty('--sub-card-bg', '#F1F5F9');
      root.style.setProperty('--sub-card-hover', '#E2E8F0');
      root.style.setProperty('--input-bg', '#FFFFFF');
      root.style.setProperty('--text-color', '#1E293B');
      root.style.setProperty('--heading-color', '#0F172A');
      root.style.setProperty('--muted-text-color', '#64748B');
      root.style.setProperty('--border-color', '#E2E8F0');
      root.style.setProperty('--sub-border-color', '#E2E8F0');
      root.style.setProperty('--accent-color', '#D97706');
      root.style.setProperty('--rank1-bg', '#FFFDF5');
      root.style.setProperty('--rank1-border', '#F59E0B');
      root.style.setProperty('--rank2-bg', '#F8FAFC');
      root.style.setProperty('--rank3-bg', '#FFFFFF');
      root.style.setProperty('--header-bg', '#FFFFFFAA');
      root.style.setProperty('--footer-bg', design.footer_bg === '#07090B' ? '#F1F5F9' : (design.footer_bg || '#F1F5F9'));
      root.style.setProperty('--footer-text-color', design.footer_text_color === '#A8A29E' ? '#78716C' : (design.footer_text_color || '#78716C'));
      root.style.setProperty('--modal-bg', '#FFFFFF');
      root.style.setProperty('--modal-header-bg', '#F8FAFC');
      root.style.setProperty('--rank-badge-top-bg', '#FEF3C7');
      root.style.setProperty('--rank-badge-top-border', '#FDE68A');
      root.style.setProperty('--rank-badge-top-text', '#B45309');
      root.style.setProperty('--banner-gradient-from', '#FFFFFF');
      root.style.setProperty('--banner-gradient-to', '#F1F5F9');
    }
  }, [design, theme]);

  // Dynamic Custom CSS Injector
  useEffect(() => {
    const customCss = design.custom_css || settings.custom_css || '';
    let styleEl = document.getElementById('topbd-custom-css') as HTMLStyleElement | null;
    if (!styleEl) {
      styleEl = document.createElement('style');
      styleEl.id = 'topbd-custom-css';
      document.head.appendChild(styleEl);
    }
    styleEl.innerHTML = customCss;
  }, [design.custom_css, settings.custom_css]);

  useEffect(() => {
    localStorage.setItem('topbd_texts', JSON.stringify(texts));
  }, [texts]);

  useEffect(() => {
    localStorage.setItem('topbd_developer', JSON.stringify(developer));
  }, [developer]);

  useEffect(() => {
    localStorage.setItem('topbd_scroll_popup', JSON.stringify(scrollPopup));
  }, [scrollPopup]);

  useEffect(() => {
    localStorage.setItem('topbd_gateways', JSON.stringify(gateways));
  }, [gateways]);

  useEffect(() => {
    localStorage.setItem('topbd_pages', JSON.stringify(pages));
  }, [pages]);

  useEffect(() => {
    localStorage.setItem('topbd_language', language);
  }, [language]);

  useEffect(() => {
    localStorage.setItem('topbd_translations', JSON.stringify(translations));
  }, [translations]);

  const setLanguage = (lang: Language) => {
    setLanguageState(lang);
  };

  // Convert English digits to Bengali digits
  const toBengaliDigits = (val: number | string): string => {
    const bengaliDigits = ['০', '১', '২', '৩', '৪', '৫', '৬', '৭', '৮', '৯'];
    return String(val).replace(/[0-9]/g, digit => bengaliDigits[parseInt(digit, 10)]);
  };

  // Translation helper: t(key, params, defaultText)
  const t = useCallback((key: string, params?: Record<string, string | number>, defaultText?: string): string => {
    const isTranslationActive = settings.translation_enabled !== false;
    const activeLang = isTranslationActive ? language : 'en';
    const entry = translations[key];
    let text = entry ? (entry[activeLang] || entry['en'] || defaultText || key) : (defaultText || key);

    if (params) {
      Object.entries(params).forEach(([paramKey, paramVal]) => {
        const formattedVal = isTranslationActive && activeLang === 'bn' && typeof paramVal === 'number'
          ? toBengaliDigits(paramVal.toLocaleString())
          : String(paramVal);
        text = text.replace(new RegExp(`\\{${paramKey}\\}`, 'g'), formattedVal);
      });
    }

    return text;
  }, [translations, language, settings.translation_enabled]);

  // Number translation helper: converts numbers / strings with numbers to Bengali digits when language === 'bn'
  const tNum = useCallback((num: number | string): string => {
    if (settings.translation_enabled !== false && language === 'bn') {
      return toBengaliDigits(typeof num === 'number' ? num.toLocaleString() : num);
    }
    return typeof num === 'number' ? num.toLocaleString() : String(num);
  }, [language, settings.translation_enabled]);

  // Category translation helper
  const tCategory = useCallback((catSlugOrId: string, fallbackName?: string): string => {
    if (settings.translation_enabled === false || language === 'en') {
      return fallbackName || catSlugOrId;
    }
    const cleanSlug = catSlugOrId.replace(/^cat_/, '').toLowerCase().replace(/[^a-z0-9]/g, '_');
    const directKey = `cat_name_${cleanSlug}`;
    if (translations[directKey] && translations[directKey].bn) {
      return translations[directKey].bn;
    }
    // Search by English category name match
    if (fallbackName) {
      const match = (Object.values(translations) as Array<{ en: string; bn: string; category?: string }>).find(
        entry => entry && entry.category === 'Categories' && entry.en && entry.en.toLowerCase() === fallbackName.toLowerCase()
      );
      if (match && match.bn) {
        return match.bn;
      }
    }
    return fallbackName || catSlugOrId;
  }, [translations, language, settings.translation_enabled]);

  // Internationalized Bid Age calculation
  const formatBidAgeI18n = useCallback((timestamp: string): string => {
    if (!timestamp) return t('time_recently', undefined, 'recently');
    const time = new Date(timestamp).getTime();
    if (isNaN(time)) return t('time_recently', undefined, 'recently');

    const diffMs = Math.max(0, Date.now() - time);
    const diffSec = Math.floor(diffMs / 1000);
    const diffMin = Math.floor(diffSec / 60);
    const diffHours = Math.floor(diffMin / 60);
    const diffDays = Math.floor(diffHours / 24);
    const diffWeeks = Math.floor(diffDays / 7);

    if (diffMin < 1) {
      return t('time_just_now', undefined, 'just now');
    }
    if (diffMin < 60) {
      return diffMin === 1
        ? t('time_minute_ago', { count: 1 }, '1 minute ago')
        : t('time_minutes_ago', { count: diffMin }, `${diffMin} minutes ago`);
    }
    if (diffHours < 24) {
      return diffHours === 1
        ? t('time_hour_ago', { count: 1 }, '1 hour ago')
        : t('time_hours_ago', { count: diffHours }, `${diffHours} hours ago`);
    }
    if (diffDays === 1) {
      return t('time_yesterday', undefined, 'yesterday');
    }
    if (diffDays < 7) {
      return t('time_days_ago', { count: diffDays }, `${diffDays} days ago`);
    }
    return diffWeeks === 1
      ? t('time_week_ago', { count: 1 }, '1 week ago')
      : t('time_weeks_ago', { count: diffWeeks }, `${diffWeeks} weeks ago`);
  }, [t]);

  // Hash listener & keyboard shortcuts for admin portal & content modals
  useEffect(() => {
    const handleHash = () => {
      const hash = window.location.hash.toLowerCase();
      if (hash === '#admin') {
        setState(prev => ({ ...prev, isAdminOpen: true }));
      } else if (hash === '#rules' || hash === '#terms' || hash === '#privacy' || hash === '#stats') {
        const modalType = hash.replace('#', '') as 'rules' | 'terms' | 'privacy' | 'stats';
        setState(prev => ({ ...prev, activeContentModal: modalType }));
      }
    };

    const handleKeyDown = (e: KeyboardEvent) => {
      if ((e.ctrlKey || e.metaKey) && e.shiftKey && (e.key === 'A' || e.key === 'a')) {
        e.preventDefault();
        setState(prev => ({ ...prev, isAdminOpen: !prev.isAdminOpen }));
      }
    };

    handleHash();
    window.addEventListener('hashchange', handleHash);
    window.addEventListener('keydown', handleKeyDown);
    return () => {
      window.removeEventListener('hashchange', handleHash);
      window.removeEventListener('keydown', handleKeyDown);
    };
  }, []);

  // Real Client Visitor Heartbeat Ping & Server Stats Synchronization
  useEffect(() => {
    let clientId = localStorage.getItem('topbd_visitor_client_id');
    if (!clientId) {
      clientId = 'client_' + Math.random().toString(36).substring(2, 11) + '_' + Date.now().toString(36);
      localStorage.setItem('topbd_visitor_client_id', clientId);
    }

    const sendPing = () => {
      fetch('/api/visitors/ping', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ clientId }),
      })
        .then(res => res.json())
        .then(data => {
          if (data.success) {
            setState(prev => ({
              ...prev,
              activeVisitors: data.activeVisitors,
              totalVisitors: data.totalVisitors,
            }));
            if (data.settings) {
              setVisitorSettings(data.settings);
            }
          }
        })
        .catch(() => {});
    };

    // Initial ping immediately
    sendPing();

    // Repeat ping every 10 seconds for real-time presence
    const interval = setInterval(sendPing, 10000);
    return () => clearInterval(interval);
  }, []);

  // Compute Ranking with Deterministic Rule:
  // 1. is_active === true
  // 2. Highest current_bid first
  // 3. Tie breaker: most recent last_bid_at
  const rankedListings = useMemo(() => {
    let list = listings.filter(item => item.is_active);

    // Apply Time Filter: if today, simulate daily bids by weighting recent items or today's bids
    if (state.timeFilter === 'today') {
      const now = new Date();
      const startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
      list = list.filter(item => {
        const itemDate = new Date(item.last_bid_at).getTime();
        return itemDate >= startOfDay || item.current_bid >= 3000;
      });
    }

    // Apply Category Filter
    if (state.selectedCategory && state.selectedCategory !== 'all') {
      list = list.filter(item => {
        const cat = categories.find(c => c.slug === state.selectedCategory || c.id === state.selectedCategory);
        return cat ? item.category_id === cat.id : true;
      });
    }

    // Apply Search Query
    if (state.searchQuery.trim()) {
      const q = state.searchQuery.toLowerCase();
      list = list.filter(item =>
        item.name.toLowerCase().includes(q) ||
        (item.category_name && item.category_name.toLowerCase().includes(q)) ||
        item.url.toLowerCase().includes(q)
      );
    }

    // Sort by Bid DESC, then last_bid_at ASC (Deterministic Rule: Higher bid first; Same bid -> Older listing first)
    const sorted = [...list].sort((a, b) => {
      if (b.current_bid !== a.current_bid) {
        return b.current_bid - a.current_bid;
      }
      return new Date(a.last_bid_at).getTime() - new Date(b.last_bid_at).getTime();
    });

    // Assign Rank 1..N
    return sorted.map((item, index) => ({
      ...item,
      rank: index + 1,
    }));
  }, [listings, state.timeFilter, state.selectedCategory, state.searchQuery, categories]);

  // Current #1 overall listing (for claim hero calculation)
  const topListing = useMemo(() => {
    const allActive = listings.filter(i => i.is_active);
    if (!allActive.length) return null;
    return [...allActive].sort((a, b) => {
      if (b.current_bid !== a.current_bid) {
        return b.current_bid - a.current_bid;
      }
      return new Date(a.last_bid_at).getTime() - new Date(b.last_bid_at).getTime();
    })[0] || null;
  }, [listings]);

  // Total Verified Revenue generated since launch
  const totalGeneratedMoney = useMemo(() => {
    return payments
      .filter(p => p.status === 'success')
      .reduce((sum, p) => sum + p.amount, 0);
  }, [payments]);

  // Pagination calculation
  const totalPages = Math.ceil(rankedListings.length / settings.pagination_size) || 1;
  const paginatedListings = useMemo(() => {
    const start = (state.currentPage - 1) * settings.pagination_size;
    return rankedListings.slice(start, start + settings.pagination_size);
  }, [rankedListings, state.currentPage, settings.pagination_size]);

  // UI Handlers
  const setTimeFilter = (filter: 'all_time' | 'today') => {
    setState(prev => ({ ...prev, timeFilter: filter, currentPage: 1 }));
  };

  const setSelectedCategory = (categoryId: string) => {
    setState(prev => ({ ...prev, selectedCategory: categoryId, currentPage: 1 }));
  };

  const setSearchQuery = (query: string) => {
    setState(prev => ({ ...prev, searchQuery: query, currentPage: 1 }));
  };

  const setCurrentPage = (page: number) => {
    setState(prev => ({ ...prev, currentPage: page }));
    window.scrollTo({ top: 320, behavior: 'smooth' });
  };

  const openOutbidModal = (targetListing?: Listing | null) => {
    setState(prev => ({
      ...prev,
      isOutbidModalOpen: true,
      liveListingTarget: targetListing || topListing,
    }));
  };

  const closeOutbidModal = () => {
    setState(prev => ({ ...prev, isOutbidModalOpen: false, liveListingTarget: null }));
  };

  const openCategoryModal = () => setState(prev => ({ ...prev, isCategoryModalOpen: true }));
  const closeCategoryModal = () => setState(prev => ({ ...prev, isCategoryModalOpen: false }));
  const openDeveloperModal = () => setState(prev => ({ ...prev, isDeveloperModalOpen: true }));
  const closeDeveloperModal = () => setState(prev => ({ ...prev, isDeveloperModalOpen: false }));
  const openContentModal = (modal: string) =>
    setState(prev => ({ ...prev, activeContentModal: modal }));
  const closeContentModal = () => setState(prev => ({ ...prev, activeContentModal: null }));
  
  const openAdmin = () => setState(prev => ({ ...prev, isAdminOpen: true }));
  const closeAdmin = () => setState(prev => ({ ...prev, isAdminOpen: false }));

  const adminLogin = (password: string) => {
    if (password === 'admin123' || password === 'topbd2026') {
      setIsAdminLoggedIn(true);
      sessionStorage.setItem('topbd_admin_auth', 'true');
      return true;
    }
    return false;
  };

  const adminLogout = () => {
    setIsAdminLoggedIn(false);
    sessionStorage.removeItem('topbd_admin_auth');
  };

  // Heart support handler (with instant optimistic update & session debouncing)
  const handleHeart = useCallback((listingId: string) => {
    if (supportedListings.has(listingId)) {
      // Toggle off
      setSupportedListings(prev => {
        const next = new Set(prev);
        next.delete(listingId);
        return next;
      });
      setListings(prev =>
        prev.map(item => item.id === listingId ? { ...item, hearts: Math.max(0, item.hearts - 1) } : item)
      );
    } else {
      // Add heart
      setSupportedListings(prev => new Set(prev).add(listingId));
      setListings(prev =>
        prev.map(item => item.id === listingId ? { ...item, hearts: item.hearts + 1 } : item)
      );
    }
  }, [supportedListings]);

  // Click tracking handler
  const handleClick = useCallback((listingId: string) => {
    setListings(prev =>
      prev.map(item => item.id === listingId ? { ...item, clicks: item.clicks + 1 } : item)
    );
  }, []);

  // Manual refresh with visual indicator
  const handleManualRefresh = () => {
    setState(prev => ({ ...prev, activeVisitors: prev.activeVisitors + Math.floor(Math.random() * 3) + 1 }));
  };

  // Activate a server-verified paid listing and record transaction
  const activateVerifiedListing = useCallback((txn: any) => {
    const nowISO = new Date().toISOString();

    // Check if listing already exists by exact listing_id (only for exact ID updates)
    const existingListing = txn.listing_id ? listings.find(l => l.id === txn.listing_id) : undefined;

    const categoryObj = categories.find(c => c.id === txn.category_id);
    const categoryName = categoryObj ? categoryObj.name : (txn.category_name || 'Other');

    const newListingId = txn.listing_id || `list_${Date.now()}_${Math.floor(1000 + Math.random() * 9000)}`;

    if (existingListing) {
      // Update existing listing's bid and URLs if provided
      setListings(prev =>
        prev.map(l =>
          l.id === existingListing.id
            ? {
                ...l,
                name: txn.listing_name || l.name,
                image_url: txn.listing_image || l.image_url,
                facebook_url: txn.facebook_url || l.facebook_url || txn.listing_url || l.url || '',
                website_url: txn.website_url || l.website_url || '',
                url: txn.listing_url || l.url,
                current_bid: Math.max(l.current_bid, Number(txn.amount)),
                category_id: txn.category_id || l.category_id,
                category_name: categoryName,
                updated_at: nowISO,
                last_bid_at: nowISO,
              }
            : l
        )
      );
    } else {
      // Create new listing
      const finalFb = txn.facebook_url || txn.listing_url || 'https://facebook.com';
      const finalWeb = txn.website_url || '';
      const newListing: Listing = {
        id: newListingId,
        name: txn.listing_name.trim(),
        image_url: txn.listing_image || 'https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?w=200&auto=format&fit=crop&q=80',
        facebook_url: finalFb,
        website_url: finalWeb,
        url: txn.listing_url || finalFb,
        category_id: txn.category_id,
        category_name: categoryName,
        current_bid: Number(txn.amount),
        clicks: 0,
        hearts: 0,
        is_active: true,
        created_at: nowISO,
        updated_at: nowISO,
        last_bid_at: nowISO,
      };

      setListings(prev => [newListing, ...prev]);
    }

    // Refresh server-ranked listings to reflect true sorted positions
    setTimeout(() => {
      fetchServerListings();
    }, 100);

    // Add or update verified payment in local history
    setPayments(prev => {
      const exists = prev.find(p => p.transaction_id === txn.transaction_id);
      if (exists) {
        return prev.map(p =>
          p.transaction_id === txn.transaction_id
            ? { ...p, status: 'paid', verified_at: nowISO, paid_at: nowISO }
            : p
        );
      }
      const paymentItem: PaymentTransaction = {
        id: txn.id || `pay_${Date.now()}`,
        transaction_id: txn.transaction_id,
        listing_id: newListingId,
        listing_name: txn.listing_name,
        facebook_url: txn.facebook_url || '',
        website_url: txn.website_url || '',
        listing_url: txn.listing_url || '',
        listing_image: txn.listing_image,
        category_id: txn.category_id,
        category_name: categoryName,
        amount: Number(txn.amount),
        currency: txn.currency || 'BDT',
        gateway: txn.gateway,
        mode: txn.mode || 'test',
        status: 'paid',
        gateway_transaction_id: txn.gateway_transaction_id || `TRX_${Date.now()}`,
        created_at: txn.created_at || nowISO,
        verified_at: nowISO,
        paid_at: nowISO,
      };
      return [paymentItem, ...prev];
    });

    // Trigger celebratory confetti effect
    try {
      confetti({
        particleCount: 90,
        spread: 80,
        origin: { y: 0.6 },
        colors: ['#006A4E', '#F42A41', '#F59E0B', '#10B981'],
      });
    } catch {
      // ignore
    }

    // Refresh server-ranked listings from API
    fetchServerListings();
  }, [categories, listings, fetchServerListings]);

  // Real Payment Verification & Outbid Execution Engine
  const processOutbidPayment = async (params: {
    targetListingId?: string;
    name: string;
    url?: string;
    facebook_url: string;
    website_url?: string;
    imageUrl: string;
    categoryId: string;
    additionalAmount?: number;
    bidAmount?: number;
    gateway: 'bkash' | 'nagad' | 'rocket' | 'sslcommerz' | 'shurjopay' | 'aamarpay' | 'uddoktapay';
    channel?: string;
  }): Promise<{ success: boolean; message: string; transactionId?: string; action?: string; checkoutUrl?: string }> => {
    const { targetListingId, name, url, facebook_url, website_url, imageUrl, categoryId, additionalAmount, bidAmount, gateway, channel } = params;

    // Determine target bid
    const target = targetListingId ? listings.find(l => l.id === targetListingId) : topListing;
    const targetBid = target ? target.current_bid : settings.initial_minimum_bid;
    const minNextBid = target ? targetBid + settings.minimum_bid_increment : settings.initial_minimum_bid;

    // Compute final bid amount
    let finalBidAmount = minNextBid;
    if (bidAmount !== undefined && Number(bidAmount) >= minNextBid) {
      finalBidAmount = Number(bidAmount);
    } else if (additionalAmount !== undefined) {
      finalBidAmount = minNextBid + (Math.max(0, Number(additionalAmount)) || 0);
    }

    const categoryObj = categories.find(c => c.id === categoryId);
    const categoryName = categoryObj ? categoryObj.name : 'Other';

    try {
      // Dispatch server-side payment initialization
      const res = await fetch('/api/payments/init', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          targetListingId,
          name: name.trim(),
          facebook_url: facebook_url.trim(),
          website_url: website_url ? website_url.trim() : '',
          url: url || facebook_url.trim(),
          imageUrl: imageUrl || 'https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?w=200&auto=format&fit=crop&q=80',
          categoryId,
          categoryName,
          amount: finalBidAmount,
          gateway,
          channel,
        }),
      });

      const data = await res.json();

      if (!data.success) {
        return {
          success: false,
          message: data.message || 'Payment initialization was rejected by server.',
        };
      }

      // If backend generated a Sandbox simulation checkout
      if (data.checkoutUrl && data.checkoutUrl.startsWith('/payment-sandbox')) {
        // Open Sandbox interactive tester modal
        setSandboxPaymentState({
          isOpen: true,
          transactionId: data.transactionId,
          gateway,
          amount: finalBidAmount,
          listingName: name.trim(),
        });

        return {
          success: true,
          message: `Sandbox payment initiated. Transaction ID: ${data.transactionId}`,
          transactionId: data.transactionId,
          action: 'sandbox_modal',
        };
      }

      // If backend returned a live hosted payment URL (e.g. bKash, SSLCommerz, Nagad hosted URL)
      if (data.checkoutUrl && (data.checkoutUrl.startsWith('http://') || data.checkoutUrl.startsWith('https://'))) {
        window.location.href = data.checkoutUrl;
        return {
          success: true,
          message: 'Redirecting to payment gateway...',
          transactionId: data.transactionId,
          action: 'redirect',
          checkoutUrl: data.checkoutUrl,
        };
      }

      return {
        success: true,
        message: 'Payment initiated.',
        transactionId: data.transactionId,
      };
    } catch (err: any) {
      return {
        success: false,
        message: err.message || 'Failed to communicate with payment backend.',
      };
    }
  };

  // Sandbox completion handler
  const handleSandboxCompletion = async (success: boolean, message: string, transactionId: string) => {
    if (!success) {
      setSandboxPaymentState(null);
      return;
    }

    try {
      // Query server to get verified transaction record
      const res = await fetch(`/api/payments/status/${transactionId}`);
      const data = await res.json();

      if (data.success && data.transaction && data.transaction.status === 'paid') {
        activateVerifiedListing(data.transaction);
        setSandboxPaymentState(null);
        closeOutbidModal();
      }
    } catch {
      setSandboxPaymentState(null);
    }
  };

  // Admin Actions
  const adminSaveListing = (listingData: Partial<Listing>) => {
    if (listingData.id && listings.some(l => l.id === listingData.id)) {
      setListings(prev =>
        prev.map(l => (l.id === listingData.id ? { ...l, ...listingData, updated_at: new Date().toISOString() } : l))
      );
    } else {
      const newId = `list_${Date.now()}`;
      const cat = categories.find(c => c.id === listingData.category_id);
      const finalFb = listingData.facebook_url || listingData.url || 'https://facebook.com';
      const finalWeb = listingData.website_url || '';
      const newListing: Listing = {
        id: newId,
        name: listingData.name || 'New Listing',
        image_url: listingData.image_url || 'https://images.unsplash.com/photo-1542838132-92c53300491e?w=200&auto=format&fit=crop&q=80',
        facebook_url: finalFb,
        website_url: finalWeb,
        url: listingData.url || finalFb,
        category_id: listingData.category_id || 'cat_biz',
        category_name: cat?.name || 'Business',
        current_bid: Number(listingData.current_bid) || 100,
        clicks: Number(listingData.clicks) || 0,
        hearts: Number(listingData.hearts) || 0,
        is_active: listingData.is_active !== undefined ? listingData.is_active : true,
        created_at: new Date().toISOString(),
        updated_at: new Date().toISOString(),
        last_bid_at: new Date().toISOString(),
      };
      setListings(prev => [newListing, ...prev]);
    }
  };

  const adminDeleteListing = (id: string) => {
    setListings(prev => prev.filter(l => l.id !== id));
  };

  const adminToggleListingStatus = (id: string) => {
    setListings(prev =>
      prev.map(l => (l.id === id ? { ...l, is_active: !l.is_active, updated_at: new Date().toISOString() } : l))
    );
  };

  const adminSaveCategory = (catData: Partial<Category>) => {
    if (catData.id && categories.some(c => c.id === catData.id)) {
      setCategories(prev => prev.map(c => (c.id === catData.id ? { ...c, ...catData } : c)));
    } else {
      const newCat: Category = {
        id: `cat_${Date.now()}`,
        name: catData.name || 'New Category',
        slug: (catData.name || 'new').toLowerCase().replace(/\s+/g, '-'),
        icon: catData.icon || 'Sparkles',
        display_order: categories.length + 1,
        is_active: true,
      };
      setCategories(prev => [...prev, newCat]);
    }
  };

  const adminDeleteCategory = (id: string) => {
    setCategories(prev => prev.filter(c => c.id !== id));
  };

  const adminToggleCategoryStatus = (id: string) => {
    setCategories(prev =>
      prev.map(c => (c.id === id ? { ...c, is_active: !c.is_active } : c))
    );
  };

  const adminReorderCategories = (newOrder: Category[]) => {
    // Automatically normalize display_orders
    const normalized = newOrder.map((cat, idx) => ({
      ...cat,
      display_order: idx + 1,
    }));
    setCategories(normalized);
  };

  const adminMoveCategory = (id: string, direction: 'up' | 'down') => {
    setCategories(prev => {
      // Keep 'all' category pinned or separated if present
      const nonAll = prev.filter(c => c.slug !== 'all').sort((a, b) => a.display_order - b.display_order);
      const allCat = prev.find(c => c.slug === 'all');

      const index = nonAll.findIndex(c => c.id === id);
      if (index === -1) return prev;

      const targetIndex = direction === 'up' ? index - 1 : index + 1;
      if (targetIndex < 0 || targetIndex >= nonAll.length) return prev;

      const updated = [...nonAll];
      const temp = updated[index];
      updated[index] = updated[targetIndex];
      updated[targetIndex] = temp;

      const reordered = updated.map((cat, idx) => ({
        ...cat,
        display_order: idx + 1,
      }));

      return allCat ? [allCat, ...reordered] : reordered;
    });
  };

  const adminSetCategoryOrder = (id: string, newOrder: number) => {
    setCategories(prev => {
      const nonAll = prev.filter(c => c.slug !== 'all').sort((a, b) => a.display_order - b.display_order);
      const allCat = prev.find(c => c.slug === 'all');

      const index = nonAll.findIndex(c => c.id === id);
      if (index === -1) return prev;

      const item = nonAll[index];
      const withoutItem = nonAll.filter(c => c.id !== id);
      const targetIndex = Math.max(0, Math.min(newOrder - 1, withoutItem.length));
      withoutItem.splice(targetIndex, 0, item);

      const reordered = withoutItem.map((cat, idx) => ({
        ...cat,
        display_order: idx + 1,
      }));

      return allCat ? [allCat, ...reordered] : reordered;
    });
  };

  const adminSaveDesign = (newDesign: DesignSettings) => setDesign(newDesign);
  const adminSaveTexts = (newTexts: FrontendTexts) => setTexts(newTexts);
  const adminSaveSettings = (newSettings: SiteSettings) => setSettings(newSettings);
  const adminSaveDeveloper = (newDev: DeveloperProfile) => setDeveloper(newDev);
  const adminSaveScrollPopup = (newPopup: FloatingScrollPopup) => setScrollPopup(newPopup);
  const adminSaveGateways = (newGateways: GatewayConfig[]) => {
    setGateways(newGateways);
    // Securely update backend server gateways & mode
    fetch('/api/admin/gateways', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        gateways: newGateways,
        defaultGateway: settings.default_payment_gateway,
      }),
    }).catch(() => {});
  };
  const adminSaveMenuItems = (newItems: MenuItem[]) => setMenuItems(newItems);
  const adminSavePage = (page: ContentPage) => {
    setPages(prev => prev.map(p => (p.id === page.id ? { ...page, updated_at: new Date().toISOString() } : p)));
  };

  const adminSaveTranslations = (newTranslations: TranslationsMap) => {
    setTranslations(newTranslations);
  };

  const adminResetTranslations = () => {
    setTranslations(INITIAL_TRANSLATIONS);
    localStorage.removeItem('topbd_translations');
  };

  const adminUpdateVisitorSettings = async (newSettings: Partial<VisitorSettings>) => {
    try {
      const res = await fetch('/api/admin/visitors/settings', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(newSettings),
      });
      const data = await res.json();
      if (data.success) {
        setState(prev => ({
          ...prev,
          activeVisitors: data.activeVisitors,
          totalVisitors: data.totalVisitors,
        }));
        if (data.settings) {
          setVisitorSettings(data.settings);
        }
      }
    } catch (e) {
      console.error('Failed to update visitor settings:', e);
    }
  };

  const adminResetVisitorStats = async (type: 'active' | 'total' | 'all', customActive?: number, customTotal?: number) => {
    try {
      const res = await fetch('/api/admin/visitors/reset', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ type, customActive, customTotal }),
      });
      const data = await res.json();
      if (data.success) {
        setState(prev => ({
          ...prev,
          activeVisitors: data.activeVisitors,
          totalVisitors: data.totalVisitors,
        }));
        if (data.settings) {
          setVisitorSettings(data.settings);
        }
      }
    } catch (e) {
      console.error('Failed to reset visitor stats:', e);
    }
  };

  const adminDeleteTransaction = async (transactionId: string) => {
    try {
      await fetch(`/api/admin/transactions/${transactionId}`, { method: 'DELETE' });
    } catch (e) {
      console.warn('Failed to delete transaction on server:', e);
    }
    const updated = payments.filter(p => p.transaction_id !== transactionId && p.id !== transactionId);
    setPayments(updated);
    localStorage.setItem('topbd_payments', JSON.stringify(updated));
  };

  const adminClearAllTransactions = async () => {
    try {
      await fetch('/api/admin/transactions/reset', { method: 'POST' });
    } catch (e) {
      console.warn('Failed to clear transactions on server:', e);
    }
    setPayments([]);
    localStorage.removeItem('topbd_payments');
  };

  const adminResetListingStats = (listingId?: string, resetType: 'clicks' | 'hearts' | 'bid' | 'all' = 'all') => {
    setListings(prev =>
      prev.map(item => {
        if (!listingId || listingId === 'all' || item.id === listingId) {
          const updated = { ...item };
          if (resetType === 'clicks' || resetType === 'all') updated.clicks = 0;
          if (resetType === 'hearts' || resetType === 'all') updated.hearts = 0;
          if (resetType === 'bid' || resetType === 'all') updated.current_bid = 100;

          fetch('/api/admin/listings/save', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(updated),
          }).catch(() => {});

          return updated;
        }
        return item;
      })
    );
  };

  const adminDeleteUserTransactions = async (identifier: string) => {
    if (!identifier) return;
    const target = identifier.trim().toLowerCase();

    const matchingTxns = payments.filter(p =>
      (p.contact_number && p.contact_number.toLowerCase().includes(target)) ||
      (p.user_email && p.user_email.toLowerCase().includes(target)) ||
      (p.transaction_id && p.transaction_id.toLowerCase().includes(target)) ||
      (p.listing_name && p.listing_name.toLowerCase().includes(target))
    );

    for (const txn of matchingTxns) {
      try {
        await fetch(`/api/admin/transactions/${txn.transaction_id || txn.id}`, { method: 'DELETE' });
      } catch (e) {}
    }

    const remaining = payments.filter(p => !matchingTxns.some(m => m.id === p.id || m.transaction_id === p.transaction_id));
    setPayments(remaining);
    localStorage.setItem('topbd_payments', JSON.stringify(remaining));
  };

  const adminResetData = () => {
    setListings(INITIAL_LISTINGS);
    setCategories(INITIAL_CATEGORIES);
    setPayments(INITIAL_PAYMENTS);
    setMenuItems(INITIAL_MENU_ITEMS);
    setSettings(INITIAL_SETTINGS);
    setDesign(INITIAL_DESIGN);
    setTexts(INITIAL_TEXTS);
    setDeveloper(INITIAL_DEVELOPER);
    setScrollPopup(INITIAL_SCROLL_POPUP);
    setGateways(INITIAL_GATEWAYS);
    setPages(INITIAL_PAGES);
    setTranslations(INITIAL_TRANSLATIONS);
    setLanguageState('en');
    localStorage.clear();
  };

  return (
    <AppContext.Provider
      value={{
        state,
        listings,
        categories,
        payments,
        menuItems,
        settings,
        design,
        texts,
        developer,
        scrollPopup,
        gateways,
        pages,
        rankedListings,
        topListing,
        totalGeneratedMoney,
        totalPages,
        paginatedListings,
        isAdminLoggedIn,
        language,
        theme,
        translations,
        visitorSettings,

        setTheme,
        toggleTheme,
        setLanguage,
        t,
        tCategory,
        tNum,
        formatBidAgeI18n,
        adminSaveTranslations,
        adminResetTranslations,

        setTimeFilter,
        setSelectedCategory,
        setSearchQuery,
        setCurrentPage,
        openOutbidModal,
        closeOutbidModal,
        openCategoryModal,
        closeCategoryModal,
        openDeveloperModal,
        closeDeveloperModal,
        openContentModal,
        closeContentModal,
        openAdmin,
        closeAdmin,
        adminLogin,
        adminLogout,

        handleHeart,
        handleClick,
        handleManualRefresh,

        processOutbidPayment,
        sandboxPaymentState,
        closeSandboxModal,
        handleSandboxCompletion,

        adminSaveListing,
        adminDeleteListing,
        adminToggleListingStatus,
        adminSaveCategory,
        adminDeleteCategory,
        adminReorderCategories,
        adminMoveCategory,
        adminToggleCategoryStatus,
        adminSetCategoryOrder,
        adminSaveDesign,
        adminSaveTexts,
        adminSaveSettings,
        adminSaveDeveloper,
        adminSaveScrollPopup,
        adminSaveGateways,
        adminSaveMenuItems,
        adminSavePage,
        adminResetData,
        adminUpdateVisitorSettings,
        adminResetVisitorStats,
        adminDeleteTransaction,
        adminClearAllTransactions,
        adminResetListingStats,
        adminDeleteUserTransactions,
      }}
    >
      {children}
    </AppContext.Provider>
  );
};

export const useApp = () => {
  const context = useContext(AppContext);
  if (!context) {
    throw new Error('useApp must be used within an AppProvider');
  }
  return context;
};
