import { useMemo, useState } from "react";
import { useAtomValue } from "@effect/atom-react";
import * as AsyncResult from "effect/unstable/reactivity/AsyncResult";

import {
  AuthTemplateSlug,
  IntegrationSlug,
  type Connection,
  type Owner,
} from "@executor-js/sdk/shared";
import { connectionsAllAtom } from "@executor-js/react/api/atoms";
import { AddAccountModal } from "@executor-js/react/components/add-account-modal";
import { OAuthSignInButton } from "@executor-js/react/plugins/oauth-sign-in";
import type { AuthMethod } from "@executor-js/react/lib/auth-placements";
import { useCanCreateWorkspaceConnections } from "@executor-js/react/multiplayer/use-admin-nav";

import { mcpServerAtom } from "./atoms";
import type { McpAuthMethod } from "../sdk/types";

// ---------------------------------------------------------------------------
// McpSignInButton — top-bar action on the integration detail page (v2).
//
// Reads the integration's declared auth methods; when one is `oauth2` it runs
// the OAuth flow to mint a connection through that method. "Connected" is
// derived from whether ANY owner already has a connection for this integration
// (the global owner toggle is retired, so the check merges both owners). The
// NEW connection's owner is a real create-target — chosen EXPLICITLY via the
// `owner` prop (default Workspace `org` on an org-scoped host, Local `org` on
// a non-org host like local), never read from an ambient owner.
// ---------------------------------------------------------------------------

export default function McpSignInButton(props: { integrationId: string; owner?: Owner }) {
  const slug = IntegrationSlug.make(props.integrationId);
  const targetOwner: Owner = props.owner ?? "org";
  const serverResult = useAtomValue(mcpServerAtom(slug));
  const connectionsResult = useAtomValue(connectionsAllAtom);
  const [modalOpen, setModalOpen] = useState(false);
  const canCreateWorkspaceConnections = useCanCreateWorkspaceConnections();

  const server = AsyncResult.isSuccess(serverResult) ? serverResult.value : null;
  const remote = server !== null && server.config.transport === "remote" ? server.config : null;
  const oauthMethod =
    remote?.authenticationTemplate.find((method: McpAuthMethod) => method.kind === "oauth2") ??
    null;
  const connections: readonly Connection[] = AsyncResult.isSuccess(connectionsResult)
    ? connectionsResult.value
    : [];
  const hasConnection = connections.some(
    (connection: Connection) => connection.integration === slug,
  );

  const methods = useMemo<readonly AuthMethod[]>(
    () =>
      remote === null || oauthMethod === null
        ? []
        : [
            {
              id: oauthMethod.slug,
              label: "OAuth",
              kind: "oauth",
              source: "spec",
              template: AuthTemplateSlug.make(oauthMethod.slug),
              placements: [],
              oauth: { discoveryUrl: remote.endpoint, supportsDynamicRegistration: true },
            },
          ],
    [remote, oauthMethod],
  );
  const initialState = useMemo(
    () =>
      modalOpen && server && oauthMethod
        ? {
            key: `${String(slug)}:${targetOwner}:oauth`,
            owner: targetOwner,
            template: oauthMethod.slug,
            label: `${server.description || String(slug)} OAuth`,
          }
        : null,
    [modalOpen, oauthMethod, server, slug, targetOwner],
  );

  if (oauthMethod === null || (targetOwner === "org" && !canCreateWorkspaceConnections)) {
    return null;
  }

  return (
    <>
      <OAuthSignInButton
        busy={false}
        error={null}
        isConnected={hasConnection}
        onSignIn={() => setModalOpen(true)}
        reconnectingLabel="Reconnecting…"
        signingInLabel="Signing in…"
      />
      {server ? (
        <AddAccountModal
          integration={slug}
          integrationName={server.description || String(slug)}
          methods={methods}
          open={modalOpen}
          onOpenChange={setModalOpen}
          initialState={initialState}
        />
      ) : null}
    </>
  );
}
