import { logger } from '@/lib/logger';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { supabase } from '@/integrations/supabase/client';
import type { Page, PageStatus, ContentBlock, PageMeta } from '@/types/cms';
import { useToast } from '@/hooks/use-toast';
import { useAuth } from './useAuth';
import type { Json } from '@/integrations/supabase/types';
import { webhookEvents } from '@/lib/webhook-utils';

// Helper to safely cast database JSON to our types
function parsePage(data: {
  id: string;
  slug: string;
  title: string;
  status: string;
  content_json: Json;
  meta_json: Json;
  created_by: string | null;
  updated_by: string | null;
  created_at: string;
  updated_at: string;
  scheduled_at?: string | null;
  deleted_at?: string | null;
  deleted_by?: string | null;
  show_in_menu?: boolean;
  menu_order?: number;
}): Page {
  return {
    ...data,
    status: data.status as PageStatus,
    content_json: (data.content_json || []) as unknown as ContentBlock[],
    meta_json: (data.meta_json || {}) as unknown as PageMeta,
    scheduled_at: data.scheduled_at ?? null,
    deleted_at: data.deleted_at ?? null,
    deleted_by: data.deleted_by ?? null,
    show_in_menu: data.show_in_menu ?? false,
    menu_order: data.menu_order ?? 999,
  };
}

export function usePages(status?: PageStatus) {
  const { loading: authLoading, session } = useAuth();
  
  return useQuery({
    queryKey: ['pages', status, session?.user?.id ?? 'anon'],
    queryFn: async () => {
      let query = supabase
        .from('pages')
        .select('*')
        .is('deleted_at', null)
        .order('updated_at', { ascending: false });
      
      if (status) {
        query = query.eq('status', status);
      }
      
      const { data, error } = await query;
      
      if (error) throw error;
      
      return (data || []).map(parsePage);
    },
    // Don't fetch until auth session is resolved
    enabled: !authLoading,
  });
}

export function usePage(id: string | undefined) {
  const { loading: authLoading, session } = useAuth();
  
  return useQuery({
    queryKey: ['page', id, session?.user?.id ?? 'anon'],
    queryFn: async () => {
      if (!id) return null;
      
      const { data, error } = await supabase
        .from('pages')
        .select('*')
        .eq('id', id)
        .maybeSingle();
      
      if (error) throw error;
      if (!data) return null;
      
      return parsePage(data);
    },
    enabled: !!id && !authLoading,
    refetchOnMount: 'always',
    staleTime: 0,
  });
}

export function useCreatePage() {
  const queryClient = useQueryClient();
  const { toast } = useToast();
  const { user } = useAuth();
  
  return useMutation({
    mutationFn: async ({ 
      title, 
      slug,
      content,
      meta,
      menu_order,
      show_in_menu,
      status
    }: { 
      title: string; 
      slug: string;
      content?: ContentBlock[];
      meta?: Partial<PageMeta>;
      menu_order?: number;
      show_in_menu?: boolean;
      status?: PageStatus;
    }) => {
      const { data, error } = await supabase
        .from('pages')
        .insert({
          title,
          slug,
          status: status || ('draft' as PageStatus),
          content_json: (content || []) as unknown as Json,
          meta_json: (meta || {}) as unknown as Json,
          created_by: user?.id,
          updated_by: user?.id,
          ...(menu_order !== undefined && { menu_order }),
          ...(show_in_menu !== undefined && { show_in_menu }),
        })
        .select()
        .single();
      
      if (error) throw error;
      
      // Create audit log
      await supabase.from('audit_logs').insert({
        action: 'create_page',
        entity_type: 'page',
        entity_id: data.id,
        user_id: user?.id,
        metadata: { title, slug } as unknown as Json,
      });
      
      return parsePage(data);
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['pages'] });
      toast({
        title: 'Page created',
        description: 'A new page has been created.',
      });
    },
    onError: (error: Error) => {
      toast({
        title: 'Error',
        description: error.message,
        variant: 'destructive',
      });
    },
  });
}

