import { Suspense } from "react";
import { useAtomRefresh, useAtomValue } from "@effect/atom-react";
import * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
import type { ProviderKey } from "@executor-js/sdk/shared";
import { useSecretProviderPlugins } from "@executor-js/sdk/client";

import { providersAtom } from "../api/atoms";
import {
  CardStack,
  CardStackContent,
  CardStackEntry,
  CardStackEntryActions,
  CardStackEntryContent,
  CardStackEntryDescription,
  CardStackEntryTitle,
  CardStackHeader,
} from "../components/card-stack";
import { Badge } from "../components/badge";
import { PageContainer, PageHeader } from "../components/page";
import { useExecutorDocumentTitle } from "../lib/document-title";
import { ErrorState } from "../components/error-state";
import { isAsyncResultLoading } from "../lib/async-result";

// ---------------------------------------------------------------------------
// Providers page (v2) — repurposed from the v1 Secrets page.
//
// v1 stored standalone secrets and bound them per-source. v2 makes a connection
// the credential, and a `CredentialProvider` is where its value lives (the
// default store for pasted values, or an external backend like 1Password /
// keychain). This page surfaces the registered providers plus any provider
// plugin's settings card. The route still exports `SecretsPage` so existing app
// wiring keeps resolving; new callers should treat it as the Providers view.
// ---------------------------------------------------------------------------

const PROVIDER_LABELS: Record<string, string> = {
  encrypted: "Encrypted store",
  keychain: "Keychain",
  file: "Local file",
  memory: "Memory",
  onepassword: "1Password",
  "workos-vault": "WorkOS Vault",
};

const providerLabel = (key: string): string =>
  PROVIDER_LABELS[key] ??
  key
    .split(/[-_]/g)
    .filter(Boolean)
    .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
    .join(" ");

export function SecretsPage(props: { showProviderInfo?: boolean }) {
  useExecutorDocumentTitle("Providers");
  const showProviderInfo = props.showProviderInfo ?? true;
  const secretProviderPlugins = useSecretProviderPlugins();
  const providers = useAtomValue(providersAtom);
  const refreshProviders = useAtomRefresh(providersAtom);

  return (
    <PageContainer>
      <PageHeader
        title="Providers"
        description="Where your connections' credential values live: the default store for pasted values, or an external backend like 1Password or your system keychain."
      />

      {/* Provider plugins (settings cards) */}
      {showProviderInfo && secretProviderPlugins.length > 0 && (
        <div className="mb-10">
          <CardStack>
            <CardStackHeader>Configure providers</CardStackHeader>
            <CardStackContent>
              {secretProviderPlugins.map((plugin) => (
                <Suspense
                  key={plugin.key}
                  fallback={
                    <div className="px-4 py-3 animate-pulse">
                      <div className="h-4 w-24 rounded bg-muted" />
                    </div>
                  }
                >
                  <plugin.settings />
                </Suspense>
              ))}
            </CardStackContent>
          </CardStack>
        </div>
      )}

      {/* Registered providers */}
      {isAsyncResultLoading(providers) ? (
        <div className="flex items-center gap-2 py-8">
          <div className="size-1.5 animate-pulse rounded-full bg-muted-foreground/30" />
          <p className="text-sm text-muted-foreground">Loading providers…</p>
        </div>
      ) : (
        AsyncResult.match(providers, {
          onInitial: () => (
            <div className="flex items-center gap-2 py-8">
              <div className="size-1.5 animate-pulse rounded-full bg-muted-foreground/30" />
              <p className="text-sm text-muted-foreground">Loading providers…</p>
            </div>
          ),
          onFailure: () => (
            <ErrorState message="Failed to load providers" onRetry={refreshProviders} />
          ),
          onSuccess: ({ value }) => (
            <CardStack>
              <CardStackHeader>Available providers</CardStackHeader>
              <CardStackContent>
                {value.length === 0 ? (
                  <CardStackEntry>
                    <CardStackEntryContent>
                      <CardStackEntryDescription>
                        No credential providers are registered.
                      </CardStackEntryDescription>
                    </CardStackEntryContent>
                  </CardStackEntry>
                ) : (
                  value.map((key: ProviderKey) => (
                    <CardStackEntry key={String(key)}>
                      <CardStackEntryContent>
                        <CardStackEntryTitle className="flex min-w-0 items-center gap-2">
                          <span className="min-w-0 shrink truncate">
                            {providerLabel(String(key))}
                          </span>
                        </CardStackEntryTitle>
                        <CardStackEntryDescription>
                          {String(key) === "encrypted"
                            ? "Values you paste are encrypted and stored in this instance's database."
                            : `${providerLabel(String(key))} credential provider.`}
                        </CardStackEntryDescription>
                      </CardStackEntryContent>
                      <CardStackEntryActions>
                        <Badge variant="secondary">
                          {String(key) === "encrypted" ? "default" : "provider"}
                        </Badge>
                      </CardStackEntryActions>
                    </CardStackEntry>
                  ))
                )}
              </CardStackContent>
            </CardStack>
          ),
        })
      )}
    </PageContainer>
  );
}
