"use client";

import React, {
  createContext,
  useContext,
  useState,
  useCallback,
  useEffect,
} from "react";
import type {
  BookingData,
  BookingContextType,
  SelectedTicket,
  QuestionAnswer,
  BasicInformation,
  ProfessionalInformation,
  PaymentInformation,
} from "@/types/booking";

const STORAGE_KEY = "bookingData";

const initialState: BookingData = {
  selectedTickets: [],
  questions: [],
  eventId: undefined,
  promoCode: undefined,
  basicInformation: undefined,
  professionalInformation: undefined,
  paymentInformation: undefined,
};

function loadFromStorage(): BookingData {
  if (typeof window === "undefined") return initialState;

  try {
    const stored = sessionStorage.getItem(STORAGE_KEY);
    if (stored) {
      const parsed = JSON.parse(stored);
      return { ...initialState, ...parsed };
    }
  } catch (error) {
    console.error("Error loading booking data from storage:", error);
  }

  return initialState;
}

function saveToStorage(data: BookingData): void {
  if (typeof window === "undefined") return;

  try {
    sessionStorage.setItem(STORAGE_KEY, JSON.stringify(data));
  } catch (error) {
    console.error("Error saving booking data to storage:", error);
  }
}

const BookingContext = createContext<BookingContextType | undefined>(undefined);

export function BookingProvider({ children }: { children: React.ReactNode }) {
  const [bookingData, setBookingData] = useState<BookingData>(initialState);
  const [isHydrated, setIsHydrated] = useState(false);

  useEffect(() => {
    const stored = loadFromStorage();
    const hasData =
      stored.selectedTickets.length > 0 ||
      stored.questions.length > 0 ||
      stored.eventId !== undefined ||
      stored.promoCode !== undefined ||
      stored.basicInformation !== undefined ||
      stored.professionalInformation !== undefined ||
      stored.paymentInformation !== undefined;

    if (hasData) {
      setBookingData(stored);
    }
    setIsHydrated(true);
  }, []);

  useEffect(() => {
    if (isHydrated) {
      saveToStorage(bookingData);
    }
  }, [bookingData, isHydrated]);

  const setSelectedTickets = useCallback((tickets: SelectedTicket[]) => {
    setBookingData((prev) => ({
      ...prev,
      selectedTickets: tickets,
    }));
  }, []);

  const setQuestions = useCallback((questions: QuestionAnswer[]) => {
    setBookingData((prev) => ({
      ...prev,
      questions: questions,
    }));
  }, []);

  const setEventId = useCallback((eventId: number) => {
    setBookingData((prev) => ({
      ...prev,
      eventId: eventId,
    }));
  }, []);

  const setPromoCode = useCallback((promoCode: string) => {
    setBookingData((prev) => ({
      ...prev,
      promoCode: promoCode.trim() || undefined,
    }));
  }, []);

  const setBasicInformation = useCallback((info: BasicInformation) => {
    setBookingData((prev) => ({
      ...prev,
      basicInformation: info,
    }));
  }, []);

  const setProfessionalInformation = useCallback(
    (info: ProfessionalInformation) => {
      setBookingData((prev) => ({
        ...prev,
        professionalInformation: info,
      }));
    },
    []
  );

  const setPaymentInformation = useCallback((info: PaymentInformation) => {
    setBookingData((prev) => ({
      ...prev,
      paymentInformation: info,
    }));
  }, []);

  const clearBookingData = useCallback(() => {
    setBookingData(initialState);
    if (typeof window !== "undefined") {
      sessionStorage.removeItem(STORAGE_KEY);
    }
  }, []);

  // Get tickets formatted for get-total price endpoint
  const getTicketsForTotalPrice = useCallback((): SelectedTicket[] => {
    return bookingData.selectedTickets.filter((ticket) => ticket.quantity > 0);
  }, [bookingData.selectedTickets]);

  // Get questions formatted for store-order endpoint
  const getQuestionsForOrder = useCallback((): QuestionAnswer[] => {
    return bookingData.questions.filter(
      (question) => question.answer.length > 0
    );
  }, [bookingData.questions]);

  const value: BookingContextType = {
    bookingData,
    setSelectedTickets,
    setQuestions,
    setEventId,
    setPromoCode,
    setBasicInformation,
    setProfessionalInformation,
    setPaymentInformation,
    clearBookingData,
    getTicketsForTotalPrice,
    getQuestionsForOrder,
  };

  return (
    <BookingContext.Provider value={value}>{children}</BookingContext.Provider>
  );
}

export function useBooking() {
  const context = useContext(BookingContext);
  if (context === undefined) {
    throw new Error("useBooking must be used within a BookingProvider");
  }
  return context;
}
