'use client'

import { useState, useEffect, useCallback, useRef } from 'react'

interface Booking {
  id: string
  facilityName: string
  status: string
  paymentStatus: string
  startDate: string
  endDate: string
  createdAt: string
}

interface AvailabilityData {
  date: string
  bookedSlots: number
  availableSlots: number
  maxSlots: number
  status: 'free' | 'available' | 'limited' | 'soldout'
  bookings: Booking[]
}

interface BookingsData {
  success: boolean
  fetchedAt: string
  dateRange: {
    start: string
    end: string
  }
  monthsAhead: number
  totalAds: number
  availability: Record<string, Record<string, AvailabilityData>>
  bookingsByPlacement: Record<string, Record<string, Booking[]>>
}

const CACHE_DURATION = 5 * 60 * 1000 // 5 minutes
const STORAGE_KEY = 'ad_bookings_cache'

interface CacheEntry {
  data: BookingsData
  timestamp: number
}

export function useAdBookings(monthsAhead: number = 6) {
  const [bookingsData, setBookingsData] = useState<BookingsData | null>(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const fetchTimeoutRef = useRef<NodeJS.Timeout | null>(null)
  const isMountedRef = useRef(true)

  // Load from cache
  const loadFromCache = useCallback((): BookingsData | null => {
    try {
      const cached = localStorage.getItem(STORAGE_KEY)
      if (cached) {
        const entry: CacheEntry = JSON.parse(cached)
        const now = Date.now()
        const age = now - entry.timestamp
        const ageMinutes = Math.floor(age / 60000)
        
        // Check if cache is still valid
        if (age < CACHE_DURATION) {
          console.log(`[useAdBookings Hook] Using cached data (${ageMinutes}m old, ${entry.data.totalAds} ads)`)
          return entry.data
        }
      }
    } catch (err) {
      console.error('[useAdBookings Hook] Cache error:', err)
    }
    return null
  }, [])

  // Save to cache
  const saveToCache = useCallback((data: BookingsData) => {
    try {
      const entry: CacheEntry = {
        data,
        timestamp: Date.now()
      }
      localStorage.setItem(STORAGE_KEY, JSON.stringify(entry))
    } catch (err) {
      console.error('Error saving to cache:', err)
    }
  }, [])

  // Fetch bookings from API
  const fetchBookings = useCallback(async (forceRefresh: boolean = false) => {
    // Don't fetch if component is unmounted
    if (!isMountedRef.current) {
      console.log('[useAdBookings Hook] Skipping fetch - component unmounted')
      return null
    }
    
    // Check cache first if not forcing refresh
    if (!forceRefresh) {
      const cached = loadFromCache()
      if (cached) {
        if (isMountedRef.current) {
          setBookingsData(cached)
          setLoading(false)
          setError(null)
        }
        return cached
      }
    }

    if (isMountedRef.current) {
      setLoading(true)
      setError(null)
    }

    try {
      const response = await fetch(`/api/ads/bookings/all-future?monthsAhead=${monthsAhead}`, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
        },
      })
      
      if (!response.ok) {
        throw new Error(`Failed to fetch bookings: ${response.status} ${response.statusText}`)
      }

      const data: BookingsData = await response.json()
      
      // Log availability summary
      const summary: any = {}
      Object.keys(data.availability).forEach(placement => {
        const dates = Object.keys(data.availability[placement])
        const soldOut = dates.filter(d => data.availability[placement][d].status === 'soldout')
        summary[placement] = { totalDates: dates.length, soldOut: soldOut.length }
      })
      
      console.log(`[useAdBookings Hook] Loaded bookings:`, {
        totalAds: data.totalAds,
        dateRange: data.dateRange,
        summary
      })
      
      // Only update state if component is still mounted
      if (isMountedRef.current) {
        setBookingsData(data)
        setError(null)
      }
      saveToCache(data)
      
      return data
    } catch (err: any) {
      const errorMsg = err.message || 'Failed to fetch bookings'
      console.error('[useAdBookings Hook] Error fetching bookings:', err)
      
      // Only update state if component is still mounted
      if (isMountedRef.current) {
        setError(errorMsg)
        
        // Try to use cache even if expired on error
        const cached = loadFromCache()
        if (cached) {
          setBookingsData(cached)
        }
      }
      
      return null
    } finally {
      if (isMountedRef.current) {
        setLoading(false)
      }
    }
  }, [monthsAhead, loadFromCache, saveToCache])

  // Get availability for a specific date and placement type
  const getAvailability = useCallback((date: Date, placementType: string): AvailabilityData | null => {
    if (!bookingsData) return null

    const normalizeDate = (d: Date): string => {
      const year = d.getFullYear()
      const month = String(d.getMonth() + 1).padStart(2, '0')
      const day = String(d.getDate()).padStart(2, '0')
      return `${year}-${month}-${day}`
    }

    const dateStr = normalizeDate(date)
    const availability = bookingsData.availability[placementType]?.[dateStr] || null
    
    return availability
  }, [bookingsData])

  // Check if a date is sold out for a placement type
  const isSoldOut = useCallback((date: Date, placementType: string): boolean => {
    const availability = getAvailability(date, placementType)
    return availability?.status === 'soldout' || availability?.availableSlots === 0
  }, [getAvailability])

  // Get all sold-out dates for a placement type
  const getSoldOutDates = useCallback((placementType: string): Set<string> => {
    if (!bookingsData) return new Set()

    const soldOut = new Set<string>()
    const placementData = bookingsData.availability[placementType] || {}

    Object.values(placementData).forEach((avail: AvailabilityData) => {
      if (avail.status === 'soldout' || avail.availableSlots === 0) {
        soldOut.add(avail.date)
      }
    })

    return soldOut
  }, [bookingsData])

  // Get availability for a date range
  const getDateRangeAvailability = useCallback((
    startDate: Date,
    endDate: Date,
    placementType: string
  ): { isBookable: boolean; soldOutDates: string[]; availability: AvailabilityData[] } => {
    if (!bookingsData) {
      console.log(`[useAdBookings Hook] No bookings data available for range check`)
      return { isBookable: false, soldOutDates: [], availability: [] }
    }

    const normalizeDate = (d: Date): string => {
      const year = d.getFullYear()
      const month = String(d.getMonth() + 1).padStart(2, '0')
      const day = String(d.getDate()).padStart(2, '0')
      return `${year}-${month}-${day}`
    }

    const dates: string[] = []
    const current = new Date(startDate)
    while (current <= endDate) {
      dates.push(normalizeDate(new Date(current)))
      current.setDate(current.getDate() + 1)
    }

    const availability: AvailabilityData[] = []
    const soldOutDates: string[] = []

    dates.forEach(dateStr => {
      const avail = bookingsData.availability[placementType]?.[dateStr]
      if (avail) {
        availability.push(avail)
        if (avail.status === 'soldout' || avail.availableSlots === 0) {
          soldOutDates.push(dateStr)
        }
      } else {
        // Date not in bookings (should be free)
        availability.push({
          date: dateStr,
          bookedSlots: 0,
          availableSlots: 5,
          maxSlots: 5,
          status: 'free',
          bookings: []
        })
      }
    })

    const isBookable = soldOutDates.length === 0

    if (soldOutDates.length > 0) {
      console.log(`[useAdBookings Hook] Range check (${placementType}): ${soldOutDates.length} sold out - ${soldOutDates.join(', ')}`)
    }

    return { isBookable, soldOutDates, availability }
  }, [bookingsData])

  // Initial load - only run once on mount
  useEffect(() => {
    isMountedRef.current = true
    
    // Initial fetch
    fetchBookings()

    return () => {
      isMountedRef.current = false
      if (fetchTimeoutRef.current) {
        clearInterval(fetchTimeoutRef.current)
        fetchTimeoutRef.current = null
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []) // Only run once on mount
  
  // Set up periodic refresh - separate effect
  useEffect(() => {
    // Clear any existing interval
    if (fetchTimeoutRef.current) {
      clearInterval(fetchTimeoutRef.current)
    }
    
    // Set up new interval
    fetchTimeoutRef.current = setInterval(() => {
      if (isMountedRef.current) {
        fetchBookings(true)
      }
    }, CACHE_DURATION)

    return () => {
      if (fetchTimeoutRef.current) {
        clearInterval(fetchTimeoutRef.current)
        fetchTimeoutRef.current = null
      }
    }
  }, [fetchBookings]) // Update interval when fetchBookings changes

  return {
    bookingsData,
    loading,
    error,
    fetchBookings,
    getAvailability,
    isSoldOut,
    getSoldOutDates,
    getDateRangeAvailability,
    refresh: () => fetchBookings(true)
  }
}

