// `/` — the public status page. `renderMode: 'ssr'`, fed by the sibling api:
// the loader bakes the current incidents + components + updates into the first
// paint (crawlable), then the component upgrades each to live with
// `useSubscription`, so a newly-declared or resolved incident lands on every
// open page within seconds — no polling.
import type { ReactNode } from 'react'
import { useLoaderData, type LoaderFn, type PageMeta } from '@voltro/web'
import { useSubscription } from '@voltro/client'
import { T } from '@voltro/i18n'
import { getCatalog } from '../locales'
import {
  deriveOverall, uptimeGrid, uptimePercent,
  type Incident, type Component, type Update,
} from '../lib/status'

interface PageData {
  readonly incidents: ReadonlyArray<Incident>
  readonly components: ReadonlyArray<Component>
  readonly updates: ReadonlyArray<Update>
}

export const renderMode = 'ssr' as const

// `query` is present ONLY server-side. It invokes the api's rpc over POST /rpc;
// a streaming query is drained to its first snapshot. On a client navigation
// `query` is undefined and we start empty — the subscriptions fill in.
export const loader: LoaderFn<PageData> = async ({ query }) => ({
  incidents:  query ? await query<ReadonlyArray<Incident>>('incidents.live', {}) : [],
  components: query ? await query<ReadonlyArray<Component>>('components.list', {}) : [],
  updates:    query ? await query<ReadonlyArray<Update>>('updates.list', {}) : [],
})

export const meta = ({ locale }: { readonly locale: string }): PageMeta => ({
  title:       getCatalog(locale)['meta.title'],
  description: getCatalog(locale)['meta.description'],
})

const fmtDate = (v: string | Date | null): string =>
  v == null ? '' : new Date(v).toLocaleString()

export default function StatusPage(): ReactNode {
  const initial = useLoaderData<PageData>()
  const { data: iLive } = useSubscription<ReadonlyArray<Incident>>('app', 'incidents.live')
  const { data: cLive } = useSubscription<ReadonlyArray<Component>>('app', 'components.list')
  const { data: uLive } = useSubscription<ReadonlyArray<Update>>('app', 'updates.list')

  const incidents  = iLive ?? initial.incidents
  const components = cLive ?? initial.components
  const updates    = uLive ?? initial.updates

  const overall = deriveOverall(incidents, components)
  const grid = uptimeGrid(incidents)
  const pct = uptimePercent(grid)

  const updatesFor = (incidentId: string): ReadonlyArray<Update> =>
    updates
      .filter((u) => u.incidentId === incidentId)
      .slice()
      .sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime())

  return (
    <main>
      {/* Overall banner */}
      <div className={`banner banner--${overall}`} role="status">
        <span className="dot" aria-hidden="true" />
        <strong><T id={`overall.${overall}`} /></strong>
      </div>

      {/* Uptime */}
      <section>
        <h2><T id="uptime.heading" values={{ days: String(grid.length) }} /></h2>
        <div className="uptime" aria-hidden="true">
          {grid.map((up, idx) => (
            <span key={idx} className={up ? 'day up' : 'day down'} />
          ))}
        </div>
        <p className="muted"><T id="uptime.percent" values={{ percent: String(pct) }} /></p>
      </section>

      {/* Components */}
      <section>
        <h2><T id="components.heading" /></h2>
        {components.length === 0 ? (
          <p className="muted"><T id="components.empty" /></p>
        ) : (
          <ul className="components">
            {components.map((c) => (
              <li key={c.id}>
                <span>{c.name}</span>
                <span className={`pill pill--${c.status}`}><T id={`comp.status.${c.status}`} /></span>
              </li>
            ))}
          </ul>
        )}
      </section>

      {/* Incidents */}
      <section>
        <h2><T id="incidents.heading" /></h2>
        {incidents.length === 0 ? (
          <p className="muted"><T id="incidents.none" /></p>
        ) : (
          <ul className="incidents">
            {incidents.map((inc) => (
              <li key={inc.id} className={`incident impact--${inc.impact}`}>
                <div className="incident-head">
                  <strong>{inc.title}</strong>
                  <span className="pill"><T id={`impact.${inc.impact}`} /></span>
                  <span className="pill"><T id={`status.${inc.status}`} /></span>
                </div>
                <p className="muted">
                  <T id="incident.started" values={{ when: fmtDate(inc.startedAt) }} />
                  {' · '}
                  {inc.resolvedAt == null
                    ? <T id="incident.ongoing" />
                    : <T id="incident.resolved" values={{ when: fmtDate(inc.resolvedAt) }} />}
                </p>
                {updatesFor(inc.id).length > 0 ? (
                  <ul className="timeline">
                    {updatesFor(inc.id).map((u) => (
                      <li key={u.id}>
                        <span className="ts">{fmtDate(u.createdAt)}</span>
                        <span className="pill"><T id={`status.${u.status}`} /></span>
                        <span>{u.body}</span>
                      </li>
                    ))}
                  </ul>
                ) : null}
              </li>
            ))}
          </ul>
        )}
      </section>
    </main>
  )
}
