"use client";

import { createContext, useContext, useState, useCallback } from "react";

const PropertyContext = createContext();

export const useProperties = () => {
  const context = useContext(PropertyContext);
  if (!context) {
    throw new Error("useProperties must be used within PropertyProvider");
  }
  return context;
};

export const PropertyProvider = ({ children }) => {
  const [properties, setProperties] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const addProperty = useCallback(async (propertyData) => {
    setLoading(true);
    try {
      await new Promise((resolve) => setTimeout(resolve, 500));

      const newProperty = {
        id: Date.now().toString(),
        ...propertyData,
        createdAt: new Date().toISOString(),
        updatedAt: new Date().toISOString(),
        bookings: [],
        status: propertyData.status || "available",
      };

      setProperties((prev) => [...prev, newProperty]);
      return newProperty;
    } catch (err) {
      setError(err.message);
      throw err;
    } finally {
      setLoading(false);
    }
  }, []);

  const updateProperty = useCallback(async (id, updates) => {
    setLoading(true);
    try {
      await new Promise((resolve) => setTimeout(resolve, 500));

      setProperties((prev) =>
        prev.map((p) =>
          p.id === id
            ? { ...p, ...updates, updatedAt: new Date().toISOString() }
            : p,
        ),
      );
    } catch (err) {
      setError(err.message);
      throw err;
    } finally {
      setLoading(false);
    }
  }, []);

  const deleteProperty = useCallback(async (id) => {
    setLoading(true);
    try {
      await new Promise((resolve) => setTimeout(resolve, 500));
      setProperties((prev) => prev.filter((p) => p.id !== id));
    } catch (err) {
      setError(err.message);
      throw err;
    } finally {
      setLoading(false);
    }
  }, []);

  const getProperty = useCallback(
    (id) => {
      return properties.find((p) => p.id === id);
    },
    [properties],
  );

  const checkAvailability = useCallback(
    (propertyId, startDate, endDate) => {
      const property = properties.find((p) => p.id === propertyId);
      if (!property) return false;

      const checkStart = new Date(startDate);
      const checkEnd = new Date(endDate);

      return !property.bookings?.some((booking) => {
        if (booking.status === "cancelled" || booking.status === "rejected") {
          return false;
        }

        const bookingStart = new Date(booking.startDate);
        const bookingEnd = new Date(booking.endDate);

        return (
          (checkStart >= bookingStart && checkStart <= bookingEnd) ||
          (checkEnd >= bookingStart && checkEnd <= bookingEnd) ||
          (checkStart <= bookingStart && checkEnd >= bookingEnd)
        );
      });
    },
    [properties],
  );

  const getPropertiesByOwner = useCallback(
    (ownerId) => {
      return properties.filter((p) => p.ownerId === ownerId);
    },
    [properties],
  );

  const getAvailableProperties = useCallback(() => {
    return properties.filter((p) => p.status === "available");
  }, [properties]);

  const updatePropertyStatus = useCallback(
    async (id, status) => {
      return updateProperty(id, { status });
    },
    [updateProperty],
  );

  const addBookingToProperty = useCallback(
    async (propertyId, bookingData) => {
      const property = getProperty(propertyId);
      if (!property) throw new Error("Property not found");

      const updatedBookings = [...(property.bookings || []), bookingData];
      return updateProperty(propertyId, { bookings: updatedBookings });
    },
    [getProperty, updateProperty],
  );

  return (
    <PropertyContext.Provider
      value={{
        properties,
        loading,
        error,
        addProperty,
        updateProperty,
        deleteProperty,
        getProperty,
        checkAvailability,
        getPropertiesByOwner,
        getAvailableProperties,
        updatePropertyStatus,
        addBookingToProperty,
      }}
    >
      {children}
    </PropertyContext.Provider>
  );
};
