"use client";

/**
 * CloudOnboardingWizard — shared 5-step federated-first wizard.
 *
 * Same component drives AWS / Azure / GCP / Cloudflare onboarding;
 * the cloud-specific shape comes from `schemas.ts`. Steps:
 *
 *   1. Choose cloud + auth method (locked to the federated default).
 *   2. Bootstrap artifacts — server returns trust policy / WIF /
 *      federated-credential JSON / scoped-token-template + 1-click
 *      IaC link. Operator applies on the customer's cloud.
 *   3. Validate identity — read-only caller-identity probe.
 *   4. Validate permissions — read-only dry-run permission preview.
 *   5. Connect — persists the resolved record.
 *
 * The wizard never echoes the raw token / federated-credential JSON /
 * trust-policy back to the operator after submission; only metadata
 * (caller ARN, subscription id, project id, token id, audit_run_id)
 * crosses the BFF boundary.
 */
import { useMutation } from "@tanstack/react-query";
import { useMemo, useState } from "react";

import {
  type AdminApiError,
  adminApi,
  type CloudBootstrapResult,
  type CloudConnectResult,
  type CloudEnumerateResult,
  type CloudIdentityResult,
  type CloudKind,
  type CloudPermissionResult,
} from "@/lib/api/client";

import { CLOUD_SCHEMAS, type CloudSchema, type FieldSchema } from "./schemas";

export type CloudOnboardingWizardProps = {
  cloudKind: CloudKind;
  orgId: string;
  onConnected?: () => void;
};

type Step = 1 | 2 | 3 | 4 | 5;

type FormState = Record<string, string>;

