import { useEffect, useState } from "react";
import type { DashboardRuntimeState } from "$lib/server/dashboard";
import { dashboardDocumentToUiDashboard } from "$lib/ui-adapter/model-renderer";
import {
  DashboardFrame,
  SystemState,
  ThemeToggle,
  persistUiTheme,
  resolveInitialUiTheme,
  type UiTheme,
  type UiSeverity,
} from "@dimensionlab/ui";

const loadingDashboardState: DashboardRuntimeState = {
  state: "loading",
  title: "Loading Dashboard",
  subtitle: "Fetching active model",
  message: "Waiting for the active dashboard document.",
};

export function AppStateView({
  dashboard,
  onThemeChange,
  theme,
}: {
  dashboard: DashboardRuntimeState;
  onThemeChange?: (theme: UiTheme) => void;
  theme?: UiTheme;
}) {
  const themeToggle =
    theme && onThemeChange ? (
      <ThemeToggle theme={theme} onThemeChange={onThemeChange} />
    ) : null;

  if (dashboard.state === "ready") {
    return (
      <DashboardFrame
        dashboard={dashboardDocumentToUiDashboard(dashboard.document)}
        actions={themeToggle}
      />
    );
  }

  const detail = `${dashboard.subtitle}: ${dashboard.message}`;
  const errors = dashboard.state === "invalid" ? dashboard.errors : [];

  return (
    <main className="state-shell" data-dashboard-state={dashboard.state}>
      {themeToggle ? (
        <div className="state-shell__actions">{themeToggle}</div>
      ) : null}
      <SystemState
        title={dashboard.title}
        detail={detail}
        severity={stateSeverity(dashboard.state)}
        icon={stateIcon(dashboard.state)}
      />
      {errors.length ? (
        <ul aria-label="Validation errors">
          {errors.map((error) => (
            <li key={error}>{error}</li>
          ))}
        </ul>
      ) : null}
    </main>
  );
}

export function resolveDocumentMetadata(dashboard: DashboardRuntimeState): {
  description: string;
  title: string;
} {
  if (dashboard.state === "ready") {
    const uiDashboard = dashboardDocumentToUiDashboard(dashboard.document);
    return {
      title: uiDashboard.title,
      description:
        uiDashboard.subtitle ||
        dashboard.document.metadata.description ||
        uiDashboard.title,
    };
  }

  return {
    title: dashboard.title,
    description: dashboard.subtitle || dashboard.message,
  };
}

export default function App() {
  const [dashboard, setDashboard] =
    useState<DashboardRuntimeState>(loadingDashboardState);
  const [theme, setTheme] = useState<UiTheme>(() => {
    if (typeof window === "undefined") return "dark";

    return resolveInitialUiTheme(getThemeStorage());
  });

  useEffect(() => {
    const metadata = resolveDocumentMetadata(dashboard);
    document.title = metadata.title;

    let description = document.querySelector<HTMLMetaElement>(
      'meta[name="description"]',
    );
    if (!description) {
      description = document.createElement("meta");
      description.name = "description";
      document.head.append(description);
    }
    description.content = metadata.description;
  }, [dashboard]);

  useEffect(() => {
    document.documentElement.dataset.uiTheme = theme;
    persistUiTheme(theme, getThemeStorage());
  }, [theme]);

  useEffect(() => {
    let cancelled = false;
    let refreshTimer: number | undefined;

    async function loadDashboard() {
      const response = await fetch("/api/dashboard");
      const nextDashboard = (await response.json()) as DashboardRuntimeState;

      if (cancelled) return;
      setDashboard(nextDashboard);

      if (refreshTimer) {
        window.clearInterval(refreshTimer);
        refreshTimer = undefined;
      }

      const refreshIntervalSeconds =
        nextDashboard.state === "ready"
          ? nextDashboard.document.metadata.refreshIntervalSeconds
          : undefined;

      if (refreshIntervalSeconds) {
        refreshTimer = window.setInterval(
          () => void loadDashboard(),
          refreshIntervalSeconds * 1000,
        );
      }
    }

    void loadDashboard();

    return () => {
      cancelled = true;
      if (refreshTimer) window.clearInterval(refreshTimer);
    };
  }, []);

  return (
    <AppStateView
      dashboard={dashboard}
      theme={theme}
      onThemeChange={setTheme}
    />
  );
}

function stateSeverity(state: DashboardRuntimeState["state"]): UiSeverity {
  if (state === "invalid") return "danger";
  if (state === "loading") return "loading";
  return "stale";
}

function stateIcon(state: DashboardRuntimeState["state"]): string {
  if (state === "invalid") return "mdi:file-alert-outline";
  if (state === "loading") return "mdi:progress-clock";
  return "mdi:tray";
}

function getThemeStorage(): Storage | undefined {
  try {
    return window.localStorage;
  } catch {
    return undefined;
  }
}
