// [nexus] Replacement onboarding wizard — 4-step flow: hardware detection, mode selection, provider selection, root directory
// Exports `OnboardingWizard` to match the named import in App.tsx.
// Wired via Vite alias: all imports of ./components/OnboardingWizard are
// redirected here at build time; the original file is preserved for upstream rebase.

import { useState, useEffect } from "react";
import { useLocation, useNavigate, useParams } from "@/lib/router";
import { VOCAB } from "@paperclipai/branding";
import { useQueryClient } from "@tanstack/react-query";
import { useCompany } from "../context/CompanyContext";
import { useDialog } from "../context/DialogContext";
import { companiesApi } from "../api/companies";
import { agentsApi } from "../api/agents";
import { puterProxyApi } from "../api/puter-proxy";
import { queryKeys } from "../lib/queryKeys";
import { resolveRouteOnboardingOptions } from "../lib/onboarding-route";
import { Dialog, DialogPortal } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { cn } from "../lib/utils";
import { ModeSelector } from "./onboarding/ModeSelector";
import { HardwareSummaryStep } from "./onboarding/HardwareSummaryStep";
import { ProviderSelectionStep } from "./onboarding/ProviderSelectionStep";
import { useHardwareInfo } from "../hooks/useHardwareInfo";
import { updateNexusSettings, type NexusMode } from "../api/hardware";