export function CloudOnboardingWizard({
  cloudKind,
  orgId,
  onConnected,
}: CloudOnboardingWizardProps) {
  const schema = CLOUD_SCHEMAS[cloudKind];
  const [step, setStep] = useState<Step>(1);
  const [form, setForm] = useState<FormState>({});
  const [validationError, setValidationError] = useState<string | null>(null);

  const bootstrap = useMutation<
    CloudBootstrapResult,
    AdminApiError | Error,
    Record<string, unknown>
  >({
    mutationFn: (body) => adminApi.cloudBootstrap(orgId, cloudKind, body),
    onSuccess: () => {
      setValidationError(null);
      setStep(3);
    },
    onError: (err) => setValidationError(err.message),
  });

  const identity = useMutation<
    CloudIdentityResult,
    AdminApiError | Error,
    Record<string, unknown>
  >({
    mutationFn: (body) => adminApi.cloudValidateIdentity(orgId, cloudKind, body),
    onError: (err) => setValidationError(err.message),
  });

  const permissions = useMutation<
    CloudPermissionResult,
    AdminApiError | Error,
    Record<string, unknown>
  >({
    mutationFn: (body) =>
      adminApi.cloudValidatePermissions(orgId, cloudKind, body),
    onError: (err) => setValidationError(err.message),
  });

  const enumerateMut = useMutation<
    CloudEnumerateResult,
    AdminApiError | Error,
    Record<string, unknown>
  >({
    mutationFn: (body) => adminApi.cloudEnumerate(orgId, cloudKind, body),
    onError: (err) => setValidationError(err.message),
  });

  const connect = useMutation<
    CloudConnectResult,
    AdminApiError | Error,
    Record<string, unknown>
  >({
    mutationFn: (body) => adminApi.cloudConnect(orgId, cloudKind, body),
    onSuccess: () => {
      setValidationError(null);
      onConnected?.();
    },
    onError: (err) => setValidationError(err.message),
  });

  const bootstrapBody = useMemo(() => onlyBootstrapFields(schema, form), [
    schema,
    form,
  ]);
  const validateBody = useMemo(() => onlyStepFields(schema, form, "validate"), [
    schema,
    form,
  ]);
  const connectBody = useMemo(() => onlyStepFields(schema, form, "connect"), [
    schema,
    form,
  ]);

  function onBootstrap() {
    if (!requireAll(schema.bootstrapFields, form, setValidationError)) return;
    bootstrap.mutate(bootstrapBody);
  }

  function onValidateIdentity() {
    if (!requireValidationInputs(schema, form, setValidationError)) return;
    identity.mutate(validateBody);
  }

  function onValidatePermissions() {
    if (!identity.data?.ok) {
      setValidationError("Validate identity first.");
      return;
    }
    permissions.mutate(validateBody);
  }

  function onEnumerate() {
    enumerateMut.mutate(validateBody);
  }

  function onConnect() {
    if (!identity.data?.ok) {
      setValidationError("Validate identity before connecting.");
      return;
    }
    if (!requireConnectInputs(schema, form, setValidationError)) return;
    connect.mutate({ ...connectBody, ...validateBody });
  }

  return (
    <section className="space-y-4 rounded-lg border bg-card p-6">
      <header className="space-y-1">
        <h3 className="text-lg font-medium">{schema.label} cloud connection</h3>
        <p className="text-sm text-muted-foreground">
          Federated-first onboarding for{" "}
          <code className="rounded bg-slate-100 px-1 py-0.5 text-xs">
            {orgId}
          </code>
          . {schema.description}
        </p>
        <p className="text-xs text-muted-foreground">
          Auth method:{" "}
          <span className="font-semibold">{schema.authMethodLabel}</span> ·{" "}
          <a
            className="underline-offset-2 hover:underline"
            href={schema.docsUrl}
            target="_blank"
            rel="noreferrer"
          >
            Why this auth method?
          </a>
        </p>
      </header>

      <ol className="flex flex-wrap items-center gap-3 text-xs">
        {[
          ["1", "Choose"],
          ["2", "Bootstrap"],
          ["3", "Identity"],
          ["4", "Permissions"],
          ["5", "Connect"],
        ].map(([num, label]) => {
          const active = String(step) === num;
          const done = Number(num) < step;
          return (
            <li
              key={num}
              className={`flex items-center gap-2 rounded-full border px-2 py-1 ${
                active
                  ? "border-slate-900 bg-slate-900 text-white"
                  : done
                    ? "border-emerald-300 bg-emerald-50 text-emerald-900"
                    : "border-slate-200 text-slate-500"
              }`}
            >
              <span className="font-mono">{num}</span>
              <span>{label}</span>
            </li>
          );
        })}
      </ol>

      {step === 1 ? <Step1 schema={schema} onNext={() => setStep(2)} /> : null}

      {step === 2 ? (
        <Step2
          schema={schema}
          form={form}
          onChange={setForm}
          onBack={() => setStep(1)}
          onSubmit={onBootstrap}
          bootstrapResult={bootstrap.data}
          isLoading={bootstrap.isPending}
        />
      ) : null}

      {step === 3 ? (
        <Step3
          schema={schema}
          form={form}
          onChange={setForm}
          onBack={() => setStep(2)}
          onSubmit={onValidateIdentity}
          identityResult={identity.data}
          isLoading={identity.isPending}
          onNext={() => setStep(4)}
        />
      ) : null}

      {step === 4 ? (
        <Step4
          permissionsResult={permissions.data}
          enumerateResult={enumerateMut.data}
          isPermissionsLoading={permissions.isPending}
          isEnumerateLoading={enumerateMut.isPending}
          onValidate={onValidatePermissions}
          onEnumerate={onEnumerate}
          onBack={() => setStep(3)}
          onNext={() => setStep(5)}
        />
      ) : null}

      {step === 5 ? (
        <Step5
          schema={schema}
          form={form}
          onChange={setForm}
          onBack={() => setStep(4)}
          onSubmit={onConnect}
          connectResult={connect.data}
          isLoading={connect.isPending}
        />
      ) : null}

      {validationError ? (
        <p className="text-sm text-red-600">{validationError}</p>
      ) : null}
    </section>
  );
}

// ---------------------------------------------------------------------------
// Step components
// ---------------------------------------------------------------------------