export function useUpdatePage() {
  const queryClient = useQueryClient();
  const { toast } = useToast();
  const { user } = useAuth();
  
  return useMutation({
    mutationFn: async ({ 
      id, 
      title, 
      content_json, 
      meta_json 
    }: { 
      id: string; 
      title?: string;
      content_json?: ContentBlock[];
      meta_json?: PageMeta;
    }) => {
      const updates: Record<string, unknown> = {
        updated_by: user?.id,
      };
      
      if (title !== undefined) updates.title = title;
      if (content_json !== undefined) updates.content_json = content_json as unknown as Json;
      if (meta_json !== undefined) updates.meta_json = meta_json as unknown as Json;
      
      const { data, error } = await supabase
        .from('pages')
        .update(updates)
        .eq('id', id)
        .select();
      
      if (error) throw error;
      if (!data || data.length === 0) throw new Error('Page not found or access denied');
      
      const row = data[0];
      
      if (error) throw error;
      
      // Create audit log for page update
      await supabase.from('audit_logs').insert({
        action: 'update_page',
        entity_type: 'page',
        entity_id: id,
        user_id: user?.id,
        metadata: { 
          updated_fields: Object.keys(updates).filter(k => k !== 'updated_by'),
        } as unknown as Json,
      });
      
      // Trigger webhook for page updated (only if page is published)
      if (row.status === 'published') {
        webhookEvents.pageUpdated({ id, slug: row.slug, title: row.title });
      }
      
      return parsePage(row);
    },
    onSuccess: (data) => {
      queryClient.invalidateQueries({ queryKey: ['pages'] });
      queryClient.setQueryData(['page', data.id], data);
    },
    onError: (error: Error) => {
      toast({
        title: 'Error saving',
        description: error.message,
        variant: 'destructive',
      });
    },
  });
}

export function useUpdatePageStatus() {
  const queryClient = useQueryClient();
  const { toast } = useToast();
  const { user } = useAuth();
  
  return useMutation({
    mutationFn: async ({ 
      id, 
      status,
      feedback,
      scheduledAt
    }: { 
      id: string; 
      status: PageStatus;
      feedback?: string;
      scheduledAt?: Date | null;
    }) => {
      const updates: Record<string, unknown> = {
        status,
        updated_by: user?.id,
      };
      
      // Handle scheduling
      if (scheduledAt !== undefined) {
        updates.scheduled_at = scheduledAt ? scheduledAt.toISOString() : null;
      }
      
      const { data, error } = await supabase
        .from('pages')
        .update(updates)
        .eq('id', id)
        .select()
        .single();
      
      if (error) throw error;
      
      // Create audit log
      await supabase.from('audit_logs').insert({
        action: `status_change_${status}`,
        entity_type: 'page',
        entity_id: id,
        user_id: user?.id,
        metadata: { 
          new_status: status,
          feedback: feedback || null,
        } as unknown as Json,
      });
      
      // If publishing, create a version snapshot
      if (status === 'published' && data) {
        await supabase.from('page_versions').insert({
          page_id: id,
          title: data.title,
          content_json: data.content_json,
          meta_json: data.meta_json,
          created_by: user?.id,
        });

        // Log cache invalidation (RPC instead of edge function)
        try {
          await supabase.rpc('log_cache_invalidation', { p_slug: data.slug, p_all: false });
          logger.log(`[usePages] Cache invalidated for: ${data.slug}`);
        } catch (cacheError) {
          logger.warn('[usePages] Cache invalidation failed:', cacheError);
        }
        
        // Trigger webhook for page published
        webhookEvents.pagePublished({ id, slug: data.slug, title: data.title });
      }
      
      return parsePage(data);
    },
    onSuccess: (data, variables) => {
      queryClient.invalidateQueries({ queryKey: ['pages'] });
      queryClient.invalidateQueries({ queryKey: ['page', data.id] });
      
      const messages: Record<PageStatus, string> = {
        draft: 'Page has been returned to draft.',
        reviewing: 'Page has been sent for review.',
        published: 'Page has been published!',
        archived: 'Page has been archived.',
      };
      
      toast({
        title: 'Status updated',
        description: messages[variables.status],
      });
    },
    onError: (error: Error) => {
      toast({
        title: 'Error',
        description: error.message,
        variant: 'destructive',
      });
    },
  });
}

