import type { CSSProperties, ReactElement, ReactNode } from "react";
import { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState } from "react";

import { useAuth } from "./hooks/useAuth";
import { providerProfileLabel } from "./hooks/useProviderProfileOptions";
import { useSidebarResize } from "./hooks/useSidebarResize";
import { useWorkbenchStore } from "./state/workbench";
import type { RouteId } from "./types/domain";
import { LoginShell } from "./components/auth/LoginShell";
import { CommandBar } from "./components/command-bar/CommandBar";
import { recordDraft } from "./components/command-bar/DraftsList";
import { ConversationPanel } from "./components/conversation/ConversationPanel";
import { HwpodNodeOpsSidebar } from "./components/hwpod/HwpodNodeOpsSidebar";
import { ActivityRail } from "./components/layout/ActivityRail";
import { SessionSidebar } from "./components/sessions/SessionSidebar";
import { WorkbenchBuildSummary } from "./components/workbench/WorkbenchBuildSummary";
import { WorkbenchProbe } from "./components/workbench/WorkbenchProbe";
import { fetchText } from "./services/api/client";
import { installWebPerformanceTelemetry } from "./services/performance/rum";
import { rememberWorkbenchProjectId, resolveInitialWorkbenchProjectId, workspaceProjectId } from "./state/constants";
import { firstNonEmptyString } from "./utils";

const AccessView = lazy(() => import("./components/access/AccessView").then((module) => ({ default: module.AccessView })));
const GateView = lazy(() => import("./components/gate/GateView").then((module) => ({ default: module.GateView })));
const ManagementView = lazy(() => import("./components/management/ManagementView").then((module) => ({ default: module.ManagementView })));
const PerformanceView = lazy(() => import("./components/performance/PerformanceView").then((module) => ({ default: module.PerformanceView })));
const SettingsView = lazy(() => import("./components/settings/SettingsView").then((module) => ({ default: module.SettingsView })));
const SkillsView = lazy(() => import("./components/skills/SkillsView").then((module) => ({ default: module.SkillsView })));

const SESSION_SIDEBAR_STORAGE_KEY = "hwlab.workbench.sessionSidebarWidth.v1";
const SESSION_SIDEBAR_DEFAULT_WIDTH = 330;
const SESSION_SIDEBAR_MIN_WIDTH = 180;
const SESSION_SIDEBAR_MAX_WIDTH = 640;
const RIGHT_SIDEBAR_STORAGE_KEY = "hwlab.workbench.rightSidebarWidth.v1";
const RIGHT_SIDEBAR_DEFAULT_WIDTH = 620;
const RIGHT_SIDEBAR_MIN_WIDTH = 420;
const RIGHT_SIDEBAR_MAX_WIDTH = 680;

const routeLabels: Record<RouteId, string> = {
  workspace: "工作台",
  performance: "性能监控",
  skills: "Skills",
  management: "管理",
  access: "授权管理",
  gate: "内部复核",
  help: "使用说明",
  settings: "设置"
};