// [nexus] 4-step onboarding wizard: hardware detection → mode selection → provider selection → root directory
export function OnboardingWizard() {
  const { onboardingOpen, onboardingOptions, closeOnboarding } = useDialog();
  const { companies, setSelectedCompanyId, loading: companiesLoading } = useCompany();
  const queryClient = useQueryClient();
  const navigate = useNavigate();
  const location = useLocation();
  const { companyPrefix } = useParams<{ companyPrefix?: string }>();
  const [routeDismissed, setRouteDismissed] = useState(false);

  // Preserve wizard-show detection logic from the original OnboardingWizard
  const routeOnboardingOptions =
    companyPrefix && companiesLoading
      ? null
      : resolveRouteOnboardingOptions({
          pathname: location.pathname,
          companyPrefix,
          companies,
        });

  const effectiveOnboardingOpen =
    onboardingOpen || (routeOnboardingOptions !== null && !routeDismissed);

  useEffect(() => {
    setRouteDismissed(false);
  }, [location.pathname]);

  // Step state: 1 = hardware detection, 2 = mode selection, 3 = provider selection, 4 = root directory
  const [step, setStep] = useState(1);

  // Mode state: "both" pre-selected per UI-SPEC
  const [selectedMode, setSelectedMode] = useState<NexusMode>("both");

  // [nexus] Provider credentials — captured in React state for post-company-creation submission
  const [puterToken, setPuterToken] = useState<string | null>(null);
  const [googleOAuthStateId, setGoogleOAuthStateId] = useState<string | null>(null);
  const [apiKeyData, setApiKeyData] = useState<{ provider: string; apiKey: string } | null>(null);

  // Form state
  const [rootDir, setRootDir] = useState("");
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  // [nexus] Hardware detection — only fetch when wizard is open
  const { data: hardwareInfo, isLoading: hwLoading, isError: hwError } = useHardwareInfo(effectiveOnboardingOpen);

  // [nexus] Adapter detection state — probe for adapters when wizard opens
  const [defaultAdapter, setDefaultAdapter] = useState<"claude_local" | "hermes_local">("claude_local");
  const [probing, setProbing] = useState(false);
  const [detectedAdapters, setDetectedAdapters] = useState<Record<string, boolean>>({});

  // Reset form when wizard closes
  useEffect(() => {
    if (!effectiveOnboardingOpen) {
      setRootDir("");
      setError(null);
      setLoading(false);
      setStep(1);
      setSelectedMode("both");
      setPuterToken(null);
      setGoogleOAuthStateId(null);
      setApiKeyData(null);
    }
  }, [effectiveOnboardingOpen]);

  // [nexus] Probe for adapter availability when wizard opens (parallel, fire-and-forget)
  useEffect(() => {
    if (!effectiveOnboardingOpen) return;
    setProbing(true);

    const probes = Promise.all([
      agentsApi.probeAdapter("hermes_local").catch(() => ({ available: false, status: "error" })),
      agentsApi.probeAdapter("claude_local").catch(() => ({ available: false, status: "error" })),
      agentsApi.probeAdapter("openclaw_gateway").catch(() => ({ available: false, status: "error" })),
    ]);

    probes.then(([hermes, claude, openclaw]) => {
      const detected: Record<string, boolean> = {
        hermes_local: hermes.available,
        claude_local: claude.available,
        openclaw_gateway: openclaw.available,
      };
      setDetectedAdapters(detected);
      if (hermes.available) setDefaultAdapter("hermes_local");
    }).catch(() => {}).finally(() => setProbing(false));
  }, [effectiveOnboardingOpen]);

  function handleClose() {
    setRouteDismissed(true);
    closeOnboarding();
  }

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    if (defaultAdapter === "claude_local" && !rootDir.trim()) return;

    setLoading(true);
    setError(null);

    try {
      // Step 1: Create workspace (company) named after VOCAB.appName
      const company = await companiesApi.create({ name: VOCAB.appName });
      setSelectedCompanyId(company.id);
      queryClient.invalidateQueries({ queryKey: queryKeys.companies.all });

      // [nexus] hermes_local doesn't require a cwd; directory is optional
      const baseAdapterConfig = defaultAdapter === "hermes_local"
        ? (rootDir.trim() ? { cwd: rootDir.trim() } : {})
        : { cwd: rootDir.trim() };

      // [nexus] Hermes agents need a promptTemplate so they follow the Nexus heartbeat
      // workflow. The server's ensureDefaultInstructionsBundle will materialize this as
      // AGENTS.md alongside the full role bundle (HEARTBEAT.md, SOUL.md, TOOLS.md).
      const hermesPromptTemplate = [
        `You are "{{agentName}}", an AI agent managed by ${VOCAB.appName}.`,
        "",
        "Your identity:",
        "  Agent ID: {{agentId}}",
        "  Company ID: {{companyId}}",
        "  API Base: {{paperclipApiUrl}}",
        "  Run ID: {{runId}}",
        "",
        "IMPORTANT: Use the `terminal` tool with `curl` for ALL API calls.",
        'IMPORTANT: Always include `-H "X-Paperclip-Run-Id: {{runId}}"` on API calls that modify data.',
        "",
        "Before starting any task:",
        "1. Call `GET {{paperclipApiUrl}}/api/agents/me` to retrieve your managed instructions",
        "2. Follow the HEARTBEAT.md workflow from your instructions",
        "3. Use TOOLS.md for available API endpoints",
        "",
        "{{#taskId}}",
        "Assigned task: {{taskId}} - {{taskTitle}}",
        "{{/taskId}}",
      ].join("\n");

      const adapterConfig = defaultAdapter === "hermes_local"
        ? { ...baseAdapterConfig, promptTemplate: hermesPromptTemplate, persistSession: true }
        : baseAdapterConfig;

      const runtimeConfig = {
        heartbeat: {
          enabled: true,
          intervalSec: 3600,
          wakeOnDemand: true,
          cooldownSec: 10,
          maxConcurrentRuns: 1,
        },
      };

      // Step 2: Create PM agent with role "ceo" for elevated permissions
      await agentsApi.create(company.id, {
        name: "Project Manager",
        role: "ceo",
        adapterType: defaultAdapter,
        adapterConfig,
        runtimeConfig,
      });

      // Step 3: Create Engineer agent
      await agentsApi.create(company.id, {
        name: "Engineer",
        role: "engineer",
        adapterType: defaultAdapter,
        adapterConfig,
        runtimeConfig,
      });

      queryClient.invalidateQueries({
        queryKey: queryKeys.agents.list(company.id),
      });

      // Persist selected mode — non-blocking
      try {
        await updateNexusSettings({ mode: selectedMode });
      } catch {
        // Non-blocking — mode defaults to "both" if save fails
      }

      // [nexus] Store collected provider credentials after company creation — all non-blocking
      if (puterToken) {
        await puterProxyApi.storeToken(company.id, puterToken).catch(() => {});
      }
      if (googleOAuthStateId) {
        // Claim Google OAuth tokens for this company
        await puterProxyApi.claimGoogleTokens(googleOAuthStateId, company.id).catch(() => {});
      }
      if (apiKeyData) {
        await puterProxyApi.storeApiKey(company.id, apiKeyData.provider, apiKeyData.apiKey).catch(() => {});
      }

      // Navigate to dashboard — not an issue detail page
      closeOnboarding();
      navigate(`/${company.issuePrefix}/dashboard`);
    } catch (err) {
      setError(err instanceof Error ? err.message : "Setup failed. Please try again.");
      setLoading(false);
    }
  }

  if (!effectiveOnboardingOpen) return null;

  return (
    <DialogPortal>
      <div className="fixed inset-0 z-50 flex items-center justify-center">
        {/* Backdrop */}
        <div
          className="absolute inset-0 bg-black/60 backdrop-blur-sm"
          onClick={handleClose}
        />

        {/* Card */}
        <div
          className={cn(
            "relative z-10 w-full max-w-md mx-4 rounded-xl border bg-card text-card-foreground shadow-2xl",
            "p-8 flex flex-col gap-6"
          )}
        >
          {/* Step indicator */}
          <p className="text-xs text-muted-foreground text-center">Step {step} of 4</p>

          {/* Step 1 — Hardware Detection */}
          {step === 1 && (
            <>
              <div className="flex flex-col gap-2 text-center">
                <h1 className="text-2xl font-semibold tracking-tight">
                  {hwLoading ? "Detecting your hardware..." : "Your hardware"}
                </h1>
              </div>

              <HardwareSummaryStep
                hardwareInfo={hardwareInfo}
                isLoading={hwLoading}
                isError={hwError}
              />

              <Button
                type="button"
                onClick={() => setStep(2)}
                className="w-full"
              >
                Continue
              </Button>
            </>
          )}

          {/* Step 2 — Mode Selection */}
          {step === 2 && (
            <>
              <div className="flex flex-col gap-2 text-center">
                <h1 className="text-2xl font-semibold tracking-tight">
                  Choose your mode
                </h1>
              </div>

              <ModeSelector value={selectedMode} onChange={setSelectedMode} />

              <div className="flex flex-col gap-2">
                <Button
                  type="button"
                  onClick={() => setStep(3)}
                  className="w-full"
                >
                  Continue
                </Button>
                <Button
                  type="button"
                  variant="ghost"
                  onClick={() => setStep(1)}
                  className="w-full"
                >
                  Back
                </Button>
              </div>
            </>
          )}

          {/* Step 3 — Provider Selection (NEW) */}
          {step === 3 && (
            <>
              <div className="flex flex-col gap-2 text-center">
                <h1 className="text-2xl font-semibold tracking-tight">
                  Choose a provider
                </h1>
                <p className="text-sm text-muted-foreground">
                  No API keys needed for the zero-config path.
                </p>
              </div>

              <ProviderSelectionStep
                onPuterToken={setPuterToken}
                onGoogleOAuthState={setGoogleOAuthStateId}
                onApiKey={(provider, apiKey) => setApiKeyData({ provider, apiKey })}
                onSkip={() => setStep(4)}
                onContinue={() => setStep(4)}
                detectedAdapters={detectedAdapters}
              />

              <Button
                type="button"
                variant="ghost"
                onClick={() => setStep(2)}
                className="w-full"
              >
                Back
              </Button>
            </>
          )}

          {/* Step 4 — Root Directory (was step 3) */}
          {step === 4 && (
            <>
              {/* Header */}
              <div className="flex flex-col gap-2 text-center">
                <h1 className="text-2xl font-semibold tracking-tight">
                  Welcome to {VOCAB.appName}
                </h1>
                <p className="text-sm text-muted-foreground">
                  {defaultAdapter === "hermes_local"
                    ? `${VOCAB.appName} will set up a local AI workspace with a ${VOCAB.ceo.toLowerCase()}, engineer, and generalist — no API key needed.`
                    : `Choose a project root directory. ${VOCAB.appName} will set up a ${VOCAB.ceo.toLowerCase()} and engineer to start working.`}
                </p>
              </div>

              {/* Form */}
              <form onSubmit={handleSubmit} className="flex flex-col gap-4">
                <div className="flex flex-col gap-2">
                  <label
                    htmlFor="nexus-root-dir"
                    className="text-sm font-medium leading-none"
                  >
                    Project root directory{defaultAdapter === "hermes_local" ? " (optional)" : ""}
                  </label>
                  <Input
                    id="nexus-root-dir"
                    type="text"
                    placeholder="~/projects/my-project"
                    value={rootDir}
                    onChange={(e) => setRootDir(e.target.value)}
                    disabled={loading}
                    autoFocus
                    autoComplete="off"
                    className="font-mono text-sm"
                  />
                </div>

                {error && (
                  <p className="text-sm text-destructive bg-destructive/10 rounded-md px-3 py-2">
                    {error}
                  </p>
                )}

                <Button
                  type="submit"
                  disabled={loading || probing || (defaultAdapter === "claude_local" && !rootDir.trim())}
                  className="w-full"
                >
                  {loading ? (
                    <span className="flex items-center gap-2">
                      <svg
                        className="h-4 w-4 animate-spin"
                        viewBox="0 0 24 24"
                        fill="none"
                        aria-hidden="true"
                      >
                        <circle
                          className="opacity-25"
                          cx="12"
                          cy="12"
                          r="10"
                          stroke="currentColor"
                          strokeWidth="4"
                        />
                        <path
                          className="opacity-75"
                          fill="currentColor"
                          d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
                        />
                      </svg>
                      Setting up…
                    </span>
                  ) : (
                    "Get Started"
                  )}
                </Button>

                <Button
                  type="button"
                  variant="ghost"
                  onClick={() => setStep(3)}
                  className="w-full"
                  disabled={loading}
                >
                  Back
                </Button>
              </form>
            </>
          )}
        </div>
      </div>
    </DialogPortal>
  );
}