function Step1({
  schema,
  onNext,
}: {
  schema: CloudSchema;
  onNext: () => void;
}) {
  return (
    <div className="space-y-3">
      <div className="rounded border bg-slate-50 p-3 text-sm">
        <div className="font-semibold">Auth method: {schema.authMethodLabel}</div>
        <p className="mt-1 text-xs text-slate-600">{schema.description}</p>
      </div>
      <div className="flex justify-end">
        <button
          type="button"
          className="rounded-md bg-slate-900 px-4 py-2 text-sm font-semibold text-white"
          onClick={onNext}
        >
          Generate bootstrap artifacts
        </button>
      </div>
    </div>
  );
}

function Step2({
  schema,
  form,
  onChange,
  onBack,
  onSubmit,
  bootstrapResult,
  isLoading,
}: {
  schema: CloudSchema;
  form: FormState;
  onChange: (form: FormState) => void;
  onBack: () => void;
  onSubmit: () => void;
  bootstrapResult: CloudBootstrapResult | undefined;
  isLoading: boolean;
}) {
  return (
    <div className="space-y-3">
      {schema.bootstrapFields.length > 0 ? (
        <FieldGrid
          schemaFields={schema.bootstrapFields}
          form={form}
          onChange={onChange}
        />
      ) : (
        <p className="text-xs text-muted-foreground">
          No additional inputs required for the bootstrap step on {schema.label}.
        </p>
      )}
      {bootstrapResult ? (
        <BootstrapPreview result={bootstrapResult} />
      ) : null}
      <div className="flex justify-between">
        <button
          type="button"
          className="rounded-md border px-4 py-2 text-sm"
          onClick={onBack}
        >
          Back
        </button>
        <button
          type="button"
          disabled={isLoading}
          className="rounded-md bg-slate-900 px-4 py-2 text-sm font-semibold text-white disabled:opacity-50"
          onClick={onSubmit}
        >
          {isLoading ? "Generating…" : bootstrapResult ? "Continue" : "Generate"}
        </button>
      </div>
    </div>
  );
}

function Step3({
  schema,
  form,
  onChange,
  onBack,
  onSubmit,
  identityResult,
  isLoading,
  onNext,
}: {
  schema: CloudSchema;
  form: FormState;
  onChange: (form: FormState) => void;
  onBack: () => void;
  onSubmit: () => void;
  identityResult: CloudIdentityResult | undefined;
  isLoading: boolean;
  onNext: () => void;
}) {
  const fields = schema.validateFields.filter((f) =>
    (f.showOn ?? ["validate"]).includes("validate"),
  );
  return (
    <div className="space-y-3">
      <FieldGrid schemaFields={fields} form={form} onChange={onChange} />
      {identityResult ? (
        <IdentityPreview result={identityResult} />
      ) : null}
      <div className="flex justify-between">
        <button
          type="button"
          className="rounded-md border px-4 py-2 text-sm"
          onClick={onBack}
        >
          Back
        </button>
        <div className="flex gap-2">
          <button
            type="button"
            disabled={isLoading}
            className="rounded-md bg-slate-900 px-4 py-2 text-sm font-semibold text-white disabled:opacity-50"
            onClick={onSubmit}
          >
            {isLoading
              ? "Probing…"
              : identityResult
                ? "Re-run identity probe"
                : "Validate identity"}
          </button>
          <button
            type="button"
            disabled={!identityResult?.ok}
            className="rounded-md border bg-emerald-600 px-4 py-2 text-sm font-semibold text-white disabled:opacity-50"
            onClick={onNext}
          >
            Continue
          </button>
        </div>
      </div>
    </div>
  );
}

