// Cookie utility functions for authentication
const COOKIE_OPTIONS = {
  path: '/',
  secure: window.location.protocol === 'https:',
  sameSite: 'Lax',
  maxAge: 7 * 24 * 60 * 60 // 7 days in seconds
}

const getAuthExpiryTime = (expiresAt) => {
  const numericExpiry = Number(expiresAt)
  if (Number.isFinite(numericExpiry) && numericExpiry > 0) return numericExpiry
  return new Date(expiresAt).getTime()
}

const getAuthCookieMaxAge = (expiresAt) => {
  const expiryTime = getAuthExpiryTime(expiresAt)
  if (!Number.isFinite(expiryTime)) return COOKIE_OPTIONS.maxAge
  return Math.max(Math.floor((expiryTime - Date.now()) / 1000), 1)
}

/**
 * Set a cookie with authentication data
 * @param {string} name - Cookie name
 * @param {string} value - Cookie value
 * @param {Object} options - Cookie options
 */
export const setCookie = (name, value, options = {}) => {
  try {
    if (!name || value === undefined || value === null) {
      console.warn('Invalid cookie parameters:', { name, value })
      return false
    }

    const cookieOptions = { ...COOKIE_OPTIONS, ...options }

    let cookieString = `${name}=${encodeURIComponent(value)}`

    if (cookieOptions.maxAge) {
      cookieString += `; Max-Age=${cookieOptions.maxAge}`
    }

    if (cookieOptions.path) {
      cookieString += `; Path=${cookieOptions.path}`
    }

    if (cookieOptions.domain) {
      cookieString += `; Domain=${cookieOptions.domain}`
    }

    if (cookieOptions.secure) {
      cookieString += '; Secure'
    }

    if (cookieOptions.sameSite) {
      cookieString += `; SameSite=${cookieOptions.sameSite}`
    }

    if (cookieOptions.httpOnly) {
      cookieString += '; HttpOnly'
    }

    document.cookie = cookieString
    return true
  } catch (error) {
    console.error('Error setting cookie:', error)
    return false
  }
}

/**
 * Get a cookie value by name
 * @param {string} name - Cookie name
 * @returns {string|null} - Cookie value or null if not found
 */
export const getCookie = (name) => {
  try {
    if (!name) {
      console.warn('Cookie name is required')
      return null
    }

    const nameEQ = name + '='
    const cookies = document.cookie.split(';')

    for (let i = 0; i < cookies.length; i++) {
      let cookie = cookies[i]
      while (cookie.charAt(0) === ' ') {
        cookie = cookie.substring(1, cookie.length)
      }
      if (cookie.indexOf(nameEQ) === 0) {
        return decodeURIComponent(
          cookie.substring(nameEQ.length, cookie.length)
        )
      }
    }
    return null
  } catch (error) {
    console.error('Error getting cookie:', error)
    return null
  }
}

/**
 * Remove a cookie by setting it to expire in the past
 * @param {string} name - Cookie name
 * @param {Object} options - Cookie options (path and domain must match when setting)
 */
export const removeCookie = (name, options = {}) => {
  try {
    if (!name) {
      console.warn('Cookie name is required for removal')
      return false
    }

    const cookieOptions = { ...COOKIE_OPTIONS, ...options }
    setCookie(name, '', { ...cookieOptions, maxAge: -1 })
    return true
  } catch (error) {
    console.error('Error removing cookie:', error)
    return false
  }
}

/**
 * Check if cookies are enabled in the browser
 * @returns {boolean} - True if cookies are enabled
 */
export const areCookiesEnabled = () => {
  try {
    setCookie('test', 'test')
    const enabled = getCookie('test') === 'test'
    removeCookie('test')
    return enabled
  } catch (e) {
    console.error('Error checking if cookies are enabled:', e)
    return false
  }
}

/**
 * Check if authentication cookies are expired and clean them up if needed
 * @returns {boolean} - True if cookies are valid and not expired
 */
export const validateAuthCookies = () => {
  try {
    const { token, expiresAt, user } = getAuthCookies()

    if (!token || !expiresAt || !user) {
      return false
    }

    const now = Date.now()
    const expirationTime = getAuthExpiryTime(expiresAt)

    if (!Number.isFinite(expirationTime) || expirationTime <= now) {
      // Cookies are expired, clean them up
      clearAuthCookies()
      return false
    }

    return true
  } catch (error) {
    console.error('Error validating auth cookies:', error)
    clearAuthCookies()
    return false
  }
}