export function App(): ReactElement {
  const [projectId, setProjectId] = useState(() => resolveInitialWorkbenchProjectId());
  const auth = useAuth(projectId);
  const [route, setRoute] = useState<RouteId>(() => routeFromLocation());
  const workspaceRoute = route === "workspace";
  const authReady = auth.authState === "authenticated";
  const authChecking = auth.authState === "checking";
  const workspaceShellPendingAuth = authChecking && workspaceRoute;
  const store = useWorkbenchStore(authReady && workspaceRoute, projectId);
  const [pickedDraft, setPickedDraft] = useState<string | null>(null);
  const [leftCollapsed, setLeftCollapsed] = useState(false);
  const [rightCollapsed, setRightCollapsed] = useState(false);
  const [help, setHelp] = useState("加载中");
  const shellRef = useRef<HTMLElement | null>(null);
  const narrow = useMatchMedia("(max-width: 1240px)");

  useEffect(() => {
    installWebPerformanceTelemetry();
  }, []);

  useEffect(() => {
    const next = workspaceProjectId(store.state.workspace, projectId);
    if (next === projectId) return;
    rememberWorkbenchProjectId(next);
    setProjectId(next);
  }, [projectId, store.state.workspace]);

  const sessionResize = useSidebarResize({
    storageKey: SESSION_SIDEBAR_STORAGE_KEY,
    defaultWidth: SESSION_SIDEBAR_DEFAULT_WIDTH,
    bounds: { min: SESSION_SIDEBAR_MIN_WIDTH, max: SESSION_SIDEBAR_MAX_WIDTH },
    side: "left",
    disabled: narrow || leftCollapsed,
    shellElement: shellRef.current,
    cssVariable: "--session-sidebar-width"
  });

  const rightResize = useSidebarResize({
    storageKey: RIGHT_SIDEBAR_STORAGE_KEY,
    defaultWidth: RIGHT_SIDEBAR_DEFAULT_WIDTH,
    bounds: { min: RIGHT_SIDEBAR_MIN_WIDTH, max: RIGHT_SIDEBAR_MAX_WIDTH },
    side: "right",
    disabled: narrow || rightCollapsed,
    shellElement: shellRef.current,
    cssVariable: "--right-sidebar-width"
  });

  useEffect(() => {
    const listener = (): void => setRoute(routeFromLocation());
    window.addEventListener("hashchange", listener);
    return () => window.removeEventListener("hashchange", listener);
  }, []);

  function pickDraft(value: string): void {
    setPickedDraft(value);
  }

  function clearPickedDraft(): void {
    setPickedDraft(null);
  }

  // HWLAB #795: wire the command bar's onTyping to the workbench activity
  // clock so the Code Agent inactivity-timeout (driven by activityRef in
  // state/workbench.ts) does not falsely fire while the user is reading the
  // trace / composing a follow-up. The bar only emits onTyping on actual
  // input changes; we keep this stable via useCallback so the CommandBar
  // does not re-render on every keystroke.
  const noteActivity = useCallback(() => {
    store.recordActivity();
  }, [store]);

  async function submitWithDraftRecord(value: string): Promise<void> {
    recordDraft(value);
    await store.submitMessage(value);
  }

  useEffect(() => {
    if (route !== "help") return;
    void fetchText("/help.md", { timeoutMs: 8000 }).then((response) => setHelp(response.ok ? response.data ?? "" : `帮助内容加载失败：${response.error ?? "unknown"}`));
  }, [route]);

  const modelLabel = useMemo(() => providerProfileLabel(store.state.providerProfile), [store.state.providerProfile]);
  const sessionSidebarVisible = workspaceRoute && !leftCollapsed;
  const hwpodSidebarVisible = workspaceRoute && !rightCollapsed;
  const shellStyle = useMemo(() => ({
    "--session-sidebar-width": `${sessionResize.width}px`,
    "--right-sidebar-width": `${rightResize.width}px`
  }) as CSSProperties, [rightResize.width, sessionResize.width]);

  function navigate(nextRoute: RouteId): void {
    window.location.hash = `/${nextRoute}`;
    setRoute(nextRoute);
  }

  if (authChecking && !workspaceRoute) return <AuthLoadingShell />;
  if (auth.authState === "login") return <LoginShell error={auth.error} onLogin={auth.login} />;

  return (
    <main
      ref={shellRef}
      className={`workbench-shell${leftCollapsed ? " is-left-sidebar-collapsed" : ""}${rightCollapsed ? " is-right-sidebar-collapsed" : ""}${sessionResize.isDragging || rightResize.isDragging ? " is-resizing" : ""}${workspaceShellPendingAuth ? " is-auth-checking" : ""}`}
      style={shellStyle}
      aria-busy={workspaceShellPendingAuth}
      data-auth-checking={workspaceShellPendingAuth ? "true" : undefined}
      data-app-shell
      data-help-route-policy="non-default-internal-help"
      data-internal-help-path="/help.md"
    >
      <ActivityRail route={route} onRoute={navigate} disabled={workspaceShellPendingAuth} />
      <section className="main-workspace" id="main-workspace" aria-label="主工作区">
        <header className="workspace-topbar" id="workspace-topbar" aria-label="主工作区状态栏">
          <button className="workspace-topbar-button" id="left-sidebar-toggle" type="button" aria-controls="session-sidebar" aria-expanded={sessionSidebarVisible} aria-label={leftCollapsed ? "展开左侧 Session sidebar" : "折叠左侧 Session sidebar"} title={leftCollapsed ? "展开左侧 Session sidebar" : "折叠左侧 Session sidebar"} disabled={workspaceShellPendingAuth || !workspaceRoute} onClick={() => setLeftCollapsed((value) => !value)}>{leftCollapsed ? "Sessions" : "隐藏 Sessions"}</button>
          <div className="workspace-topbar-status">
            <span className="workspace-route-label">{routeLabels[route]}</span>
            <StatePill tone={store.state.chatPending ? "pending" : "source"}>{store.state.chatPending ? "处理中" : modelLabel}</StatePill>
            {workspaceRoute ? (
              <div className="topbar-status-tools" aria-label="工作区实时状态">
                <WorkbenchProbe live={store.state.live} />
                <WorkbenchBuildSummary live={store.state.live} />
              </div>
            ) : null}
          </div>
          <button className="workspace-topbar-button" id="right-sidebar-toggle" type="button" aria-controls="hwpod-node-sidebar" aria-expanded={hwpodSidebarVisible} aria-label={rightCollapsed ? "展开右侧 HWPOD 看板" : "折叠右侧 HWPOD 看板"} title={rightCollapsed ? "展开右侧 HWPOD 看板" : "折叠右侧 HWPOD 看板"} disabled={workspaceShellPendingAuth || !workspaceRoute} onClick={() => setRightCollapsed((value) => !value)}>{rightCollapsed ? "HWPOD" : "隐藏 HWPOD"}</button>
        </header>
        <div className={`workspace-body${!workspaceRoute ? " is-route-without-sidebars" : ""}`}>
          {workspaceRoute ? <SessionSidebar tabs={store.sessionTabs} loading={store.state.loading} modelLabel={modelLabel} disabled={workspaceShellPendingAuth} onCreate={() => void store.createSession()} onDelete={() => void store.deleteCurrentSession()} onSelect={(tab) => void store.selectConversation(tab)} /> : null}
          {workspaceRoute ? (
            <div
              className="resize-handle session-sidebar-resize"
              id="session-sidebar-resize"
              role="separator"
              tabIndex={workspaceShellPendingAuth || narrow || leftCollapsed ? -1 : 0}
              aria-disabled={workspaceShellPendingAuth || narrow || leftCollapsed}
              aria-hidden={workspaceShellPendingAuth || narrow || leftCollapsed}
              aria-label="拖拽调整 Session sidebar 宽度"
              aria-controls="session-sidebar"
              aria-orientation="vertical"
              aria-valuemin={sessionResize.bounds.min}
              aria-valuemax={sessionResize.bounds.max}
              aria-valuenow={sessionResize.ariaValueNow}
              aria-valuetext={sessionResize.ariaValueText}
              title="拖拽调整 Session sidebar 宽度；用左右方向键微调，Home/End 到最小或最大。"
              onPointerDown={sessionResize.onPointerDown}
              onPointerMove={sessionResize.onPointerMove}
              onPointerUp={sessionResize.onPointerUp}
              onPointerCancel={sessionResize.onPointerCancel}
              onKeyDown={sessionResize.onKeyDown}
            />
          ) : null}
          <section className="center-workspace">
            {route === "workspace" ? <ConversationPanel messages={store.state.messages} loading={store.state.loading} availability={store.state.codeAgentAvailability} live={store.state.live} chatPending={store.state.chatPending} codeAgentTimeoutMs={store.state.codeAgentTimeoutMs} onCopySession={() => copyTextToClipboard(firstNonEmptyString(store.composer.sessionId, store.state.workspace?.selectedAgentSessionId, store.state.workspace?.workspace?.selectedAgentSessionId, store.activeConversationId) ?? "")} onCancelMessage={(id) => void store.cancelAgentMessage(id)} onRetryMessage={(id) => void store.retryAgentMessage(id)} onReplayTrace={(id) => void store.replayAgentTrace(id)} /> : null}
            {route === "performance" ? <DeferredRouteView><PerformanceView /></DeferredRouteView> : null}
            {route === "skills" ? <DeferredRouteView><SkillsView /></DeferredRouteView> : null}
            {route === "management" ? <DeferredRouteView><ManagementView /></DeferredRouteView> : null}
            {route === "access" ? <DeferredRouteView><AccessView /></DeferredRouteView> : null}
            {route === "gate" ? <DeferredRouteView><GateView /></DeferredRouteView> : null}
            {route === "help" ? <HelpView help={help} /> : null}
            {route === "settings" ? <DeferredRouteView><SettingsView providerProfile={store.state.providerProfile} codeAgentTimeoutMs={store.state.codeAgentTimeoutMs} gatewayShellTimeoutMs={store.state.gatewayShellTimeoutMs} onProviderProfile={store.setProviderProfile} onCodeAgentTimeout={store.setCodeAgentTimeoutMs} onGatewayShellTimeout={store.setGatewayShellTimeoutMs} onLogout={auth.logout} /></DeferredRouteView> : null}
            {workspaceRoute ? <CommandBar key={store.activeConversationId ?? "default"} disabled={store.composer.disabled} interactionDisabled={workspaceShellPendingAuth} submitMode={store.composer.submitMode} targetTraceId={store.composer.targetTraceId} providerProfile={store.state.providerProfile} onProviderProfile={store.setProviderProfile} onSubmit={submitWithDraftRecord} onClear={store.clearConversation} pickedDraft={pickedDraft} onPickedDraftConsumed={clearPickedDraft} disabledReason={store.composer.disabledReason} onTyping={noteActivity} onPickDraft={pickDraft} /> : null}
          </section>
          {workspaceRoute ? (
            <div
              className="resize-handle right-sidebar-resize"
              id="right-sidebar-resize"
              role="separator"
              tabIndex={workspaceShellPendingAuth || narrow || rightCollapsed ? -1 : 0}
              aria-disabled={workspaceShellPendingAuth || narrow || rightCollapsed}
              aria-hidden={workspaceShellPendingAuth || narrow || rightCollapsed}
              aria-label="拖拽调整右侧 HWPOD 看板宽度"
              aria-controls="hwpod-node-sidebar"
              aria-orientation="vertical"
              aria-valuemin={rightResize.bounds.min}
              aria-valuemax={rightResize.bounds.max}
              aria-valuenow={rightResize.ariaValueNow}
              aria-valuetext={rightResize.ariaValueText}
              title="拖拽调整右侧 HWPOD 看板宽度；用左右方向键微调，Home/End 到最小或最大。"
              onPointerDown={rightResize.onPointerDown}
              onPointerMove={rightResize.onPointerMove}
              onPointerUp={rightResize.onPointerUp}
              onPointerCancel={rightResize.onPointerCancel}
              onKeyDown={rightResize.onKeyDown}
            />
          ) : null}
          {workspaceRoute ? <HwpodNodeOpsSidebar live={store.state.live} collapsed={rightCollapsed} /> : null}
        </div>
      </section>
      {workspaceShellPendingAuth ? <div className="workbench-auth-overlay" id="auth-loading-shell" role="status" aria-live="polite" aria-busy="true"><span className="workbench-auth-status">正在检查登录状态</span></div> : null}
    </main>
  );
}