function Step4({
  permissionsResult,
  enumerateResult,
  isPermissionsLoading,
  isEnumerateLoading,
  onValidate,
  onEnumerate,
  onBack,
  onNext,
}: {
  permissionsResult: CloudPermissionResult | undefined;
  enumerateResult: CloudEnumerateResult | undefined;
  isPermissionsLoading: boolean;
  isEnumerateLoading: boolean;
  onValidate: () => void;
  onEnumerate: () => void;
  onBack: () => void;
  onNext: () => void;
}) {
  return (
    <div className="space-y-3">
      <div className="grid grid-cols-1 gap-3 md:grid-cols-2">
        <div className="rounded border bg-card p-3 text-sm">
          <div className="mb-2 flex items-center justify-between">
            <span className="font-semibold">Permissions preview</span>
            <button
              type="button"
              disabled={isPermissionsLoading}
              className="rounded-md bg-slate-900 px-3 py-1 text-xs font-semibold text-white disabled:opacity-50"
              onClick={onValidate}
            >
              {isPermissionsLoading ? "Checking…" : "Run check"}
            </button>
          </div>
          {permissionsResult ? (
            <PermissionPreview result={permissionsResult} />
          ) : (
            <p className="text-xs text-muted-foreground">
              No preview yet — run the dry-run check.
            </p>
          )}
        </div>
        <div className="rounded border bg-card p-3 text-sm">
          <div className="mb-2 flex items-center justify-between">
            <span className="font-semibold">Resource enumeration</span>
            <button
              type="button"
              disabled={isEnumerateLoading}
              className="rounded-md bg-slate-900 px-3 py-1 text-xs font-semibold text-white disabled:opacity-50"
              onClick={onEnumerate}
            >
              {isEnumerateLoading ? "Listing…" : "Enumerate"}
            </button>
          </div>
          {enumerateResult ? (
            <EnumeratePreview result={enumerateResult} />
          ) : (
            <p className="text-xs text-muted-foreground">
              No listing yet — enumerate to populate dropdowns.
            </p>
          )}
        </div>
      </div>
      <div className="flex justify-between">
        <button
          type="button"
          className="rounded-md border px-4 py-2 text-sm"
          onClick={onBack}
        >
          Back
        </button>
        <button
          type="button"
          disabled={!permissionsResult?.ok}
          className="rounded-md border bg-emerald-600 px-4 py-2 text-sm font-semibold text-white disabled:opacity-50"
          onClick={onNext}
        >
          Continue to save
        </button>
      </div>
    </div>
  );
}