/**
 * Check if authentication cookies are about to expire (within specified minutes)
 * @param {number} minutesBeforeExpiry - Minutes before expiry to consider "about to expire"
 * @returns {Object} - Object with isExpiringSoon flag and timeRemaining in milliseconds
 */
export const checkAuthCookiesExpiry = (minutesBeforeExpiry = 5) => {
  try {
    const { token, expiresAt, user } = getAuthCookies()

    if (!token || !expiresAt || !user) {
      return { isExpiringSoon: false, timeRemaining: 0 }
    }

    const timeRemaining = getAuthExpiryTime(expiresAt) - Date.now()
    const minutesRemaining = timeRemaining / (1000 * 60)

    return {
      isExpiringSoon: minutesRemaining <= minutesBeforeExpiry,
      timeRemaining,
      minutesRemaining: Math.floor(minutesRemaining)
    }
  } catch (error) {
    console.error('Error checking auth cookies expiry:', error)
    return { isExpiringSoon: false, timeRemaining: 0 }
  }
}

/**
 * Set up a listener for cookie changes to sync authentication state between tabs
 * @param {Function} onAuthChange - Callback function when auth state changes
 * @returns {Function} - Function to remove the listener
 */
export const setupCookieSync = (onAuthChange) => {
  const handleStorageChange = (event) => {
    // Check if auth-related cookies changed
    if (
      event.key === 'authToken' ||
      event.key === 'authExpiresAt' ||
      event.key === 'user'
    ) {
      // Small delay to ensure cookies are updated
      setTimeout(() => {
        onAuthChange()
      }, 100)
    }
  }

  // Listen for storage events (for cross-tab communication)
  window.addEventListener('storage', handleStorageChange)

  // Also listen for cookie changes using a polling mechanism
  let lastCookieState = document.cookie
  const cookieCheckInterval = setInterval(() => {
    const currentCookieState = document.cookie
    if (currentCookieState !== lastCookieState) {
      lastCookieState = currentCookieState
      // Check if auth cookies changed
      const authCookies = getAuthCookies()
      if (authCookies.token || authCookies.expiresAt || authCookies.user) {
        onAuthChange()
      }
    }
  }, 1000)

  // Return cleanup function
  return () => {
    window.removeEventListener('storage', handleStorageChange)
    clearInterval(cookieCheckInterval)
  }
}

/**
 * Set authentication cookies
 * @param {Object} authData - Authentication data object
 * @returns {boolean} - True if all cookies were set successfully
 */
export const setAuthCookies = (authData) => {
  try {
    if (!authData) {
      console.warn('Auth data is required')
      return false
    }

    let success = true
    const maxAge = getAuthCookieMaxAge(authData.expires_at)

    if (authData.access_token) {
      success =
        success &&
        setCookie('authToken', authData.access_token, {
          maxAge
        })
    }

    if (authData.expires_at) {
      success =
        success &&
        setCookie('authExpiresAt', authData.expires_at, {
          maxAge
        })
    }

    if (authData.user) {
      const userObject = {
        ...authData.user,
        access_token: undefined,
        refresh_token: undefined,
        id_token: undefined
      }
      success =
        success &&
        setCookie('user', JSON.stringify(userObject), {
          maxAge
        })
    }

    if (!success) {
      console.warn('Some cookies failed to set, clearing all auth cookies')
      clearAuthCookies()
    }

    return success
  } catch (error) {
    console.error('Error setting auth cookies:', error)
    clearAuthCookies()
    return false
  }
}

/**
 * Get authentication cookies
 * @returns {Object} - Object containing auth data from cookies
 */
export const getAuthCookies = () => {
  return {
    token: getCookie('authToken'),
    expiresAt: getCookie('authExpiresAt'),
    user: getCookie('user') ? JSON.parse(getCookie('user')) : null
  }
}

/**
 * Clear authentication cookies
 */
export const clearAuthCookies = () => {
  removeCookie('authToken')
  removeCookie('authExpiresAt')
  removeCookie('user')
}
