import { useState, useEffect, useCallback } from 'react';
import { useToast } from '@/components/ui/toast';
import { templateService, DatabaseTemplate, TemplateFeature, TemplatesByCategory } from '@/lib/template-service';
import { useAuth } from '@/contexts/auth-context';

export function useTemplates() {
  const { user, isLoading: authLoading } = useAuth();

  // Log user ID for debugging
  useEffect(() => {
    console.log('🔍 [useTemplates] Current user ID:', user?.id || 'No user ID')
    console.log('👤 [useTemplates] User object:', user)
    console.log('🔐 [useTemplates] Auth state - user exists:', !!user)
    console.log('🔐 [useTemplates] Auth state - user.id exists:', !!user?.id)
    console.log('🔐 [useTemplates] User type:', typeof user)
    console.log('🔐 [useTemplates] User keys:', user ? Object.keys(user) : 'No user object')
    console.log('🔐 [useTemplates] Auth loading:', authLoading)
    console.log('🔐 [useTemplates] Timestamp:', new Date().toISOString())
    
    // Check if we have tokens available
    const accessToken = localStorage.getItem('accessToken')
    const refreshToken = localStorage.getItem('refreshToken')
    console.log('🔐 [useTemplates] Token availability:', {
      hasAccessToken: !!accessToken,
      hasRefreshToken: !!refreshToken,
      accessTokenLength: accessToken?.length || 0,
      refreshTokenLength: refreshToken?.length || 0
    })
  }, [user, authLoading])

  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [combined, setCombined] = useState<{
    data: DatabaseTemplate[];
    count?: number;
    pagination?: { total?: number; limit?: number; offset?: number; hasMore?: boolean };
  } | null>(null);

  // Stable categories fetched once, independent of paginated data
  const [categories, setCategories] = useState<Array<{ id: string; name: string; count: number }>>([]);

  const [paginationState, setPaginationState] = useState({
    currentPage: 0,
    pageSize: 6, // Respect backend pagination: 6 items per page
    total: 0,
    hasMore: false,
    loading: false,
    searchQuery: '',
    selectedCategory: 'all',
  });

  const { show } = useToast();

  // Fetch templates with pagination, category, and search
  const fetchTemplatesWithPagination = useCallback(async (opts?: {
    page?: number;
    pageSize?: number;
    category?: string;
    search?: string;
    resetPagination?: boolean;
  }) => {
    // Don't fetch if auth is still loading
    if (authLoading) {
      console.log('[useTemplates] Auth still loading, skipping fetch')
      return;
    }

    // Check if we have authentication tokens available
    const accessToken = localStorage.getItem('accessToken')
    const refreshToken = localStorage.getItem('refreshToken')
    const hasTokens = !!(accessToken || refreshToken)
    
    console.log('[useTemplates] Token check before API call:', {
      hasAccessToken: !!accessToken,
      hasRefreshToken: !!refreshToken,
      hasAnyToken: hasTokens,
      userExists: !!user,
      userId: user?.id
    })

    // If user exists but no tokens, wait a bit for tokens to be loaded
    if (user && !hasTokens) {
      console.log('[useTemplates] User exists but no tokens found, waiting for token loading...')
      // Wait a short time for tokens to be loaded from localStorage
      await new Promise(resolve => setTimeout(resolve, 100))
      
      // Check again after waiting
      const retryAccessToken = localStorage.getItem('accessToken')
      const retryRefreshToken = localStorage.getItem('refreshToken')
      const retryHasTokens = !!(retryAccessToken || retryRefreshToken)
      
      console.log('[useTemplates] Token check after waiting:', {
        hasAccessToken: !!retryAccessToken,
        hasRefreshToken: !!retryRefreshToken,
        hasAnyToken: retryHasTokens
      })
      
      if (!retryHasTokens) {
        console.log('[useTemplates] Still no tokens after waiting, skipping authenticated request')
        return;
      }
    }

    try {
      const { page = 0, pageSize = paginationState.pageSize, category = paginationState.selectedCategory, search = paginationState.searchQuery, resetPagination = false } = opts || {};

      const offset = resetPagination ? 0 : page * pageSize;
      const limit = pageSize; // Use pageSize for limit

      setPaginationState((prev) => ({ ...prev, loading: true }));
      setError(null);
      setLoading(true);

      console.log('[useTemplates] Fetching templates with params:', { page, pageSize, category, search, offset });
      console.log('[useTemplates] User ID for API call:', user?.id);
      console.log('[useTemplates] User object:', user);
      console.log('[useTemplates] includeOthers will be:', !user?.id);

      // Only pass userId if it is a valid UUID v4; otherwise, omit and include others
      const uuidV4Regex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
      const validUserId = typeof user?.id === 'string' && uuidV4Regex.test(user.id) ? user.id : undefined;
      if (!validUserId && user?.id) {
        console.warn('[useTemplates] user.id is not a valid UUID v4; omitting userId to avoid backend filter. user.id:', user.id)
      }

      const res = await templateService.getCombinedTemplates({
        userId: validUserId,
        includeOthers: true, // always include custom templates from others + defaults
        limit: pageSize,
        offset,
        category: category === 'all' ? undefined : category,
        search: search || undefined,
      });

      console.log('[useTemplates] API call parameters:', {
        userId: user?.id,
        includeOthers: !user?.id,
        userExists: !!user,
        userType: typeof user
      });

      console.log('[useTemplates] API response received:', { 
        hasData: !!res?.data, 
        dataLength: res?.data?.length || 0, 
        count: res?.count,
        pagination: res?.pagination,
        fullResponse: res,
        templates: res?.data?.map(t => ({ id: t.id, title: t.title, type: t.type, category: t.category }))
      });

      setPaginationState((prev) => ({
        ...prev,
        currentPage: resetPagination ? 0 : page,
        pageSize,
        total: res.pagination?.total || 0,
        hasMore: res.pagination?.hasMore || false,
        loading: false,
        searchQuery: search,
        selectedCategory: category,
      }));

      setCombined(res);
      setLoading(false);

      return res;
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : 'Failed to fetch templates';
      console.error('[useTemplates] Error fetching templates:', err);
      
      // Handle authentication errors gracefully without redirecting
      if (errorMessage.includes('Authentication required') || errorMessage.includes('Access denied')) {
        setError('Please sign in to view your templates. You can still browse public templates.');
        // Don't throw the error to prevent further processing
      } else {
        setError(errorMessage);
        throw err;
      }
      
      setPaginationState((prev) => ({ ...prev, loading: false }));
      setLoading(false);
    }
  }, [paginationState.pageSize, paginationState.selectedCategory, paginationState.searchQuery, user?.id, authLoading]);

  // Load more templates for pagination
  const loadMoreTemplates = useCallback(async () => {
    if (paginationState.loading || !paginationState.hasMore) {
      console.log('[useTemplates] Skipping loadMoreTemplates:', { loading: paginationState.loading, hasMore: paginationState.hasMore });
      return;
    }

    try {
      const nextPage = paginationState.currentPage + 1;
      const res = await fetchTemplatesWithPagination({
        page: nextPage,
        pageSize: paginationState.pageSize,
        category: paginationState.selectedCategory,
        search: paginationState.searchQuery,
      });
      return res;
    } catch (err) {
      console.error('[useTemplates] Error loading more templates:', err);
      throw err;
    }
  }, [user, paginationState.loading, paginationState.hasMore, paginationState.currentPage, paginationState.pageSize, paginationState.selectedCategory, paginationState.searchQuery, fetchTemplatesWithPagination]);

  // Initial fetch on mount - wait for user to be loaded or confirmed as null
  useEffect(() => {
    if (authLoading) {
      console.log('[useTemplates] Auth still loading, waiting...')
      return;
    }
    
    console.log('[useTemplates] Initiating fetch, user:', user?.id || 'anonymous')
    
    // Determine what to fetch based on user state
    let fetchParams = {
      page: 0,
      pageSize: paginationState.pageSize,
      category: paginationState.selectedCategory,
      search: paginationState.searchQuery,
      resetPagination: true,
    };
    
    // If no user, only fetch public templates
    if (!user?.id) {
      console.log('[useTemplates] No user, fetching only public templates')
      fetchParams = {
        ...fetchParams,
        category: 'all', // Force 'all' category for public templates
        search: '',
      };
    }
    
    fetchTemplatesWithPagination(fetchParams).catch((err) => {
      console.error('[useTemplates] Fetch failed:', err)
      setLoading(false)
    });
  }, [authLoading, user?.id]); // Depend on both authLoading and user?.id

  // Fetch categories once (does not affect pagination)
  useEffect(() => {
    const loadCategories = async () => {
      try {
        const byCat: TemplatesByCategory = await templateService.getTemplatesByCategory();
        const entries = Object.entries(byCat || {});
        const total = entries.reduce((sum, [, arr]) => sum + (Array.isArray(arr) ? arr.length : 0), 0);
        const cats = [
          { id: 'all', name: 'All Templates', count: total },
          ...entries.map(([key, arr]) => ({ id: key, name: key, count: (arr || []).length })),
        ];
        setCategories(cats);
      } catch (e) {
        console.warn('[useTemplates] Failed to load categories; falling back to derived list.', e);
        setCategories([{ id: 'all', name: 'All Templates', count: combined?.pagination?.total || 0 }]);
      }
    };
    loadCategories();
  }, [combined?.pagination?.total]);

  // CRUD operations
  const createTemplate = async (templateData: Partial<DatabaseTemplate>) => {
    try {
      const newTemplate = await templateService.createTemplate(templateData);
      // Refresh templates after creation
      await fetchTemplatesWithPagination({ resetPagination: true });
      return newTemplate;
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : 'Failed to create template';
      // Emit a browser toast using the simplest possible fallback
      show({ title: 'Duplicate template', description: errorMessage, variant: 'error' });
      throw err;
    }
  };

  const updateTemplate = async (id: string, templateData: Partial<DatabaseTemplate>, isCustom: boolean = false) => {
    try {
      const updatedTemplate = await templateService.updateTemplate(id, templateData, isCustom);
      // Refresh templates after update
      await fetchTemplatesWithPagination({ resetPagination: true });
      show({
        title: 'Template updated',
        description: (templateData as Record<string, unknown>)?.title ? `Updated: ${(templateData as Record<string, unknown>).title}` : undefined,
        variant: 'success'
      });
      return updatedTemplate;
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : 'Failed to update template';
      show({ title: 'Update failed', description: errorMessage, variant: 'error' });
      throw err;
    }
  };

  const deleteTemplate = async (id: string, isCustom: boolean = false) => {
    try {
      await templateService.deleteTemplate(id, isCustom);
      // Refresh templates after deletion
      await fetchTemplatesWithPagination({ resetPagination: true });
      show({ title: 'Template deleted', variant: 'success' });
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : 'Failed to delete template';
      show({ title: 'Delete failed', description: errorMessage, variant: 'error' });
      throw err;
    }
  };

  const getTemplateFeatures = async (templateId: string): Promise<string[]> => {
    try {
      const features = await templateService.getFeaturesForTemplate(templateId);
      return features.map((feature) => feature.name);
    } catch (error) {
      console.error('[useTemplates] Error fetching template features:', error);
      return [];
    }
  };

  const fetchFeatures = async (templateId: string): Promise<TemplateFeature[]> => {
    return templateService.getFeaturesForTemplate(templateId);
  };

  const createFeature = async (templateId: string, feature: Partial<TemplateFeature>) => {
    const payload = { ...feature, template_id: templateId };
    return templateService.createFeature(payload);
  };

  const updateFeature = async (featureId: string, updates: Partial<TemplateFeature> & { isCustom?: boolean }) => {
    return templateService.updateFeature(featureId, updates);
  };

  const deleteFeature = async (featureId: string, opts?: { isCustom?: boolean }) => {
    return templateService.deleteFeature(featureId, opts);
  };

  return {
    user,
    combined,
    loading: loading || authLoading,
    error,
    paginationState,
    categories,
    fetchTemplatesWithPagination,
    loadMoreTemplates,
    createTemplate,
    updateTemplate,
    deleteTemplate,
    getTemplateFeatures,
    fetchFeatures,
    createFeature,
    updateFeature,
    deleteFeature,
  };
}