import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { supabase } from '@/integrations/supabase/client';
import { Tables } from '@/integrations/supabase/types';
import { toast } from 'sonner';

export type Contact = Tables<'contacts'>;
export type Tag = Tables<'tags'>;
export type CustomField = Tables<'custom_fields'>;
export type ContactCustomValue = Tables<'contact_custom_values'>;
export type PipelineStage = Tables<'pipeline_stages'>;
export type Pipeline = Tables<'pipelines'>;

export interface ContactWithDetails extends Contact {
  tags: Tag[];
  pipeline?: Pipeline | null;
  stage?: PipelineStage | null;
}

export function useContact(contactId: string) {
  const queryClient = useQueryClient();

  const contactQuery = useQuery({
    queryKey: ['contact', contactId],
    queryFn: async () => {
      // Fetch contact
      const { data: contact, error } = await supabase
        .from('contacts')
        .select('*')
        .eq('id', contactId)
        .maybeSingle();

      if (error) throw error;
      if (!contact) return null;

      // Fetch tags for this contact
      const { data: contactTags, error: tagsError } = await supabase
        .from('contact_tags')
        .select('tag_id, tags(*)')
        .eq('contact_id', contactId);

      if (tagsError) throw tagsError;

      // Fetch pipeline and stage if set
      let pipeline: Pipeline | null = null;
      let stage: PipelineStage | null = null;

      if (contact.pipeline_id) {
        const { data: pipelineData } = await supabase
          .from('pipelines')
          .select('*')
          .eq('id', contact.pipeline_id)
          .maybeSingle();
        pipeline = pipelineData;
      }

      if (contact.stage_id) {
        const { data: stageData } = await supabase
          .from('pipeline_stages')
          .select('*')
          .eq('id', contact.stage_id)
          .maybeSingle();
        stage = stageData;
      }

      const contactWithDetails: ContactWithDetails = {
        ...contact,
        tags: contactTags
          .map((ct) => ct.tags)
          .filter(Boolean) as Tag[],
        pipeline,
        stage,
      };

      return contactWithDetails;
    },
    enabled: !!contactId,
  });

  const updateContactMutation = useMutation({
    mutationFn: async (updates: Partial<Contact>) => {
      const { data, error } = await supabase
        .from('contacts')
        .update(updates)
        .eq('id', contactId)
        .select()
        .single();

      if (error) throw error;
      return data;
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['contact', contactId] });
      queryClient.invalidateQueries({ queryKey: ['contacts'] });
      toast.success('Contact updated successfully');
    },
    onError: (error) => {
      toast.error('Failed to update contact: ' + error.message);
    },
  });

  const deleteContactMutation = useMutation({
    mutationFn: async () => {
      const { error } = await supabase.from('contacts').delete().eq('id', contactId);
      if (error) throw error;
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['contacts'] });
      toast.success('Contact deleted successfully');
    },
    onError: (error) => {
      toast.error('Failed to delete contact: ' + error.message);
    },
  });

  return {
    contact: contactQuery.data,
    isLoading: contactQuery.isLoading,
    error: contactQuery.error,
    updateContact: updateContactMutation.mutateAsync,
    deleteContact: deleteContactMutation.mutateAsync,
    isUpdating: updateContactMutation.isPending,
    isDeleting: deleteContactMutation.isPending,
  };
}

export function useCustomFields() {
  return useQuery({
    queryKey: ['custom-fields'],
    queryFn: async () => {
      const { data, error } = await supabase
        .from('custom_fields')
        .select('*')
        .eq('entity_type', 'contact')
        .eq('is_active', true)
        .order('sort_order');

      if (error) throw error;
      return data;
    },
  });
}

export function useContactCustomValues(contactId: string) {
  const queryClient = useQueryClient();

  const valuesQuery = useQuery({
    queryKey: ['contact-custom-values', contactId],
    queryFn: async () => {
      const { data, error } = await supabase
        .from('contact_custom_values')
        .select('*')
        .eq('contact_id', contactId);

      if (error) throw error;
      return data;
    },
    enabled: !!contactId,
  });

  const updateValueMutation = useMutation({
    mutationFn: async ({ customFieldId, value }: { customFieldId: string; value: string | null }) => {
      // Check if value already exists
      const { data: existing } = await supabase
        .from('contact_custom_values')
        .select('id')
        .eq('contact_id', contactId)
        .eq('custom_field_id', customFieldId)
        .maybeSingle();

      if (existing) {
        // Update existing
        const { error } = await supabase
          .from('contact_custom_values')
          .update({ value, updated_at: new Date().toISOString() })
          .eq('id', existing.id);
        if (error) throw error;
      } else {
        // Insert new
        const { error } = await supabase
          .from('contact_custom_values')
          .insert({
            contact_id: contactId,
            custom_field_id: customFieldId,
            value,
          });
        if (error) throw error;
      }
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['contact-custom-values', contactId] });
    },
  });

  const saveAllValuesMutation = useMutation({
    mutationFn: async (values: Record<string, string | null>) => {
      for (const [customFieldId, value] of Object.entries(values)) {
        await updateValueMutation.mutateAsync({ customFieldId, value });
      }
    },
    onSuccess: () => {
      toast.success('Custom fields saved successfully');
    },
    onError: (error) => {
      toast.error('Failed to save custom fields: ' + error.message);
    },
  });

  return {
    values: valuesQuery.data ?? [],
    isLoading: valuesQuery.isLoading,
    saveValues: saveAllValuesMutation.mutateAsync,
    isSaving: saveAllValuesMutation.isPending,
  };
}

export function usePipelineStages(pipelineId?: string | null) {
  return useQuery({
    queryKey: ['pipeline-stages', pipelineId],
    queryFn: async () => {
      if (!pipelineId) return [];
      const { data, error } = await supabase
        .from('pipeline_stages')
        .select('*')
        .eq('pipeline_id', pipelineId)
        .order('order_index');

      if (error) throw error;
      return data;
    },
    enabled: !!pipelineId,
  });
}

export function usePipelines() {
  return useQuery({
    queryKey: ['pipelines'],
    queryFn: async () => {
      const { data, error } = await supabase
        .from('pipelines')
        .select('*')
        .order('name');

      if (error) throw error;
      return data;
    },
  });
}