function copyTextToClipboard(value: string): void {
  if (!value) return;
  const clipboard = typeof navigator !== "undefined" ? navigator.clipboard : null;
  if (clipboard?.writeText) {
    void clipboard.writeText(value).catch(() => fallbackCopyText(value));
    return;
  }
  fallbackCopyText(value);
}

function fallbackCopyText(value: string): void {
  if (typeof document === "undefined") return;
  const node = document.createElement("textarea");
  node.value = value;
  node.setAttribute("readonly", "");
  node.style.position = "fixed";
  node.style.left = "-9999px";
  node.style.top = "0";
  document.body.appendChild(node);
  node.select();
  try { document.execCommand("copy"); } catch { /* ignore clipboard fallback failures */ }
  node.remove();
}

function StatePill({ tone, children }: { tone: "pending" | "source"; children: string }): ReactElement {
  return <span className={`workspace-topbar-pill tone-${tone}`}>{children}</span>;
}

function useMatchMedia(query: string): boolean {
  const [match, setMatch] = useState<boolean>(() => typeof window !== "undefined" && window.matchMedia(query).matches);
  useEffect(() => {
    if (typeof window === "undefined") return;
    const media = window.matchMedia(query);
    const listener = (event: MediaQueryListEvent): void => setMatch(event.matches);
    setMatch(media.matches);
    media.addEventListener("change", listener);
    return () => media.removeEventListener("change", listener);
  }, [query]);
  return match;
}

