export type SiteStatus = {
  offline: boolean
  /** ISO string — when the calendar reopens (UTC) */
  offlineUntil: string | null
  offlineMessage: string | null
  updatedAt: string
}

const DEFAULT: SiteStatus = {
  offline: false,
  offlineUntil: null,
  offlineMessage: null,
  updatedAt: new Date(0).toISOString(),
}

declare global {
  // eslint-disable-next-line no-var
  var __redbullSiteStatus: SiteStatus | undefined
}

function memoryGet(): SiteStatus {
  return globalThis.__redbullSiteStatus ?? { ...DEFAULT }
}

function memorySet(next: SiteStatus) {
  globalThis.__redbullSiteStatus = next
}

export function formatOfflineUntil(iso: string | null | undefined): string {
  if (!iso) return 'later'
  try {
    const d = new Date(iso)
    return (
      d.toLocaleString('en-GB', {
        timeZone: 'UTC',
        weekday: 'short',
        day: 'numeric',
        month: 'short',
        year: 'numeric',
        hour: '2-digit',
        minute: '2-digit',
        hour12: false,
      }) + ' UTC'
    )
  } catch {
    return 'later'
  }
}

export function buildOfflineCopy(status: SiteStatus): { title: string; body: string } {
  const until = formatOfflineUntil(status.offlineUntil)
  if (status.offlineMessage?.trim()) {
    return {
      title: 'Calendar is currently offline',
      body: status.offlineMessage.trim(),
    }
  }
  return {
    title: 'Calendar is currently offline',
    body: `Please come back after ${until}. Scheduling will reopen automatically when the countdown ends.`,
  }
}

function maybeAutoResume(status: SiteStatus): SiteStatus | null {
  if (!status.offline || !status.offlineUntil) return null
  const target = new Date(status.offlineUntil).getTime()
  if (Number.isNaN(target) || target > Date.now()) return null
  return {
    offline: false,
    offlineUntil: null,
    offlineMessage: null,
    updatedAt: new Date().toISOString(),
  }
}

async function loadRawStatus(): Promise<SiteStatus> {
  try {
    const { supabase } = await import('@/lib/supabase')
    const { data, error } = await supabase
      .from('site_settings')
      .select('value, updated_at')
      .eq('key', 'portal_status')
      .maybeSingle()

    if (!error && data?.value) {
      const v = data.value as Partial<SiteStatus>
      return {
        offline: Boolean(v.offline),
        offlineUntil: v.offlineUntil ?? null,
        offlineMessage: v.offlineMessage ?? null,
        updatedAt: data.updated_at || new Date().toISOString(),
      }
    }
  } catch {
    /* table may not exist yet */
  }
  return memoryGet()
}

async function persistStatus(status: SiteStatus): Promise<SiteStatus> {
  memorySet(status)
  try {
    const { supabase } = await import('@/lib/supabase')
    await supabase.from('site_settings').upsert(
      {
        key: 'portal_status',
        value: {
          offline: status.offline,
          offlineUntil: status.offlineUntil,
          offlineMessage: status.offlineMessage,
        },
        updated_at: status.updatedAt,
      },
      { onConflict: 'key' }
    )
  } catch {
    /* ignore */
  }
  return status
}

export async function readSiteStatus(): Promise<SiteStatus> {
  const status = await loadRawStatus()
  const resumed = maybeAutoResume(status)
  if (resumed) return persistStatus(resumed)
  memorySet(status)
  return status
}

export async function writeSiteStatus(
  patch: Partial<Pick<SiteStatus, 'offline' | 'offlineUntil' | 'offlineMessage'>>
): Promise<SiteStatus> {
  const prev = await loadRawStatus()
  const next: SiteStatus = {
    offline: patch.offline ?? prev.offline,
    offlineUntil:
      patch.offlineUntil !== undefined ? patch.offlineUntil : prev.offlineUntil,
    offlineMessage:
      patch.offlineMessage !== undefined ? patch.offlineMessage : prev.offlineMessage,
    updatedAt: new Date().toISOString(),
  }

  return persistStatus(next)
}

/** Default resume time when pausing without a pick — today 20:00 UTC (or tomorrow if past) */
export function defaultOfflineUntilIso(): string {
  const now = new Date()
  const until = new Date(
    Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), 20, 0, 0)
  )
  if (until.getTime() <= now.getTime()) {
    until.setUTCDate(until.getUTCDate() + 1)
  }
  return until.toISOString()
}
