import { useCallback, useEffect, useMemo, useState } from "react";

import { api } from "../services/api/client";
import { DEFAULT_WORKBENCH_PROJECT_ID, normalizeWorkbenchProjectId } from "../state/constants";
import type { AuthSession, AuthState, AuthUser, WorkspaceRecord } from "../types/domain";
import type { WorkbenchEarlyWorkspaceBootstrap } from "../types/config";
import { asRecord, nonEmptyString } from "../utils";

const DEFAULT_USERNAME = "admin";
const DEFAULT_PASSWORD = "hwlab2026";

export interface UseAuthResult {
  authState: AuthState;
  session: AuthSession | null;
  error: string | null;
  login(username: string, password: string): Promise<void>;
  logout(): Promise<void>;
}

export function useAuth(projectId: string = DEFAULT_WORKBENCH_PROJECT_ID): UseAuthResult {
  const [authState, setAuthState] = useState<AuthState>("checking");
  const [session, setSession] = useState<AuthSession | null>(null);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    let canceled = false;
    async function run(): Promise<void> {
      const config = window.HWLAB_CLOUD_WEB_CONFIG?.auth;
      const mode = config?.mode ?? "auto";
      const current = mode === "auto" ? await resolveWorkspaceBootstrap(projectId) : await api.session();
      if (canceled) return;
      if (current.ok && current.data?.authenticated === true) {
        const workspace = workspaceFromPayload(current.data);
        if (workspace) {
          window.HWLAB_CLOUD_WEB_WORKSPACE_BOOTSTRAP = { projectId: payloadProjectId(current.data, workspace, projectId), workspace };
        }
        const next = sessionFromPayload(current.data);
        setSession(next);
        setAuthState("authenticated");
        return;
      }
      const username = nonEmptyString(config?.username) ?? DEFAULT_USERNAME;
      const password = nonEmptyString(config?.password) ?? DEFAULT_PASSWORD;
      if (mode === "auto" && current.status === 404) {
        const autoLogin = await api.login(username, password);
        if (canceled) return;
        if (autoLogin.ok && autoLogin.data?.authenticated === true) {
          setSession(sessionFromPayload(autoLogin.data));
          setAuthState("authenticated");
          return;
        }
      }
      setAuthState("login");
    }
    void run();
    return () => {
      canceled = true;
    };
  }, [projectId]);

  useEffect(() => {
    document.body.dataset.authState = authState;
  }, [authState]);

  const login = useCallback(async (username: string, password: string) => {
    setError(null);
    const response = await api.login(username.trim(), password);
    if (!response.ok || response.data?.authenticated !== true) {
      setError("账号或密码不正确，请重新输入。");
      setAuthState("login");
      return;
    }
    setSession(sessionFromPayload(response.data));
    setAuthState("authenticated");
  }, []);

  const logout = useCallback(async () => {
    await api.logout();
    setSession(null);
    setAuthState("login");
  }, []);

  return useMemo(() => ({ authState, session, error, login, logout }), [authState, session, error, login, logout]);
}

async function resolveWorkspaceBootstrap(projectId: string): ReturnType<typeof api.workspaceBootstrap> {
  const normalizedProjectId = normalizeWorkbenchProjectId(projectId) ?? DEFAULT_WORKBENCH_PROJECT_ID;
  const early = await consumeEarlyWorkspaceBootstrap(normalizedProjectId);
  if (early) return early;
  return api.workspaceBootstrap(normalizedProjectId);
}

async function consumeEarlyWorkspaceBootstrap(projectId: string): Promise<Awaited<ReturnType<typeof api.workspaceBootstrap>> | null> {
  const pending = window.HWLAB_CLOUD_WEB_EARLY_WORKSPACE_BOOTSTRAP;
  if (!pending) return null;
  window.HWLAB_CLOUD_WEB_EARLY_WORKSPACE_BOOTSTRAP = undefined;
  const early = await pending;
  if ((normalizeWorkbenchProjectId(early.projectId) ?? DEFAULT_WORKBENCH_PROJECT_ID) !== projectId) return null;
  return normalizeEarlyWorkspaceBootstrap(early);
}

function normalizeEarlyWorkspaceBootstrap(early: WorkbenchEarlyWorkspaceBootstrap): Awaited<ReturnType<typeof api.workspaceBootstrap>> {
  const data = early.data ?? null;
  return {
    ok: early.ok === true,
    status: Number.isFinite(Number(early.status)) ? Number(early.status) : 0,
    data,
    error: early.ok === true ? null : early.error ?? `HTTP ${early.status ?? 0}`
  };
}

function workspaceFromPayload(payload: unknown): WorkspaceRecord | null {
  const record = asRecord(payload);
  const workspace = asRecord(record?.workspace);
  return typeof workspace?.workspaceId === "string" && workspace.workspaceId.trim() ? workspace as unknown as WorkspaceRecord : null;
}

function payloadProjectId(payload: unknown, workspace: WorkspaceRecord | null, fallback: string): string {
  const record = asRecord(payload);
  return normalizeWorkbenchProjectId(record?.projectId)
    ?? normalizeWorkbenchProjectId(workspace?.projectId)
    ?? normalizeWorkbenchProjectId(workspace?.workspace?.projectId)
    ?? normalizeWorkbenchProjectId(fallback)
    ?? DEFAULT_WORKBENCH_PROJECT_ID;
}

function sessionFromPayload(payload: { authenticated?: boolean; user?: unknown; actor?: unknown; expiresAt?: string }): AuthSession {
  return {
    authenticated: payload.authenticated === true,
    mode: "server",
    user: userFromUnknown(payload.user),
    actor: userFromUnknown(payload.actor),
    expiresAt: nonEmptyString(payload.expiresAt)
  };
}

function userFromUnknown(value: unknown): AuthUser | undefined {
  const record = asRecord(value);
  if (!record) return undefined;
  return {
    id: nonEmptyString(record.id) ?? undefined,
    username: nonEmptyString(record.username) ?? undefined,
    name: nonEmptyString(record.name) ?? undefined
  };
}