function AuthLoadingShell(): ReactElement {
  return (
    <section className="login-shell auth-loading-shell" id="auth-loading-shell" aria-live="polite" aria-busy="true">
      <div className="login-panel auth-loading-panel">
        <p className="eyebrow">HWLAB</p>
        <h1>正在检查登录状态</h1>
        <p>正在读取服务器会话。</p>
      </div>
    </section>
  );
}

function DeferredRouteView({ children }: { children: ReactNode }): ReactElement {
  return <Suspense fallback={<RouteLoadingView />}>{children}</Suspense>;
}

function RouteLoadingView(): ReactElement {
  return (
    <section className="view route-loading-view" id="route-loading" aria-live="polite" aria-busy="true">
      <div className="workspace-panel route-loading-panel"><div className="panel-title-row"><div><p className="eyebrow">HWLAB</p><h2>正在加载</h2></div><span className="state-tag tone-source">准备中</span></div></div>
    </section>
  );
}

function HelpView({ help }: { help: string }): ReactElement {
  return (
    <section className="view help-view" id="help" data-view="help" aria-labelledby="help-title">
      <div className="workspace-panel help-panel"><div className="panel-title-row"><div><p className="eyebrow">内部说明</p><h2 id="help-title">使用说明</h2></div><span className="state-tag tone-source" id="help-status">已就绪</span></div><pre id="help-content" className="help-content" aria-live="polite">{help}</pre></div>
    </section>
  );
}

function routeFromLocation(): RouteId {
  const hash = window.location.hash.replace(/^#\/?/u, "");
  if (hash === "performance" || hash === "skills" || hash === "management" || hash === "access" || hash === "gate" || hash === "help" || hash === "settings" || hash === "workspace") return hash;
  const path = window.location.pathname.replace(/\/+$/u, "") || "/";
  if (path === "/help") return "help";
  if (path === "/performance" || path === "/ops/performance") return "performance";
  if (path === "/skills") return "skills";
  if (path === "/management" || path === "/admin/provider-profiles") return "management";
  if (path === "/access" || path === "/admin/access") return "access";
  if (path === "/gate" || path === "/diagnostics/gate") return "gate";
  return "workspace";
}
