"use client";

import { useState, useEffect, type SyntheticEvent } from "react";
import { Plus, History, Key, RotateCw, Trash2, Eye, EyeOff } from "lucide-react";
import Link from "next/link";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  fetchCredentials,
  createCredential,
  deleteCredential,
  rotateCredential,
  CredentialType,
  CredentialScope,
  type Credential,
  type CreateCredentialDto,
} from "@/lib/api/credentials";
import { useWorkspaceId } from "@/lib/hooks";

/* ---------------------------------------------------------------------------
   Constants
   --------------------------------------------------------------------------- */

const CREDENTIAL_TYPE_LABELS: Record<CredentialType, string> = {
  [CredentialType.API_KEY]: "API Key",
  [CredentialType.OAUTH_TOKEN]: "OAuth Token",
  [CredentialType.ACCESS_TOKEN]: "Access Token",
  [CredentialType.SECRET]: "Secret",
  [CredentialType.PASSWORD]: "Password",
  [CredentialType.CUSTOM]: "Custom",
};

const CREDENTIAL_SCOPE_LABELS: Record<CredentialScope, string> = {
  [CredentialScope.USER]: "User",
  [CredentialScope.WORKSPACE]: "Workspace",
  [CredentialScope.SYSTEM]: "System",
};

/* ---------------------------------------------------------------------------
   Add Credential Dialog
   --------------------------------------------------------------------------- */

interface AddCredentialDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onSubmit: (data: CreateCredentialDto) => Promise<void>;
  isSubmitting: boolean;
}

