import { supabase } from "@/integrations/supabase/client";
import { StepValidationStatus, TripStep } from "@/types";
import {
  mapTripStepFromDB,
  mapTripStepToInsert,
  mapTripStepToUpdate,
} from "@/utils/tripStepMappers";
import { assertStepMutation } from "@/services/itineraryGuards";
import { isManagedDocumentStoragePath } from "@/services/documentGuards";
import { deleteParentWithDocumentsSafely } from "@/services/documentDeletionService";

export function useSupabaseTripSteps() {
  const addTripStep = async (
    tripId: string,
    stepData: Omit<TripStep, "id" | "comments" | "tripId">
  ): Promise<TripStep | null> => {
    const payload = mapTripStepToInsert(tripId, stepData);
      const { data: newStep, error } = await supabase
        .from("trip_steps")
        .insert(payload)
        .select("*, comments!comments_step_id_fkey(*)")
        .single();

      if (error) throw error;

    return mapTripStepFromDB(newStep);
  };

  const updateTripStep = async (
    tripId: string,
    stepId: string,
    stepData: Partial<TripStep>
  ): Promise<TripStep | null> => {
    const dbStepData = mapTripStepToUpdate(stepData);

      const { data: updatedStep, error } = await supabase
        .from("trip_steps")
        .update(dbStepData)
        .eq("id", stepId)
        .eq("trip_id", tripId)
        .select("*, comments!comments_step_id_fkey(*)")
        .maybeSingle();

      if (error) throw error;
    return mapTripStepFromDB(assertStepMutation(updatedStep, "modification"));
  };

  const deleteTripStep = async (tripId: string, stepId: string): Promise<boolean> => {
    const deleted = await deleteParentWithDocumentsSafely({
      loadTarget: async () => {
        const { data: target, error: targetError } = await supabase
          .from("trip_steps").select("id, trip_id").eq("id", stepId).eq("trip_id", tripId).maybeSingle();
        if (targetError) throw targetError;
        const step = assertStepMutation(target, "suppression");
        const { data: documents, error: documentsError } = await supabase
          .from("documents").select("url").eq("trip_id", tripId).eq("step_id", stepId);
        if (documentsError) throw documentsError;
        const storagePaths = (documents || [])
          .map((document) => document.url)
          .filter((path) => isManagedDocumentStoragePath(tripId, path));
        return { target: step, storagePaths };
      },
      deleteStorageFiles: async (paths) => {
        const { error } = await supabase.storage.from("documents").remove(paths);
        if (error) throw error;
      },
      deleteParentRow: async () => {
        const { data: deletedStep, error } = await supabase
        .from("trip_steps")
        .delete()
        .eq("id", stepId)
        .eq("trip_id", tripId)
        .select("id, trip_id")
        .maybeSingle();

        if (error) throw error;
        assertStepMutation(deletedStep, "suppression");
      },
      reload: async () => { await supabase.from("trip_steps").select("id").eq("trip_id", tripId); },
    });
    return deleted.id === stepId && deleted.trip_id === tripId;
  };

  const validateTripStep = async (
    tripId: string,
    stepId: string,
    status: Exclude<StepValidationStatus, "pending">
  ): Promise<{ travelerId: string; status: Exclude<StepValidationStatus, "pending"> } | null> => {
      const { data: { user }, error: userError } = await supabase.auth.getUser();
      if (userError || !user) throw userError || new Error("Authentification requise");
      const { data: visibleStep, error: stepError } = await supabase
        .from("trip_steps").select("id").eq("id", stepId).eq("trip_id", tripId)
        .eq("is_published", true).maybeSingle();
      if (stepError) throw stepError;
      if (!visibleStep) throw new Error("Étape introuvable ou validation non autorisée");
      const { data: validatedStep, error } = await supabase
        .from("step_validations")
        .upsert({ step_id: stepId, traveler_id: user.id, status }, { onConflict: "step_id,traveler_id" })
        .select("step_id, traveler_id, status")
        .maybeSingle();

      if (error) throw error;
      if (!validatedStep) throw new Error("Validation introuvable ou non autorisée");
      const persisted = validatedStep.step_id === stepId
        && validatedStep.traveler_id === user.id
        && validatedStep.status === status;
      return persisted ? { travelerId: validatedStep.traveler_id, status } : null;
  };

  const publishTripStep = async (
    tripId: string,
    stepId: string,
    isPublished: boolean
  ): Promise<boolean> => {
      const { data: publishedStep, error } = await supabase
        .from("trip_steps")
        .update({ is_published: isPublished })
        .eq("id", stepId)
        .eq("trip_id", tripId)
        .select("id, trip_id, is_published")
        .maybeSingle();

      if (error) throw error;
      const persisted = assertStepMutation(publishedStep, "publication");
      return persisted.id === stepId
        && publishedStep.trip_id === tripId
        && publishedStep.is_published === isPublished;
  };

  return {
    addTripStep,
    updateTripStep,
    deleteTripStep,
    validateTripStep,
    publishTripStep,
  };
}