function Step5({
  schema,
  form,
  onChange,
  onBack,
  onSubmit,
  connectResult,
  isLoading,
}: {
  schema: CloudSchema;
  form: FormState;
  onChange: (form: FormState) => void;
  onBack: () => void;
  onSubmit: () => void;
  connectResult: CloudConnectResult | undefined;
  isLoading: boolean;
}) {
  const fields = schema.validateFields.filter((f) =>
    (f.showOn ?? []).includes("connect"),
  );
  return (
    <div className="space-y-3">
      <FieldGrid schemaFields={fields} form={form} onChange={onChange} />
      {connectResult ? (
        <div className="rounded border bg-green-50 p-3 text-xs text-green-900">
          <div className="font-semibold">Connected</div>
          <dl className="mt-2 grid grid-cols-[140px_1fr] gap-1 font-mono">
            <dt>credential_key</dt>
            <dd>{connectResult.integration.credential_key}</dd>
            <dt>namespace</dt>
            <dd>{connectResult.integration.namespace}</dd>
            <dt>status</dt>
            <dd>{connectResult.integration.status}</dd>
            <dt>audit_run_id</dt>
            <dd>{connectResult.audit_run_id ?? "—"}</dd>
          </dl>
        </div>
      ) : null}
      <div className="flex justify-between">
        <button
          type="button"
          className="rounded-md border px-4 py-2 text-sm"
          onClick={onBack}
        >
          Back
        </button>
        <button
          type="button"
          disabled={isLoading}
          className="rounded-md bg-slate-900 px-4 py-2 text-sm font-semibold text-white disabled:opacity-50"
          onClick={onSubmit}
        >
          {isLoading ? "Saving…" : connectResult ? "Save again" : "Save connection"}
        </button>
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Preview blocks
// ---------------------------------------------------------------------------

function BootstrapPreview({ result }: { result: CloudBootstrapResult }) {
  return (
    <div className="space-y-3 rounded border bg-slate-50 p-3 text-xs">
      <div>
        <div className="font-semibold">Next step</div>
        <p className="mt-1 text-slate-700">{result.next_step}</p>
      </div>
      {result.external_id ? (
        <div>
          <div className="font-semibold">External id</div>
          <code className="break-all font-mono text-[11px]">
            {result.external_id}
          </code>
        </div>
      ) : null}
      {Object.entries(result.templates).map(([name, body]) => (
        <details key={name} className="rounded border bg-white p-2">
          <summary className="cursor-pointer font-semibold">{name}</summary>
          <pre className="mt-2 max-h-44 overflow-auto whitespace-pre-wrap break-all">
            {body}
          </pre>
        </details>
      ))}
      {Object.entries(result.cli_commands).map(([name, cmd]) => (
        <details key={name} className="rounded border bg-white p-2">
          <summary className="cursor-pointer font-semibold">{name}</summary>
          <pre className="mt-2 max-h-32 overflow-auto whitespace-pre-wrap break-all">
            {cmd}
          </pre>
        </details>
      ))}
      {Object.entries(result.iac_links).length > 0 ? (
        <div>
          <div className="font-semibold">Quick links</div>
          <ul className="mt-1 space-y-1">
            {Object.entries(result.iac_links).map(([name, href]) => (
              <li key={name}>
                <a
                  className="text-blue-700 underline-offset-2 hover:underline"
                  href={href}
                  target="_blank"
                  rel="noreferrer"
                >
                  {name}
                </a>
              </li>
            ))}
          </ul>
        </div>
      ) : null}
    </div>
  );
}

function IdentityPreview({ result }: { result: CloudIdentityResult }) {
  return (
    <div
      className={`rounded border p-3 text-xs ${
        result.ok
          ? "border-emerald-200 bg-emerald-50 text-emerald-900"
          : "border-red-200 bg-red-50 text-red-900"
      }`}
    >
      <div className="font-semibold">
        Identity probe: {result.ok ? "ok" : "failed"}
      </div>
      {result.error ? <p className="mt-1">{result.error}</p> : null}
      <dl className="mt-2 grid grid-cols-[140px_1fr] gap-1 font-mono">
        {Object.entries(result.identity).map(([k, v]) => (
          <Fragment key={k}>
            <dt>{k}</dt>
            <dd>{String(v ?? "—")}</dd>
          </Fragment>
        ))}
      </dl>
    </div>
  );
}

function PermissionPreview({ result }: { result: CloudPermissionResult }) {
  if (result.error) {
    return (
      <p className="text-xs text-red-700">Error: {result.error}</p>
    );
  }
  return (
    <div className="text-xs">
      <p className="mb-1">
        Status:{" "}
        <span className={result.ok ? "text-emerald-700" : "text-red-700"}>
          {result.ok ? "all required granted" : "missing required scopes"}
        </span>
      </p>
      {result.allowed.length > 0 ? (
        <p>
          <span className="font-semibold">Allowed:</span>{" "}
          {result.allowed.join(", ")}
        </p>
      ) : null}
      {result.denied.length > 0 ? (
        <p>
          <span className="font-semibold">Denied:</span>{" "}
          {result.denied.join(", ")}
        </p>
      ) : null}
      {result.missing_required.length > 0 ? (
        <p className="text-red-700">
          <span className="font-semibold">Missing required:</span>{" "}
          {result.missing_required.join(", ")}
        </p>
      ) : null}
    </div>
  );
}

function EnumeratePreview({ result }: { result: CloudEnumerateResult }) {
  if (result.error) {
    return <p className="text-xs text-red-700">Error: {result.error}</p>;
  }
  const entries = Object.entries(result.resources);
  if (entries.length === 0) {
    return <p className="text-xs text-muted-foreground">No resources listed.</p>;
  }
  return (
    <div className="space-y-2 text-xs">
      {entries.map(([group, items]) => (
        <div key={group}>
          <div className="font-semibold">
            {group} ({items.length})
          </div>
          <ul className="ml-3 list-disc">
            {items.slice(0, 5).map((item, idx) => (
              <li
                key={`${group}-${idx}`}
                className="break-all"
              >
                {JSON.stringify(item)}
              </li>
            ))}
            {items.length > 5 ? (
              <li className="text-muted-foreground">
                …and {items.length - 5} more
              </li>
            ) : null}
          </ul>
        </div>
      ))}
    </div>
  );
}

// ---------------------------------------------------------------------------
// Shared field helpers
// ---------------------------------------------------------------------------

function FieldGrid({
  schemaFields,
  form,
  onChange,
}: {
  schemaFields: FieldSchema[];
  form: FormState;
  onChange: (form: FormState) => void;
}) {
  if (schemaFields.length === 0) return null;
  return (
    <div className="grid grid-cols-1 gap-3 md:grid-cols-2">
      {schemaFields.map((field) => (
        <Field key={field.name} field={field} form={form} onChange={onChange} />
      ))}
    </div>
  );
}

function Field({
  field,
  form,
  onChange,
}: {
  field: FieldSchema;
  form: FormState;
  onChange: (form: FormState) => void;
}) {
  const value = form[field.name] ?? "";
  function setValue(next: string) {
    onChange({ ...form, [field.name]: next });
  }
  return (
    <label className="space-y-1">
      <div className="text-xs font-medium text-slate-600">
        {field.label}
        {field.required ? <span className="text-red-500"> *</span> : null}
      </div>
      {field.type === "select" ? (
        <select
          className="w-full rounded border px-3 py-2 text-sm"
          value={value}
          onChange={(e) => setValue(e.target.value)}
        >
          <option value="">(default)</option>
          {(field.options ?? []).map((opt) => (
            <option key={opt.value} value={opt.value}>
              {opt.label}
            </option>
          ))}
        </select>
      ) : field.type === "textarea" ? (
        <textarea
          className="min-h-20 w-full rounded border px-3 py-2 font-mono text-xs"
          placeholder={field.placeholder}
          value={value}
          onChange={(e) => setValue(e.target.value)}
        />
      ) : (
        <input
          className="w-full rounded border px-3 py-2 text-sm"
          placeholder={field.placeholder}
          value={value}
          onChange={(e) => setValue(e.target.value)}
        />
      )}
      {field.hint ? (
        <div className="text-[11px] text-muted-foreground">{field.hint}</div>
      ) : null}
    </label>
  );
}

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function onlyBootstrapFields(
  schema: CloudSchema,
  form: FormState,
): Record<string, unknown> {
  const out: Record<string, unknown> = {};
  for (const field of schema.bootstrapFields) {
    const value = form[field.name];
    if (value !== undefined && value !== "") {
      out[field.name] = field.name === "managed_policy_arns"
        ? value.split(",").map((s) => s.trim()).filter(Boolean)
        : value;
    }
  }
  return out;
}

function onlyStepFields(
  schema: CloudSchema,
  form: FormState,
  step: "validate" | "connect",
): Record<string, unknown> {
  const out: Record<string, unknown> = {};
  for (const field of schema.validateFields) {
    if (!(field.showOn ?? ["validate"]).includes(step)) continue;
    const value = form[field.name];
    if (value !== undefined && value !== "") {
      out[field.name] = value;
    }
  }
  return out;
}

function requireAll(
  fields: FieldSchema[],
  form: FormState,
  setError: (msg: string | null) => void,
): boolean {
  const missing = fields
    .filter((f) => f.required)
    .map((f) => f.name)
    .filter((name) => !form[name]);
  if (missing.length > 0) {
    setError(`Required: ${missing.join(", ")}`);
    return false;
  }
  setError(null);
  return true;
}

function requireValidationInputs(
  schema: CloudSchema,
  form: FormState,
  setError: (msg: string | null) => void,
): boolean {
  return requireAll(
    schema.validateFields.filter((f) =>
      (f.showOn ?? ["validate"]).includes("validate"),
    ),
    form,
    setError,
  );
}

function requireConnectInputs(
  schema: CloudSchema,
  form: FormState,
  setError: (msg: string | null) => void,
): boolean {
  return requireAll(
    schema.validateFields.filter((f) =>
      (f.showOn ?? []).includes("connect"),
    ),
    form,
    setError,
  );
}

// React Fragment helper — keeps the JSX clean.
function Fragment({
  children,
}: {
  // biome-ignore lint/suspicious/noExplicitAny: structural pass-through
  children: any;
}) {
  return <>{children}</>;
}

export default CloudOnboardingWizard;