export function useDeletePage() {
  const queryClient = useQueryClient();
  const { toast } = useToast();
  const { user } = useAuth();
  
  return useMutation({
    mutationFn: async (id: string) => {
      const { error } = await supabase
        .from('pages')
        .update({ deleted_at: new Date().toISOString(), deleted_by: user?.id })
        .eq('id', id);
      
      if (error) throw error;
      
      // Create audit log
      await supabase.from('audit_logs').insert({
        action: 'delete_page',
        entity_type: 'page',
        entity_id: id,
        user_id: user?.id,
        metadata: {} as unknown as Json,
      });
      
      // Trigger webhook for page deleted
      webhookEvents.pageDeleted(id);
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['pages'] });
      queryClient.invalidateQueries({ queryKey: ['deleted-pages'] });
      toast({
        title: 'Page moved to trash',
        description: 'You can restore it from the trash.',
      });
    },
    onError: (error: Error) => {
      toast({
        title: 'Error',
        description: error.message,
        variant: 'destructive',
      });
    },
  });
}

export function useDeletedPages() {
  const { loading: authLoading, session } = useAuth();
  
  return useQuery({
    queryKey: ['deleted-pages', session?.user?.id ?? 'anon'],
    queryFn: async () => {
      const { data, error } = await supabase
        .from('pages')
        .select('*')
        .not('deleted_at', 'is', null)
        .order('deleted_at', { ascending: false });
      
      if (error) throw error;
      
      return (data || []).map(parsePage);
    },
    enabled: !authLoading && !!session,
  });
}

export function useRestorePage() {
  const queryClient = useQueryClient();
  const { toast } = useToast();
  const { user } = useAuth();
  
  return useMutation({
    mutationFn: async (id: string) => {
      const { error } = await supabase
        .from('pages')
        .update({ deleted_at: null, deleted_by: null })
        .eq('id', id);
      
      if (error) throw error;
      
      await supabase.from('audit_logs').insert({
        action: 'restore_page',
        entity_type: 'page',
        entity_id: id,
        user_id: user?.id,
        metadata: {} as unknown as Json,
      });
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['pages'] });
      queryClient.invalidateQueries({ queryKey: ['deleted-pages'] });
      toast({
        title: 'Page restored',
        description: 'The page has been restored from trash.',
      });
    },
    onError: (error: Error) => {
      toast({
        title: 'Error',
        description: error.message,
        variant: 'destructive',
      });
    },
  });
}

export function usePermanentDeletePage() {
  const queryClient = useQueryClient();
  const { toast } = useToast();
  const { user } = useAuth();
  
  return useMutation({
    mutationFn: async (id: string) => {
      const { error } = await supabase
        .from('pages')
        .delete()
        .eq('id', id);
      
      if (error) throw error;
      
      await supabase.from('audit_logs').insert({
        action: 'permanent_delete_page',
        entity_type: 'page',
        entity_id: id,
        user_id: user?.id,
        metadata: {} as unknown as Json,
      });
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['deleted-pages'] });
      toast({
        title: 'Page permanently deleted',
        description: 'This action cannot be undone.',
      });
    },
    onError: (error: Error) => {
      toast({
        title: 'Error',
        description: error.message,
        variant: 'destructive',
      });
    },
  });
}

export function usePageVersions(pageId: string | undefined) {
  const { loading: authLoading, session } = useAuth();
  
  return useQuery({
    queryKey: ['page-versions', pageId, session?.user?.id ?? 'anon'],
    queryFn: async () => {
      if (!pageId) return [];
      
      const { data, error } = await supabase
        .from('page_versions')
        .select('*')
        .eq('page_id', pageId)
        .order('created_at', { ascending: false })
        .limit(5);
      
      if (error) throw error;
      
      return data;
    },
    enabled: !!pageId && !authLoading,
  });
}
