import { createContext, useContext, type ReactNode } from 'react';
import type { AppSettings } from '~/lib/settings-management.server';

interface SettingsContextType {
  settings: AppSettings;
  formatNumber: (value: number) => string;
  formatCurrency: (value: number) => string;
  formatDate: (date: Date | string) => string;
  formatDateTime: (date: Date | string) => string;
}

const SettingsContext = createContext<SettingsContextType | null>(null);

interface SettingsProviderProps {
  children: ReactNode;
  settings: AppSettings;
}

export function SettingsProvider({ children, settings }: SettingsProviderProps) {
  // Helper function to convert Western numerals to Arabic numerals
  const convertToArabicNumerals = (str: string): string => {
    const arabicNumerals = ['٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩'];
    return str.replace(/[0-9]/g, (digit) => arabicNumerals[parseInt(digit)]);
  };

  // Helper function to format date with custom pattern
  const formatDateWithPattern = (date: Date, pattern: string): string => {
    const day = date.getDate();
    const month = date.getMonth() + 1;
    const year = date.getFullYear();

    // Format numbers according to locale
    const formatNumber = (num: number, padLength: number = 2): string => {
      const padded = num.toString().padStart(padLength, '0');
      return settings.numberFormat === 'ar-SA' 
        ? convertToArabicNumerals(padded)
        : padded;
    };

    return pattern
      .replace(/yyyy/g, formatNumber(year, 4))
      .replace(/yy/g, formatNumber(year % 100, 2))
      .replace(/MM/g, formatNumber(month, 2))
      .replace(/M/g, formatNumber(month, 1))
      .replace(/dd/g, formatNumber(day, 2))
      .replace(/d/g, formatNumber(day, 1));
  };

  const formatNumber = (value: number): string => {
    return value.toLocaleString(settings.numberFormat);
  };

  const formatCurrency = (value: number): string => {
    const formatted = value.toLocaleString(settings.numberFormat, {
      minimumFractionDigits: 2,
      maximumFractionDigits: 2
    });
    return `${formatted} ${settings.currencySymbol}`;
  };

  const formatDate = (date: Date | string): string => {
    const dateObj = typeof date === 'string' ? new Date(date) : date;
    return formatDateWithPattern(dateObj, settings.dateDisplayFormat);
  };

  const formatDateTime = (date: Date | string): string => {
    const dateObj = typeof date === 'string' ? new Date(date) : date;
    const datePart = formatDateWithPattern(dateObj, settings.dateDisplayFormat);
    const timePart = dateObj.toLocaleTimeString(settings.dateFormat, {
      hour: '2-digit',
      minute: '2-digit'
    });
    return `${datePart} ${timePart}`;
  };

  const contextValue: SettingsContextType = {
    settings,
    formatNumber,
    formatCurrency,
    formatDate,
    formatDateTime
  };

  return (
    <SettingsContext.Provider value={contextValue}>
      {children}
    </SettingsContext.Provider>
  );
}

export function useSettings(): SettingsContextType {
  const context = useContext(SettingsContext);
  if (!context) {
    throw new Error('useSettings must be used within a SettingsProvider');
  }
  return context;
}

// Hook for formatting utilities without requiring context
export function useFormatters(settings: AppSettings) {
  // Helper function to convert Western numerals to Arabic numerals
  const convertToArabicNumerals = (str: string): string => {
    const arabicNumerals = ['٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩'];
    return str.replace(/[0-9]/g, (digit) => arabicNumerals[parseInt(digit)]);
  };

  // Helper function to format date with custom pattern
  const formatDateWithPattern = (date: Date, pattern: string): string => {
    const day = date.getDate();
    const month = date.getMonth() + 1;
    const year = date.getFullYear();

    // Format numbers according to locale
    const formatNumber = (num: number, padLength: number = 2): string => {
      const padded = num.toString().padStart(padLength, '0');
      return settings.numberFormat === 'ar-SA' 
        ? convertToArabicNumerals(padded)
        : padded;
    };

    return pattern
      .replace(/yyyy/g, formatNumber(year, 4))
      .replace(/yy/g, formatNumber(year % 100, 2))
      .replace(/MM/g, formatNumber(month, 2))
      .replace(/M/g, formatNumber(month, 1))
      .replace(/dd/g, formatNumber(day, 2))
      .replace(/d/g, formatNumber(day, 1));
  };

  const formatNumber = (value: number): string => {
    return value.toLocaleString(settings.numberFormat);
  };

  const formatCurrency = (value: number): string => {
    const formatted = value.toLocaleString(settings.numberFormat, {
      minimumFractionDigits: 2,
      maximumFractionDigits: 2
    });
    return `${formatted} ${settings.currencySymbol}`;
  };

  const formatDate = (date: Date | string): string => {
    const dateObj = typeof date === 'string' ? new Date(date) : date;
    return formatDateWithPattern(dateObj, settings.dateDisplayFormat);
  };

  const formatDateTime = (date: Date | string): string => {
    const dateObj = typeof date === 'string' ? new Date(date) : date;
    const datePart = formatDateWithPattern(dateObj, settings.dateDisplayFormat);
    const timePart = dateObj.toLocaleTimeString(settings.dateFormat, {
      hour: '2-digit',
      minute: '2-digit'
    });
    return `${datePart} ${timePart}`;
  };

  return {
    formatNumber,
    formatCurrency,
    formatDate,
    formatDateTime
  };
}