import { supabase } from "@/integrations/supabase/client";
import { Trip, UserRole } from "@/types";
import { transformTripFromDB } from "@/utils/tripDataTransformers";
import { TablesInsert, TablesUpdate } from "@/integrations/supabase/types";
import { useCallback } from "react";
import { hasValidTripDates, requireMutationResult } from "@/services/tripCrudGuards";
import { isManagedDocumentStoragePath } from "@/services/documentGuards";
import { deleteParentWithDocumentsSafely } from "@/services/documentDeletionService";

type TripInsert = TablesInsert<"trips">;
type TripUpdate = TablesUpdate<"trips">;

export function useSupabaseTrips() {
  const fetchUserTrips = useCallback(async (userId: string, userRole: UserRole) => {
      const relations = userRole === "planner" ? `
          *,
          trip_steps(*,comments!comments_step_id_fkey(*),step_validations(*)),
          documents(*),
          invitations(email,status,created_at),
          trip_members(user_id,status,source,joined_at,profiles!trip_members_user_id_fkey(id,name,email,role))
        ` : `
          *,
          trip_steps(*,comments!comments_step_id_fkey(*),step_validations(*)),
          documents(*),
          invitations(email,status,created_at),
          trip_members!inner(user_id,status,source,joined_at,profiles!trip_members_user_id_fkey(id,name,email,role))
        `;
      let query = supabase.from("trips").select(relations);
      query = userRole === "planner" ? query.eq("planner_id", userId) : query.eq("trip_members.user_id", userId);
      const { data: trips, error } = await query
        .order("created_at", { ascending: false });

      if (error) throw error;
      if (!trips) return [];
      return trips.map((trip) => transformTripFromDB(trip, userRole));
  }, []);

  const createTrip = async (tripData: Omit<Trip, "id" | "steps" | "documents">) => {
      if (
        !tripData.title ||
        !tripData.destination ||
        !tripData.startDate ||
        !tripData.endDate
      ) {
        throw new Error("Tous les champs obligatoires doivent être remplis");
      }
      if (!hasValidTripDates(tripData.startDate, tripData.endDate)) {
        throw new Error("La date de fin doit être postérieure ou égale à la date de début");
      }

      const payload = {
        title: tripData.title,
        destination: tripData.destination,
        start_date: tripData.startDate,
        end_date: tripData.endDate,
        traveler_name: tripData.travelerName ?? "",
        traveler_email: tripData.travelerEmail || null,
        cover_url: tripData.coverUrl ?? null,
      } as TripInsert;

      const { data: newTrip, error } = await supabase
        .from("trips")
        .insert(payload)
        .select("*")
        .single();

      if (error) throw error;
      return transformTripFromDB(newTrip, "planner");
  };

  const updateTrip = async (tripId: string, tripData: Partial<Trip>) => {
      const payload: TripUpdate = {};
      if (tripData.title !== undefined) payload.title = tripData.title;
      if (tripData.destination !== undefined) payload.destination = tripData.destination;
      if (tripData.startDate !== undefined) payload.start_date = tripData.startDate;
      if (tripData.endDate !== undefined) payload.end_date = tripData.endDate;
      if (tripData.travelerName !== undefined) payload.traveler_name = tripData.travelerName;
      if (tripData.travelerEmail !== undefined)
        payload.traveler_email = tripData.travelerEmail ?? null;
      if (tripData.coverUrl !== undefined) payload.cover_url = tripData.coverUrl ?? null;
      const startDate = tripData.startDate;
      const endDate = tripData.endDate;
      if (startDate && endDate && endDate < startDate) {
        throw new Error("La date de fin doit être postérieure ou égale à la date de début");
      }

      const { data: updatedTrip, error } = await supabase
        .from("trips")
        .update(payload)
        .eq("id", tripId)
        .select("*")
        .maybeSingle();

      if (error) throw error;
      return transformTripFromDB(requireMutationResult(updatedTrip, "modification"), "planner");
  };

  const deleteTrip = async (tripId: string) => {
    await deleteParentWithDocumentsSafely({
      loadTarget: async () => {
        const { data: target, error: targetError } = await supabase
        .from("trips")
        .select("id, cover_url, documents(url)")
        .eq("id", tripId)
        .maybeSingle();
        if (targetError) throw targetError;
        if (!target) throw new Error("Voyage introuvable ou suppression non autorisée");

        const documentPaths = (target.documents || [])
          .map((document) => document.url)
          .filter((path) => isManagedDocumentStoragePath(tripId, path));
        return { target, storagePaths: documentPaths };
      },
      deleteStorageFiles: async (paths) => {
        const { error } = await supabase.storage.from("documents").remove(paths);
        if (error) throw error;
      },
      deleteParentRow: async (target) => {

        const coverMarker = "/storage/v1/object/public/covers/";
        if (target.cover_url?.includes(coverMarker)) {
          const coverPath = decodeURIComponent(target.cover_url.split(coverMarker)[1]);
          const { error: coverError } = await supabase.storage.from("covers").remove([coverPath]);
          if (coverError) throw coverError;
        }

      const { data, error } = await supabase
        .from("trips")
        .delete()
        .eq("id", tripId)
        .select("id")
        .maybeSingle();
        if (error) throw error;
        requireMutationResult(data, "suppression");
      },
      reload: async () => { await supabase.from("trips").select("id").eq("id", tripId); },
    });
    return true;
  };

  return { fetchUserTrips, createTrip, updateTrip, deleteTrip };
}
