import React, { createContext, useContext, useState, useEffect } from 'react';
import { getOptions, isPro as checkIsPro, isSetupComplete as checkSetup, getAjaxUrl, getNonce, getPublicUrl, getOsgswLicenseTrigger } from '../Helpers';

const SettingsContext = createContext();

export const SettingsProvider = ({ children }) => {
  const initialOptions = getOptions();
  const [options, setOptions] = useState(initialOptions);
  const [isProStatus] = useState(checkIsPro());
  const [isSetupCompleteStatus] = useState(checkSetup());
  const [saveChangeCount, setSaveChangeCount] = useState(0);
  const [isLoading, setIsLoading] = useState(false);
  const [syncProgress, setSyncProgress] = useState(0);
  const [isSyncing, setIsSyncing] = useState(false);
  const [syncMessage, setSyncMessage] = useState('');
  const [showNoticePopup, setShowNoticePopup] = useState(false);
  const [showDiscardPopup, setShowDiscardPopup] = useState(false);
  const [showDisableBulkEditPopup, setShowDisableBulkEditPopup] = useState(false);

  const publicUrl = getPublicUrl();

  const updateOption = (key, value) => {
    setOptions(prev => ({ ...prev, [key]: value }));
    setSaveChangeCount(prev => prev + 1);
  };

  const updateMultipleOptions = (updates) => {
    setOptions(prev => ({ ...prev, ...updates }));
    setSaveChangeCount(prev => prev + 1);
  };

  const ajaxPost = async (action, data = {}) => {
    const ajaxUrl = (window.appLocalizer?.ajax_url || getAjaxUrl()) + `?action=osgsw_${action}`;
    const res = await fetch(ajaxUrl, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ _wpnonce: getNonce(), ...data })
    });
    return res.json();
  };

  const triggerSheetSync = async (initialMsg = 'Preparing sync...') => {
    setIsSyncing(true);
    setSyncProgress(0);
    setSyncMessage(initialMsg);

    // yield to browser so the modal renders before we start the loop
    await new Promise(r => setTimeout(r, 50));

    try {
      const syncRes = await ajaxPost('sync_sheet');
      const countValue = syncRes?.data || syncRes?.message;
      const totalItems = parseInt(countValue, 10);

      if (!syncRes?.success || isNaN(totalItems) || totalItems <= 0) {
        setIsSyncing(false);
        const isFiltering = options.enable_google_sheets_filtering;
        setSyncMessage(isFiltering ? 'No orders match your filter criteria.' : 'Headers synced. No orders to sync.');
        return;
      }

      // For small order counts split into 3 chunks so the bar visibly progresses
      // without adding unnecessary extra requests. For larger counts use 1500/batch.
      const MAX_BATCH = 1500;
      const batchSize = totalItems <= MAX_BATCH
        ? Math.ceil(totalItems / 3)
        : MAX_BATCH;

      let offset = 0;
      let errorCount = 0;

      while (offset < totalItems) {
        const isLastBatch = offset + batchSize >= totalItems;
        const batchRes = await ajaxPost('sync_batch_to_sheet', { offset, batchSize, isLastBatch });

        if (batchRes?.success) {
          const synced = Math.min(offset + batchSize, totalItems);
          const progress = Math.round((synced / totalItems) * 100);
          await new Promise(r => setTimeout(r, 0));
          setSyncProgress(progress);
          setSyncMessage(`Syncing orders... ${synced} / ${totalItems}`);
          offset += batchSize;
        } else {
          errorCount++;
          if (errorCount > 5) offset += batchSize;
        }
      }

      setSyncProgress(100);
      setSyncMessage('Synced successfully!');
    } catch (err) {
      console.error('Error during sheet sync:', err);
      setSyncMessage('Unexpected error occurred during sync.');
    } finally {
      setIsSyncing(false);
      setTimeout(() => setSyncMessage(''), 4000);
    }
  };

  // Auto-sync when license is activated/deactivated and flag is set
  useEffect(() => {
    if (getOsgswLicenseTrigger()) {
      triggerSheetSync('Syncing data to Google Sheet...');
    }
  }, []);

  const saveChanges = async () => {
    setIsLoading(true);
    setSyncProgress(0);
    setSyncMessage('');
    try {
      const payloadOptions = { ...options };
      if (payloadOptions.credentials && typeof payloadOptions.credentials === 'object') {
        payloadOptions.credentials = JSON.stringify(payloadOptions.credentials);
      }
      if (!payloadOptions.spreadsheet_id) {
        delete payloadOptions.spreadsheet_id;
      }
      delete payloadOptions['1'];

      const data = await ajaxPost('update_options', { options: payloadOptions });

      if (!data || !data.success) {
        setSyncMessage('Settings save failed.');
        return;
      }

      setSaveChangeCount(0);

      // After saving, re-sync sheet to reflect column/filter changes
      await triggerSheetSync('Preparing sync...');
    } catch (err) {
      console.error('Error saving settings:', err);
      setSyncMessage('Unexpected error occurred.');
    } finally {
      setIsLoading(false);
    }
  };

  const discardChanges = () => {
    setOptions(getOptions());
    setSaveChangeCount(0);
    setShowDiscardPopup(false);
  };

  return (
    <SettingsContext.Provider
      value={{
        options,
        setOptions,
        updateOption,
        updateMultipleOptions,
        isPro: isProStatus,
        isSetupComplete: isSetupCompleteStatus,
        saveChangeCount,
        isLoading,
        isSyncing,
        syncProgress,
        syncMessage,
        showNoticePopup,
        setShowNoticePopup,
        showDiscardPopup,
        setShowDiscardPopup,
        showDisableBulkEditPopup,
        setShowDisableBulkEditPopup,
        saveChanges,
        discardChanges,
        triggerSheetSync,
        publicUrl,
        getNonce,
        getAjaxUrl,
      }}
    >
      {children}
    </SettingsContext.Provider>
  );
};

export const useSettings = () => useContext(SettingsContext);
