import * as React from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import type { Credential, CredentialWithSecret } from '@sentryagent/idp-sdk';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { ConfirmDialog } from '@/components/ui/dialog';
import { getClient } from '@/lib/client';

/** Truncates a string to a maximum length with ellipsis. */
function truncate(value: string, maxLen = 16): string {
  return value.length > maxLen ? `${value.slice(0, maxLen)}…` : value;
}

/** Formats an ISO timestamp to a short local date string. */
function formatDate(iso: string): string {
  return new Date(iso).toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });
}

interface NewSecretBoxProps {
  secret: string;
  onDismiss: () => void;
}

/**
 * Displays a newly issued client secret exactly once.
 * Provides a copy button and a dismiss button.
 */
function NewSecretBox({ secret, onDismiss }: NewSecretBoxProps): React.JSX.Element {
  const [copied, setCopied] = React.useState<boolean>(false);

  const handleCopy = React.useCallback(async (): Promise<void> => {
    await navigator.clipboard.writeText(secret);
    setCopied(true);
    setTimeout(() => { setCopied(false); }, 2000);
  }, [secret]);

  return (
    <div className="mb-6 rounded-lg border-2 border-green-400 bg-green-50 p-4">
      <p className="mb-2 text-sm font-semibold text-green-800">
        New client secret — copy it now. It will not be shown again.
      </p>
      <div className="flex items-center gap-3">
        <code className="flex-1 break-all rounded bg-white px-3 py-2 text-sm font-mono text-green-900 border border-green-200">
          {secret}
        </code>
        <Button variant="outline" size="sm" onClick={() => { void handleCopy(); }}>
          {copied ? 'Copied!' : 'Copy'}
        </Button>
      </div>
      <button
        onClick={onDismiss}
        className="mt-3 text-xs text-green-700 underline hover:text-green-900"
      >
        I have saved this secret — dismiss
      </button>
    </div>
  );
}

type DialogAction = { type: 'rotate'; credentialId: string } | { type: 'revoke'; credentialId: string };

/**
 * Credentials page — lists all credentials for an agent with rotate/revoke actions.
 * Route: /dashboard/agents/:agentId/credentials
 */