function AddCredentialDialog({
  open,
  onOpenChange,
  onSubmit,
  isSubmitting,
}: AddCredentialDialogProps): React.ReactElement | null {
  const [name, setName] = useState("");
  const [provider, setProvider] = useState("");
  const [type, setType] = useState<CredentialType>(CredentialType.API_KEY);
  const [scope, setScope] = useState<CredentialScope>(CredentialScope.WORKSPACE);
  const [value, setValue] = useState("");
  const [description, setDescription] = useState("");
  const [showValue, setShowValue] = useState(false);
  const [formError, setFormError] = useState<string | null>(null);

  function resetForm(): void {
    setName("");
    setProvider("");
    setType(CredentialType.API_KEY);
    setScope(CredentialScope.WORKSPACE);
    setValue("");
    setDescription("");
    setShowValue(false);
    setFormError(null);
  }

  async function handleSubmit(e: SyntheticEvent): Promise<void> {
    e.preventDefault();
    setFormError(null);

    const trimmedName = name.trim();
    if (!trimmedName) {
      setFormError("Name is required.");
      return;
    }

    const trimmedProvider = provider.trim();
    if (!trimmedProvider) {
      setFormError("Provider is required.");
      return;
    }

    const trimmedValue = value.trim();
    if (!trimmedValue) {
      setFormError("Credential value is required.");
      return;
    }

    try {
      const payload: CreateCredentialDto = {
        name: trimmedName,
        provider: trimmedProvider,
        type,
        scope,
        value: trimmedValue,
      };

      const trimmedDesc = description.trim();
      if (trimmedDesc) {
        payload.description = trimmedDesc;
      }

      await onSubmit(payload);
      resetForm();
    } catch (err: unknown) {
      setFormError(err instanceof Error ? err.message : "Failed to create credential.");
    }
  }

  if (!open) return null;

  return (
    <div
      role="dialog"
      aria-modal="true"
      aria-labelledby="add-credential-title"
      style={{
        position: "fixed",
        inset: 0,
        zIndex: 50,
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
      }}
    >
      {/* Backdrop */}
      <div
        style={{
          position: "fixed",
          inset: 0,
          background: "rgba(0,0,0,0.5)",
        }}
        onClick={() => {
          if (!isSubmitting) {
            resetForm();
            onOpenChange(false);
          }
        }}
      />

      {/* Dialog */}
      <div
        style={{
          position: "relative",
          background: "var(--surface, #fff)",
          borderRadius: "8px",
          border: "1px solid var(--border, #e5e7eb)",
          padding: 24,
          width: "100%",
          maxWidth: 520,
          zIndex: 1,
          maxHeight: "90vh",
          overflowY: "auto",
        }}
      >
        <h2
          id="add-credential-title"
          style={{
            fontSize: "1.125rem",
            fontWeight: 600,
            color: "var(--text, #111)",
            margin: "0 0 8px",
          }}
        >
          Add Credential
        </h2>
        <p style={{ color: "var(--muted, #6b7280)", fontSize: "0.875rem", margin: "0 0 16px" }}>
          Securely store an API key, token, or secret.
        </p>

        <form
          onSubmit={(e) => {
            void handleSubmit(e);
          }}
        >
          {/* Name */}
          <div style={{ marginBottom: 16 }}>
            <label
              htmlFor="cred-name"
              style={{
                display: "block",
                marginBottom: 6,
                fontSize: "0.85rem",
                fontWeight: 500,
                color: "var(--text-2, #374151)",
              }}
            >
              Name <span style={{ color: "var(--danger, #ef4444)" }}>*</span>
            </label>
            <Input
              id="cred-name"
              type="text"
              value={name}
              onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
                setName(e.target.value);
              }}
              placeholder="e.g. GitHub Personal Access Token"
              maxLength={255}
              autoFocus
            />
          </div>

          {/* Provider */}
          <div style={{ marginBottom: 16 }}>
            <label
              htmlFor="cred-provider"
              style={{
                display: "block",
                marginBottom: 6,
                fontSize: "0.85rem",
                fontWeight: 500,
                color: "var(--text-2, #374151)",
              }}
            >
              Provider <span style={{ color: "var(--danger, #ef4444)" }}>*</span>
            </label>
            <Input
              id="cred-provider"
              type="text"
              value={provider}
              onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
                setProvider(e.target.value);
              }}
              placeholder="e.g. github, openai, custom"
              maxLength={100}
            />
            <p style={{ fontSize: "0.75rem", color: "var(--muted, #6b7280)", margin: "4px 0 0" }}>
              The service or system this credential belongs to.
            </p>
          </div>

          {/* Type */}
          <div style={{ marginBottom: 16 }}>
            <label
              htmlFor="cred-type"
              style={{
                display: "block",
                marginBottom: 6,
                fontSize: "0.85rem",
                fontWeight: 500,
                color: "var(--text-2, #374151)",
              }}
            >
              Type <span style={{ color: "var(--danger, #ef4444)" }}>*</span>
            </label>
            <Select
              value={type}
              onValueChange={(v) => {
                setType(v as CredentialType);
              }}
            >
              <SelectTrigger id="cred-type">
                <SelectValue placeholder="Select type" />
              </SelectTrigger>
              <SelectContent>
                {Object.values(CredentialType).map((t) => (
                  <SelectItem key={t} value={t}>
                    {CREDENTIAL_TYPE_LABELS[t]}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          {/* Scope */}
          <div style={{ marginBottom: 16 }}>
            <label
              htmlFor="cred-scope"
              style={{
                display: "block",
                marginBottom: 6,
                fontSize: "0.85rem",
                fontWeight: 500,
                color: "var(--text-2, #374151)",
              }}
            >
              Scope
            </label>
            <Select
              value={scope}
              onValueChange={(v) => {
                setScope(v as CredentialScope);
              }}
            >
              <SelectTrigger id="cred-scope">
                <SelectValue placeholder="Select scope" />
              </SelectTrigger>
              <SelectContent>
                {Object.values(CredentialScope).map((s) => (
                  <SelectItem key={s} value={s}>
                    {CREDENTIAL_SCOPE_LABELS[s]}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          {/* Value */}
          <div style={{ marginBottom: 16 }}>
            <label
              htmlFor="cred-value"
              style={{
                display: "block",
                marginBottom: 6,
                fontSize: "0.85rem",
                fontWeight: 500,
                color: "var(--text-2, #374151)",
              }}
            >
              Value <span style={{ color: "var(--danger, #ef4444)" }}>*</span>
            </label>
            <div style={{ position: "relative" }}>
              <Input
                id="cred-value"
                type={showValue ? "text" : "password"}
                value={value}
                onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
                  setValue(e.target.value);
                }}
                placeholder="Paste your secret value here"
                style={{ paddingRight: "40px" }}
              />
              <button
                type="button"
                onClick={() => {
                  setShowValue((prev) => !prev);
                }}
                style={{
                  position: "absolute",
                  right: "10px",
                  top: "50%",
                  transform: "translateY(-50%)",
                  background: "none",
                  border: "none",
                  cursor: "pointer",
                  color: "var(--muted, #6b7280)",
                  padding: 0,
                  display: "flex",
                  alignItems: "center",
                }}
                aria-label={showValue ? "Hide value" : "Show value"}
              >
                {showValue ? <EyeOff size={16} /> : <Eye size={16} />}
              </button>
            </div>
            <p style={{ fontSize: "0.75rem", color: "var(--muted, #6b7280)", margin: "4px 0 0" }}>
              The value is encrypted at rest and never returned in plaintext.
            </p>
          </div>

          {/* Description */}
          <div style={{ marginBottom: 16 }}>
            <label
              htmlFor="cred-description"
              style={{
                display: "block",
                marginBottom: 6,
                fontSize: "0.85rem",
                fontWeight: 500,
                color: "var(--text-2, #374151)",
              }}
            >
              Description
            </label>
            <textarea
              id="cred-description"
              value={description}
              onChange={(e) => {
                setDescription(e.target.value);
              }}
              placeholder="Optional description..."
              rows={2}
              maxLength={1000}
              style={{
                width: "100%",
                padding: "8px 12px",
                background: "var(--bg, #f9fafb)",
                border: "1px solid var(--border, #d1d5db)",
                borderRadius: "6px",
                color: "var(--text, #111)",
                fontSize: "0.9rem",
                outline: "none",
                resize: "vertical",
                fontFamily: "inherit",
                boxSizing: "border-box",
              }}
            />
          </div>

          {/* Form error */}
          {formError !== null && (
            <p
              style={{
                color: "var(--danger, #ef4444)",
                fontSize: "0.85rem",
                margin: "0 0 12px",
              }}
            >
              {formError}
            </p>
          )}

          {/* Buttons */}
          <div
            style={{
              display: "flex",
              justifyContent: "flex-end",
              gap: 8,
              marginTop: 8,
            }}
          >
            <button
              type="button"
              onClick={() => {
                resetForm();
                onOpenChange(false);
              }}
              disabled={isSubmitting}
              style={{
                padding: "8px 16px",
                background: "transparent",
                border: "1px solid var(--border, #d1d5db)",
                borderRadius: "6px",
                color: "var(--text-2, #374151)",
                fontSize: "0.85rem",
                cursor: "pointer",
              }}
            >
              Cancel
            </button>
            <button
              type="submit"
              disabled={isSubmitting || !name.trim() || !provider.trim() || !value.trim()}
              style={{
                padding: "8px 16px",
                background: "var(--primary, #111827)",
                border: "none",
                borderRadius: "6px",
                color: "#fff",
                fontSize: "0.85rem",
                fontWeight: 500,
                cursor:
                  isSubmitting || !name.trim() || !provider.trim() || !value.trim()
                    ? "not-allowed"
                    : "pointer",
                opacity:
                  isSubmitting || !name.trim() || !provider.trim() || !value.trim() ? 0.6 : 1,
              }}
            >
              {isSubmitting ? "Saving..." : "Add Credential"}
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}

/* ---------------------------------------------------------------------------
   Rotate Credential Dialog
   --------------------------------------------------------------------------- */

interface RotateCredentialDialogProps {
  credential: Credential;
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onSubmit: (credentialId: string, newValue: string) => Promise<void>;
  isSubmitting: boolean;
}

function RotateCredentialDialog({
  credential,
  open,
  onOpenChange,
  onSubmit,
  isSubmitting,
}: RotateCredentialDialogProps): React.ReactElement | null {
  const [newValue, setNewValue] = useState("");
  const [showValue, setShowValue] = useState(false);
  const [formError, setFormError] = useState<string | null>(null);

  function resetForm(): void {
    setNewValue("");
    setShowValue(false);
    setFormError(null);
  }

  async function handleSubmit(e: SyntheticEvent): Promise<void> {
    e.preventDefault();
    setFormError(null);

    const trimmedValue = newValue.trim();
    if (!trimmedValue) {
      setFormError("New value is required.");
      return;
    }

    try {
      await onSubmit(credential.id, trimmedValue);
      resetForm();
    } catch (err: unknown) {
      setFormError(err instanceof Error ? err.message : "Failed to rotate credential.");
    }
  }

  if (!open) return null;

  return (
    <div
      role="dialog"
      aria-modal="true"
      aria-labelledby="rotate-credential-title"
      style={{
        position: "fixed",
        inset: 0,
        zIndex: 50,
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
      }}
    >
      {/* Backdrop */}
      <div
        style={{ position: "fixed", inset: 0, background: "rgba(0,0,0,0.5)" }}
        onClick={() => {
          if (!isSubmitting) {
            resetForm();
            onOpenChange(false);
          }
        }}
      />

      {/* Dialog */}
      <div
        style={{
          position: "relative",
          background: "var(--surface, #fff)",
          borderRadius: "8px",
          border: "1px solid var(--border, #e5e7eb)",
          padding: 24,
          width: "100%",
          maxWidth: 480,
          zIndex: 1,
        }}
      >
        <h2
          id="rotate-credential-title"
          style={{
            fontSize: "1.125rem",
            fontWeight: 600,
            color: "var(--text, #111)",
            margin: "0 0 8px",
          }}
        >
          Rotate Credential
        </h2>
        <p style={{ color: "var(--muted, #6b7280)", fontSize: "0.875rem", margin: "0 0 4px" }}>
          Replace the value for{" "}
          <strong style={{ color: "var(--text, #111)" }}>{credential.name}</strong>.
        </p>
        <p style={{ color: "var(--muted, #6b7280)", fontSize: "0.875rem", margin: "0 0 16px" }}>
          The old value will be permanently replaced.
        </p>

        <form
          onSubmit={(e) => {
            void handleSubmit(e);
          }}
        >
          <div style={{ marginBottom: 16 }}>
            <label
              htmlFor="rotate-value"
              style={{
                display: "block",
                marginBottom: 6,
                fontSize: "0.85rem",
                fontWeight: 500,
                color: "var(--text-2, #374151)",
              }}
            >
              New Value <span style={{ color: "var(--danger, #ef4444)" }}>*</span>
            </label>
            <div style={{ position: "relative" }}>
              <Input
                id="rotate-value"
                type={showValue ? "text" : "password"}
                value={newValue}
                onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
                  setNewValue(e.target.value);
                }}
                placeholder="Paste new secret value"
                autoFocus
                style={{ paddingRight: "40px" }}
              />
              <button
                type="button"
                onClick={() => {
                  setShowValue((prev) => !prev);
                }}
                style={{
                  position: "absolute",
                  right: "10px",
                  top: "50%",
                  transform: "translateY(-50%)",
                  background: "none",
                  border: "none",
                  cursor: "pointer",
                  color: "var(--muted, #6b7280)",
                  padding: 0,
                  display: "flex",
                  alignItems: "center",
                }}
                aria-label={showValue ? "Hide value" : "Show value"}
              >
                {showValue ? <EyeOff size={16} /> : <Eye size={16} />}
              </button>
            </div>
          </div>

          {formError !== null && (
            <p
              style={{
                color: "var(--danger, #ef4444)",
                fontSize: "0.85rem",
                margin: "0 0 12px",
              }}
            >
              {formError}
            </p>
          )}

          <div style={{ display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 8 }}>
            <button
              type="button"
              onClick={() => {
                resetForm();
                onOpenChange(false);
              }}
              disabled={isSubmitting}
              style={{
                padding: "8px 16px",
                background: "transparent",
                border: "1px solid var(--border, #d1d5db)",
                borderRadius: "6px",
                color: "var(--text-2, #374151)",
                fontSize: "0.85rem",
                cursor: "pointer",
              }}
            >
              Cancel
            </button>
            <button
              type="submit"
              disabled={isSubmitting || !newValue.trim()}
              style={{
                padding: "8px 16px",
                background: "var(--primary, #111827)",
                border: "none",
                borderRadius: "6px",
                color: "#fff",
                fontSize: "0.85rem",
                fontWeight: 500,
                cursor: isSubmitting || !newValue.trim() ? "not-allowed" : "pointer",
                opacity: isSubmitting || !newValue.trim() ? 0.6 : 1,
              }}
            >
              {isSubmitting ? "Rotating..." : "Rotate Credential"}
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}

/* ---------------------------------------------------------------------------
   Credential Row
   --------------------------------------------------------------------------- */

interface CredentialRowProps {
  credential: Credential;
  onDelete: (credential: Credential) => void;
  onRotate: (credential: Credential) => void;
}

function formatCredentialDate(date: Date | string | null): string {
  if (!date) return "-";
  return new Intl.DateTimeFormat("en-US", {
    month: "short",
    day: "numeric",
    year: "numeric",
  }).format(new Date(date));
}

function CredentialRow({ credential, onDelete, onRotate }: CredentialRowProps): React.ReactElement {
  return (
    <tr className="border-b border-gray-100 hover:bg-gray-50">
      <td className="px-4 py-3">
        <div className="flex items-center gap-2">
          <Key size={14} className="text-gray-400 shrink-0" />
          <div>
            <p className="font-medium text-gray-900 text-sm">{credential.name}</p>
            {credential.description !== null && credential.description.length > 0 && (
              <p className="text-xs text-gray-500 mt-0.5">{credential.description}</p>
            )}
          </div>
        </div>
      </td>
      <td className="px-4 py-3 text-sm text-gray-600">
        <span className="capitalize">{credential.provider}</span>
      </td>
      <td className="px-4 py-3">
        <span className="inline-block px-2 py-0.5 rounded text-xs font-medium bg-blue-50 text-blue-700">
          {CREDENTIAL_TYPE_LABELS[credential.type]}
        </span>
      </td>
      <td className="px-4 py-3">
        <span className="inline-block px-2 py-0.5 rounded text-xs font-medium bg-gray-100 text-gray-600">
          {CREDENTIAL_SCOPE_LABELS[credential.scope]}
        </span>
      </td>
      <td className="px-4 py-3 text-xs text-gray-500 font-mono">
        {credential.maskedValue ?? "••••••••"}
      </td>
      <td className="px-4 py-3 text-xs text-gray-500">
        {formatCredentialDate(credential.createdAt)}
      </td>
      <td className="px-4 py-3">
        <div className="flex items-center gap-1 justify-end">
          <button
            type="button"
            onClick={() => {
              onRotate(credential);
            }}
            title="Rotate credential value"
            style={{
              padding: "4px 8px",
              background: "transparent",
              border: "1px solid var(--border, #d1d5db)",
              borderRadius: "4px",
              cursor: "pointer",
              color: "var(--text-2, #374151)",
              display: "flex",
              alignItems: "center",
              gap: 4,
              fontSize: "0.75rem",
            }}
          >
            <RotateCw size={12} />
            Rotate
          </button>
          <button
            type="button"
            onClick={() => {
              onDelete(credential);
            }}
            title="Delete credential"
            style={{
              padding: "4px 8px",
              background: "transparent",
              border: "1px solid var(--danger, #fca5a5)",
              borderRadius: "4px",
              cursor: "pointer",
              color: "var(--danger, #ef4444)",
              display: "flex",
              alignItems: "center",
              gap: 4,
              fontSize: "0.75rem",
            }}
          >
            <Trash2 size={12} />
            Delete
          </button>
        </div>
      </td>
    </tr>
  );
}

/* ---------------------------------------------------------------------------
   Credentials Page
   --------------------------------------------------------------------------- */

export default function CredentialsPage(): React.ReactElement {
  const [credentials, setCredentials] = useState<Credential[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  // Add dialog state
  const [addOpen, setAddOpen] = useState(false);
  const [isAdding, setIsAdding] = useState(false);

  // Rotate dialog state
  const [rotateTarget, setRotateTarget] = useState<Credential | null>(null);
  const [isRotating, setIsRotating] = useState(false);

  const workspaceId = useWorkspaceId();

  useEffect(() => {
    if (!workspaceId) return;
    void loadCredentials(workspaceId);
  }, [workspaceId]);

  async function loadCredentials(wsId: string): Promise<void> {
    try {
      setIsLoading(true);
      const response = await fetchCredentials(wsId);
      setCredentials(response.data);
      setError(null);
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to load credentials");
    } finally {
      setIsLoading(false);
    }
  }

  async function handleAdd(data: CreateCredentialDto): Promise<void> {
    if (!workspaceId) return;
    setIsAdding(true);
    try {
      await createCredential(workspaceId, data);
      setAddOpen(false);
      await loadCredentials(workspaceId);
    } finally {
      setIsAdding(false);
    }
  }

  async function handleDelete(credential: Credential): Promise<void> {
    if (!workspaceId) return;
    if (!confirm(`Delete credential "${credential.name}"? This action cannot be undone.`)) return;

    try {
      await deleteCredential(credential.id, workspaceId);
      await loadCredentials(workspaceId);
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to delete credential");
    }
  }

  async function handleRotate(credentialId: string, newValue: string): Promise<void> {
    if (!workspaceId) return;
    setIsRotating(true);
    try {
      await rotateCredential(credentialId, workspaceId, newValue);
      setRotateTarget(null);
      await loadCredentials(workspaceId);
    } finally {
      setIsRotating(false);
    }
  }

  return (
    <div className="max-w-6xl mx-auto p-6">
      {/* Header */}
      <div className="mb-6">
        <div className="flex items-center justify-between">
          <div>
            <h1 className="text-3xl font-bold">Credentials</h1>
            <p className="text-muted-foreground mt-1">
              Securely store and manage API keys, tokens, and passwords
            </p>
          </div>
          <div className="flex gap-2">
            <Button
              onClick={() => {
                setAddOpen(true);
              }}
            >
              <Plus className="mr-2 h-4 w-4" />
              Add Credential
            </Button>
            <Link href="/settings/credentials/audit">
              <Button variant="outline">
                <History className="mr-2 h-4 w-4" />
                Audit Log
              </Button>
            </Link>
          </div>
        </div>
      </div>

      {/* Error Display */}
      {error !== null && (
        <div className="mb-4 p-4 bg-red-50 border border-red-200 text-red-800 rounded-md">
          {error}
        </div>
      )}

      {/* Loading State */}
      {isLoading ? (
        <div className="text-center py-12">
          <p className="text-gray-500">Loading credentials...</p>
        </div>
      ) : credentials.length === 0 ? (
        <Card>
          <CardContent className="flex flex-col items-center justify-center py-12">
            <Key size={32} className="text-gray-300 mb-4" />
            <p className="text-gray-500 mb-2 font-medium">No credentials yet</p>
            <p className="text-gray-400 text-sm mb-4">
              Add your first API key, token, or secret to get started.
            </p>
            <Button
              onClick={() => {
                setAddOpen(true);
              }}
            >
              <Plus className="mr-2 h-4 w-4" />
              Add First Credential
            </Button>
          </CardContent>
        </Card>
      ) : (
        <Card>
          <CardHeader>
            <div className="flex items-center justify-between">
              <div>
                <CardTitle className="text-lg">Stored Credentials</CardTitle>
                <CardDescription>
                  {credentials.length} credential{credentials.length !== 1 ? "s" : ""} stored
                </CardDescription>
              </div>
            </div>
          </CardHeader>
          <CardContent className="p-0">
            {/* Desktop table */}
            <div className="hidden md:block overflow-x-auto">
              <table className="w-full text-sm">
                <thead className="bg-gray-50 border-b border-gray-200">
                  <tr>
                    <th className="px-4 py-3 text-left font-medium text-gray-700">Name</th>
                    <th className="px-4 py-3 text-left font-medium text-gray-700">Provider</th>
                    <th className="px-4 py-3 text-left font-medium text-gray-700">Type</th>
                    <th className="px-4 py-3 text-left font-medium text-gray-700">Scope</th>
                    <th className="px-4 py-3 text-left font-medium text-gray-700">Value</th>
                    <th className="px-4 py-3 text-left font-medium text-gray-700">Created</th>
                    <th className="px-4 py-3 text-right font-medium text-gray-700">Actions</th>
                  </tr>
                </thead>
                <tbody>
                  {credentials.map((cred) => (
                    <CredentialRow
                      key={cred.id}
                      credential={cred}
                      onDelete={(c) => {
                        void handleDelete(c);
                      }}
                      onRotate={(c) => {
                        setRotateTarget(c);
                      }}
                    />
                  ))}
                </tbody>
              </table>
            </div>

            {/* Mobile cards */}
            <div className="md:hidden divide-y divide-gray-100">
              {credentials.map((cred) => (
                <div key={cred.id} className="p-4">
                  <div className="flex items-start justify-between mb-2">
                    <div className="flex items-center gap-2">
                      <Key size={14} className="text-gray-400 shrink-0 mt-0.5" />
                      <div>
                        <p className="font-medium text-gray-900 text-sm">{cred.name}</p>
                        {cred.description !== null && cred.description.length > 0 && (
                          <p className="text-xs text-gray-500 mt-0.5">{cred.description}</p>
                        )}
                      </div>
                    </div>
                    <span className="inline-block px-2 py-0.5 rounded text-xs font-medium bg-blue-50 text-blue-700">
                      {CREDENTIAL_TYPE_LABELS[cred.type]}
                    </span>
                  </div>
                  <div className="text-xs text-gray-500 mb-3 font-mono">
                    {cred.maskedValue ?? "••••••••"}
                  </div>
                  <div className="flex items-center gap-2">
                    <button
                      type="button"
                      onClick={() => {
                        setRotateTarget(cred);
                      }}
                      style={{
                        padding: "4px 10px",
                        background: "transparent",
                        border: "1px solid var(--border, #d1d5db)",
                        borderRadius: "4px",
                        cursor: "pointer",
                        color: "var(--text-2, #374151)",
                        display: "flex",
                        alignItems: "center",
                        gap: 4,
                        fontSize: "0.75rem",
                      }}
                    >
                      <RotateCw size={12} />
                      Rotate
                    </button>
                    <button
                      type="button"
                      onClick={() => {
                        void handleDelete(cred);
                      }}
                      style={{
                        padding: "4px 10px",
                        background: "transparent",
                        border: "1px solid var(--danger, #fca5a5)",
                        borderRadius: "4px",
                        cursor: "pointer",
                        color: "var(--danger, #ef4444)",
                        display: "flex",
                        alignItems: "center",
                        gap: 4,
                        fontSize: "0.75rem",
                      }}
                    >
                      <Trash2 size={12} />
                      Delete
                    </button>
                  </div>
                </div>
              ))}
            </div>
          </CardContent>
        </Card>
      )}

      {/* Add Credential Dialog */}
      <AddCredentialDialog
        open={addOpen}
        onOpenChange={setAddOpen}
        onSubmit={handleAdd}
        isSubmitting={isAdding}
      />

      {/* Rotate Credential Dialog */}
      {rotateTarget !== null && (
        <RotateCredentialDialog
          credential={rotateTarget}
          open
          onOpenChange={(open) => {
            if (!open) setRotateTarget(null);
          }}
          onSubmit={handleRotate}
          isSubmitting={isRotating}
        />
      )}
    </div>
  );
}
