import { useState, useEffect, useCallback, useRef } from 'react';
import { useUser, useCurrentUser } from './useUsers';
import { useApiRequest } from './useApi';
import { GenericDataHook } from '../core/PageManager/pageInterface';
import type { SettingsFieldConfig } from '../core/PageManager/pageInterface';

// Interface for unified settings data
export interface SettingsData {
  // User data (from API)
  username?: string;
  fullName?: string;
  email?: string;
  language?: string;
  privilege?: string;
  enabled?: boolean;
  authenticationAuthority?: string;
  // Phone name (localStorage)
  phoneName?: string;
  // Theme (localStorage)
  theme?: string;
  // Speech data (localStorage)
  speechData?: any;
  // Nested speech fields
  mandate_general?: {
    company_name?: string;
    industry?: string;
    contact_info?: {
      email?: string;
      phone?: string;
      street?: string;
      postal_code?: string;
      city?: string;
      country?: string;
    };
    business_hours?: string;
    timezone?: string;
  };
  setup_contacts?: boolean;
}

// Create settings hook factory
export function createSettingsHook(): () => GenericDataHook {
  return function useSettings() {
    const { user: currentUser } = useCurrentUser();
    const { getUser, updateUser } = useUser();
    const { request } = useApiRequest();
    
    const [settingsData, setSettingsData] = useState<SettingsData>({});
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState<string | null>(null);
    const [settingsFields, setSettingsFields] = useState<Record<string, SettingsFieldConfig[]>>({});
    const [settingsLoading, setSettingsLoading] = useState<Record<string, boolean>>({});
    const [settingsErrors, setSettingsErrors] = useState<Record<string, string | null>>({});
    
    // Track if we've loaded data initially to prevent infinite loops
    const hasLoadedRef = useRef(false);
    const currentUserIdRef = useRef<string | undefined>(currentUser?.id);

    // Load phone name from localStorage
    const _loadPhoneName = useCallback((): string => {
      try {
        return localStorage.getItem('userPhoneName') || '';
      } catch (error) {
        console.error('Failed to load phone name from localStorage:', error);
        return '';
      }
    }, []);
    void _loadPhoneName; // Intentionally unused, reserved for future use

    // Load theme from localStorage
    const _loadTheme = useCallback((): string => {
      try {
        const savedTheme = localStorage.getItem('theme');
        if (savedTheme) {
          return savedTheme;
        }
        // Default to system preference
        return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
      } catch (error) {
        console.error('Failed to load theme from localStorage:', error);
        return 'light';
      }
    }, []);
    void _loadTheme; // Intentionally unused, reserved for future use

    // Load speech data from localStorage
    const _loadSpeechData = useCallback((): any | null => {
      try {
        const savedData = localStorage.getItem('speechSignUpData');
        const timestamp = localStorage.getItem('speechSignUpTimestamp');
        
        if (savedData && timestamp) {
          const parsedData = JSON.parse(savedData);
          const savedTime = parseInt(timestamp);
          const now = Date.now();
          const twentyFourHours = 24 * 60 * 60 * 1000;
          
          // Check if data is still valid (within 24 hours)
          if (now - savedTime < twentyFourHours) {
            return parsedData;
          } else {
            // Data expired, clear it
            localStorage.removeItem('speechSignUpData');
            localStorage.removeItem('speechSignUpTimestamp');
            return null;
          }
        }
        return null;
      } catch (error) {
        console.error('Error loading speech data:', error);
        return null;
      }
    }, []);
    void _loadSpeechData; // Intentionally unused, reserved for future use

    // Fetch user data from API
    const _fetchUserData = useCallback(async () => {
      if (!currentUser?.id) return null;
      
      try {
        const userData = await getUser(currentUser.id);
        return userData;
      } catch (error) {
        console.error('Failed to fetch user data:', error);
        throw error;
      }
    }, [currentUser?.id, getUser]);
    void _fetchUserData; // Intentionally unused, reserved for future use

    // Fetch field definitions from backend
    const _fetchFieldsForSection = useCallback(async (sectionId: string): Promise<SettingsFieldConfig[]> => {
      try {
        setSettingsLoading(prev => ({ ...prev, [sectionId]: true }));
        setSettingsErrors(prev => ({ ...prev, [sectionId]: null }));
        
        // TODO: Replace with actual backend endpoint
        // For now, return empty array - fields will come from backend later
        const response = await request({
          url: `/api/settings/fields?section=${sectionId}`,
          method: 'get'
        });
        
        const fields = response?.fields || [];
        setSettingsFields(prev => ({ ...prev, [sectionId]: fields }));
        return fields;
      } catch (error: any) {
        const errorMessage = error.message || `Failed to load fields for ${sectionId}`;
        console.error(`Error fetching fields for section ${sectionId}:`, error);
        setSettingsErrors(prev => ({ ...prev, [sectionId]: errorMessage }));
        return [];
      } finally {
        setSettingsLoading(prev => ({ ...prev, [sectionId]: false }));
      }
    }, [request]);
    void _fetchFieldsForSection; // Intentionally unused, reserved for future use

    // Load all settings data
    const loadSettingsData = useCallback(async () => {
      // Prevent multiple simultaneous loads
      if (loading && hasLoadedRef.current) return;
      
      try {
        setLoading(true);
        setError(null);

        // Load from different sources - call functions directly to avoid dependency issues
        const userData = currentUser?.id ? await getUser(currentUser.id) : null;
        const phoneName = localStorage.getItem('userPhoneName') || '';
        const savedTheme = localStorage.getItem('theme');
        const theme = savedTheme || (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
        
        // Load speech data
        let speechData: any | null = null;
        try {
          const savedData = localStorage.getItem('speechSignUpData');
          const timestamp = localStorage.getItem('speechSignUpTimestamp');
          if (savedData && timestamp) {
            const parsedData = JSON.parse(savedData);
            const savedTime = parseInt(timestamp);
            const now = Date.now();
            const twentyFourHours = 24 * 60 * 60 * 1000;
            if (now - savedTime < twentyFourHours) {
              speechData = parsedData;
            } else {
              localStorage.removeItem('speechSignUpData');
              localStorage.removeItem('speechSignUpTimestamp');
            }
          }
        } catch (error) {
          console.error('Error loading speech data:', error);
        }

        // Merge all data into unified object
        const unifiedData: SettingsData = {
          ...(userData || {}),
          phoneName,
          theme,
          speechData,
          // Flatten speech data if it exists
          ...(speechData?.mandate_general && {
            mandate_general: speechData.mandate_general
          }),
          ...(speechData?.setup_contacts !== undefined && {
            setup_contacts: speechData.setup_contacts
          })
        };

        setSettingsData(unifiedData);
        hasLoadedRef.current = true;
      } catch (error: any) {
        console.error('Error loading settings data:', error);
        setError(error.message || 'Failed to load settings');
      } finally {
        setLoading(false);
      }
    }, [currentUser?.id, getUser]); // Only depend on currentUser?.id and getUser

    // Save section data
    const saveSection = useCallback(async (sectionId: string, data: any) => {
      try {
        setSettingsLoading(prev => ({ ...prev, [sectionId]: true }));
        setSettingsErrors(prev => ({ ...prev, [sectionId]: null }));

        if (sectionId === 'user-info') {
          // Separate user API data from localStorage data
          const { phoneName, id, mandateId, ...userApiData } = data;
          
          // Build clean update object with only allowed fields (explicitly exclude id and mandateId)
          // Allowed fields: username, email, fullName, language, enabled, privilege, authenticationAuthority
          const userUpdateData: Record<string, any> = {};
          const allowedFields = ['username', 'email', 'fullName', 'language', 'enabled', 'privilege', 'authenticationAuthority'];
          
          allowedFields.forEach(field => {
            if (userApiData.hasOwnProperty(field)) {
              userUpdateData[field] = userApiData[field];
            }
          });
          
          // Save user data via API (only allowed fields, no id or mandateId)
          if (currentUser?.id && Object.keys(userUpdateData).length > 0) {
            const updatedUser = await updateUser(currentUser.id, userUpdateData);
            // Update local state with API data
            setSettingsData(prev => ({ ...prev, ...updatedUser }));
            
            // Update localStorage cache
            localStorage.setItem('currentUser', JSON.stringify(updatedUser));
            
            // Dispatch event to notify other components
            window.dispatchEvent(new CustomEvent('userInfoUpdated'));
          }
          
          // Save phone name to localStorage separately
          if (phoneName !== undefined) {
            if (phoneName?.trim()) {
              localStorage.setItem('userPhoneName', phoneName.trim());
            } else {
              localStorage.removeItem('userPhoneName');
            }
            // Update local state with phone name
            setSettingsData(prev => ({ ...prev, phoneName }));
          }
        } else if (sectionId === 'theme') {
          // Save theme to localStorage
          localStorage.setItem('theme', data.theme);
          // Apply theme immediately
          document.documentElement.setAttribute('data-theme', data.theme);
          document.documentElement.classList.remove('light-theme', 'dark-theme');
          document.documentElement.classList.add(`${data.theme}-theme`);
          // Update local state
          setSettingsData(prev => ({ ...prev, theme: data.theme }));
        } else if (sectionId === 'speech-settings') {
          // Save speech data to localStorage
          localStorage.setItem('speechSignUpData', JSON.stringify(data));
          localStorage.setItem('speechSignUpTimestamp', Date.now().toString());
          // Update local state
          setSettingsData(prev => ({ 
            ...prev, 
            speechData: data,
            ...(data.mandate_general && { mandate_general: data.mandate_general }),
            ...(data.setup_contacts !== undefined && { setup_contacts: data.setup_contacts })
          }));
          // Dispatch event to notify other components
          window.dispatchEvent(new CustomEvent('speechSignUpChanged'));
        } else if (sectionId === 'phone-name') {
          // Save phone name to localStorage
          if (data.phoneName?.trim()) {
            localStorage.setItem('userPhoneName', data.phoneName.trim());
          } else {
            localStorage.removeItem('userPhoneName');
          }
          // Update local state
          setSettingsData(prev => ({ ...prev, phoneName: data.phoneName }));
        }
      } catch (error: any) {
        const errorMessage = error.message || `Failed to save ${sectionId}`;
        console.error(`Error saving section ${sectionId}:`, error);
        setSettingsErrors(prev => ({ ...prev, [sectionId]: errorMessage }));
        throw error;
      } finally {
        setSettingsLoading(prev => ({ ...prev, [sectionId]: false }));
      }
    }, [currentUser?.id, updateUser]);

    // Initial load - only when currentUser?.id changes or on first mount
    useEffect(() => {
      // Only load if:
      // 1. We haven't loaded yet, OR
      // 2. The user ID changed
      if (!hasLoadedRef.current || currentUserIdRef.current !== currentUser?.id) {
        currentUserIdRef.current = currentUser?.id;
        
        // Load data directly to avoid dependency issues
        const loadData = async () => {
          if (loading && hasLoadedRef.current) return;
          
          try {
            setLoading(true);
            setError(null);

            // Load from different sources
            const userData = currentUser?.id ? await getUser(currentUser.id) : null;
            const phoneName = localStorage.getItem('userPhoneName') || '';
            const savedTheme = localStorage.getItem('theme');
            const theme = savedTheme || (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
            
            // Load speech data
            let speechData: any | null = null;
            try {
              const savedData = localStorage.getItem('speechSignUpData');
              const timestamp = localStorage.getItem('speechSignUpTimestamp');
              if (savedData && timestamp) {
                const parsedData = JSON.parse(savedData);
                const savedTime = parseInt(timestamp);
                const now = Date.now();
                const twentyFourHours = 24 * 60 * 60 * 1000;
                if (now - savedTime < twentyFourHours) {
                  speechData = parsedData;
                } else {
                  localStorage.removeItem('speechSignUpData');
                  localStorage.removeItem('speechSignUpTimestamp');
                }
              }
            } catch (error) {
              console.error('Error loading speech data:', error);
            }

            // Merge all data into unified object
            const unifiedData: SettingsData = {
              ...(userData || {}),
              phoneName,
              theme,
              speechData,
              ...(speechData?.mandate_general && {
                mandate_general: speechData.mandate_general
              }),
              ...(speechData?.setup_contacts !== undefined && {
                setup_contacts: speechData.setup_contacts
              })
            };

            setSettingsData(unifiedData);
            hasLoadedRef.current = true;
          } catch (error: any) {
            console.error('Error loading settings data:', error);
            setError(error.message || 'Failed to load settings');
          } finally {
            setLoading(false);
          }
        };
        
        loadData();
      }
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [currentUser?.id]); // Only depend on currentUser?.id

    return {
      data: [], // Not used for settings
      loading,
      error,
      settingsData,
      settingsFields,
      settingsLoading,
      settingsErrors,
      saveSection,
      refetch: loadSettingsData
    } as GenericDataHook;
  };
}