export default function Credentials(): React.JSX.Element {
  const { agentId } = useParams<{ agentId: string }>();
  const navigate = useNavigate();

  const [credentials, setCredentials] = React.useState<Credential[]>([]);
  const [loading, setLoading] = React.useState<boolean>(true);
  const [error, setError] = React.useState<string | null>(null);
  const [actionLoading, setActionLoading] = React.useState<boolean>(false);
  const [dialog, setDialog] = React.useState<DialogAction | null>(null);
  const [newSecret, setNewSecret] = React.useState<CredentialWithSecret | null>(null);

  const fetchCredentials = React.useCallback(async (): Promise<void> => {
    if (!agentId) return;
    setLoading(true);
    setError(null);
    try {
      const result = await getClient().credentials.listCredentials(agentId);
      setCredentials(result.data);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to load credentials.');
    } finally {
      setLoading(false);
    }
  }, [agentId]);

  React.useEffect(() => {
    void fetchCredentials();
  }, [fetchCredentials]);

  const handleGenerate = React.useCallback(async (): Promise<void> => {
    if (!agentId) return;
    setActionLoading(true);
    setError(null);
    try {
      const result = await getClient().credentials.generateCredential(agentId, {});
      setNewSecret(result);
      await fetchCredentials();
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to generate credential.');
    } finally {
      setActionLoading(false);
    }
  }, [agentId, fetchCredentials]);

  const handleConfirm = React.useCallback(async (): Promise<void> => {
    if (!dialog || !agentId) return;
    setActionLoading(true);
    setDialog(null);
    setError(null);
    try {
      if (dialog.type === 'rotate') {
        const result = await getClient().credentials.rotateCredential(agentId, dialog.credentialId);
        setNewSecret(result);
      } else {
        await getClient().credentials.revokeCredential(agentId, dialog.credentialId);
      }
      await fetchCredentials();
    } catch (err) {
      setError(err instanceof Error ? err.message : `Failed to ${dialog.type} credential.`);
    } finally {
      setActionLoading(false);
    }
  }, [dialog, agentId, fetchCredentials]);

  const dialogConfig = React.useMemo(() => {
    if (!dialog) return null;
    if (dialog.type === 'rotate') {
      return {
        title: 'Rotate credential?',
        description: 'The existing secret will be invalidated immediately. You will receive a new secret — store it securely.',
        confirmLabel: 'Rotate',
        variant: 'destructive' as const,
      };
    }
    return {
      title: 'Revoke credential?',
      description: 'This will permanently revoke the credential. This cannot be undone.',
      confirmLabel: 'Revoke',
      variant: 'destructive' as const,
    };
  }, [dialog]);

  return (
    <div>
      {/* Back navigation */}
      <button
        onClick={() => { navigate(`/dashboard/agents/${agentId ?? ''}`); }}
        className="mb-6 flex items-center gap-1 text-sm text-brand-600 hover:text-brand-800"
      >
        ← Back to Agent
      </button>

      <div className="mb-6 flex items-center justify-between">
        <h1 className="text-2xl font-bold text-slate-900">Credentials</h1>
        <Button
          loading={actionLoading}
          onClick={() => { void handleGenerate(); }}
        >
          Generate Credential
        </Button>
      </div>

      {error && (
        <div className="mb-4 rounded-md bg-red-50 px-4 py-3 text-sm text-red-700" role="alert">
          {error}
        </div>
      )}

      {/* New secret display — shown once */}
      {newSecret !== null && (
        <NewSecretBox
          secret={newSecret.clientSecret}
          onDismiss={() => { setNewSecret(null); }}
        />
      )}

      {/* Credentials table */}
      <div className="overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm">
        <table className="min-w-full divide-y divide-slate-200 text-sm">
          <thead className="bg-slate-50">
            <tr>
              {['Credential ID', 'Status', 'Created', 'Actions'].map((col) => (
                <th key={col} className="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-slate-500">
                  {col}
                </th>
              ))}
            </tr>
          </thead>
          <tbody className="divide-y divide-slate-100">
            {loading ? (
              Array.from({ length: 3 }).map((_, i) => (
                <tr key={i}>
                  {Array.from({ length: 4 }).map((__, j) => (
                    <td key={j} className="px-4 py-3">
                      <div className="h-4 w-full animate-pulse rounded bg-slate-200" />
                    </td>
                  ))}
                </tr>
              ))
            ) : credentials.length === 0 ? (
              <tr>
                <td colSpan={4} className="px-4 py-12 text-center text-slate-400">
                  No credentials found. Generate one above.
                </td>
              </tr>
            ) : credentials.map((cred) => (
              <tr key={cred.credentialId} className="hover:bg-slate-50">
                <td className="px-4 py-3 font-mono text-xs text-slate-700">
                  {truncate(cred.credentialId, 24)}
                </td>
                <td className="px-4 py-3">
                  <Badge variant={cred.status === 'active' ? 'success' : 'muted'}>
                    {cred.status}
                  </Badge>
                </td>
                <td className="px-4 py-3 text-slate-500">{formatDate(cred.createdAt)}</td>
                <td className="px-4 py-3">
                  {cred.status === 'active' && (
                    <div className="flex gap-2">
                      <Button
                        variant="outline"
                        size="sm"
                        disabled={actionLoading}
                        onClick={() => { setDialog({ type: 'rotate', credentialId: cred.credentialId }); }}
                      >
                        Rotate
                      </Button>
                      <Button
                        variant="destructive"
                        size="sm"
                        disabled={actionLoading}
                        onClick={() => { setDialog({ type: 'revoke', credentialId: cred.credentialId }); }}
                      >
                        Revoke
                      </Button>
                    </div>
                  )}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      {/* Confirm dialog */}
      {dialog !== null && dialogConfig !== null && (
        <ConfirmDialog
          open
          title={dialogConfig.title}
          description={dialogConfig.description}
          confirmLabel={dialogConfig.confirmLabel}
          variant={dialogConfig.variant}
          onConfirm={() => { void handleConfirm(); }}
          onCancel={() => { setDialog(null); }}
        />
      )}
    </div>
  );
}
