"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { Button, Card, Modal, Space, Table, Tag, Tooltip, Typography, message } from "antd";
import type { ColumnsType } from "antd/es/table";
import { PlusOutlined, ReloadOutlined, WarningOutlined } from "@ant-design/icons";
import dayjs from "dayjs";
import { useRouter } from "next/navigation";

import { CopyOnceModal } from "@/app/dashboard/api-keys/components/copy-once-modal";
import { PageStateNotice } from "@/components/common/page-state-notice";
import { apiKeysApi } from "@/lib/api/api-keys";
import { extractApiErrorMessage } from "@/lib/api/errors";
import { useAuth } from "@/lib/hooks/use-auth";
import type { APIKey, APIKeyStatus, CreateAPIKeyResponse } from "@/lib/api/api-keys";

const { Title, Paragraph, Text } = Typography;

const MANAGE_KEYS_PERMISSION = "agent:manage_own_keys";
const EXPIRING_SOON_THRESHOLD_MS = 7 * 24 * 60 * 60 * 1000;
const EXPIRING_SOON_TOOLTIP = "Expiring soon";
const EXPIRING_SOON_ROW_BACKGROUND = "#fff7e6";

const statusMeta: Record<APIKeyStatus, { label: string; color: string }> = {
  active: { label: "Active", color: "green" },
  revoked: { label: "Revoked", color: "default" },
  expired: { label: "Expired", color: "gold" },
};

function formatDateTime(value?: string | null) {
  return value ? dayjs(value).format("YYYY-MM-DD HH:mm") : null;
}

function isExpiringSoon(record: APIKey) {
  if (record.status !== "active" || !record.expires_at) {
    return false;
  }
  return dayjs(record.expires_at).valueOf() - Date.now() < EXPIRING_SOON_THRESHOLD_MS;
}

export default function APIKeysPage() {
  const router = useRouter();
  const { hasPermission } = useAuth();
  const canManageKeys = hasPermission(MANAGE_KEYS_PERMISSION);

  const [records, setRecords] = useState<APIKey[]>([]);
  const [loading, setLoading] = useState(false);
  const [loadError, setLoadError] = useState<string | null>(null);
  const [pendingAction, setPendingAction] = useState<{ id: number; action: "revoke" | "rotate" } | null>(null);
  // The rotated plaintext key lives only in this state and is cleared when CopyOnceModal closes.
  const [rotatedKey, setRotatedKey] = useState<CreateAPIKeyResponse | null>(null);

  const loadKeys = useCallback(async () => {
    if (!canManageKeys) return;
    setLoading(true);
    try {
      const payload = await apiKeysApi.list();
      setRecords(payload ?? []);
      setLoadError(null);
    } catch (error) {
      console.error("Failed to load API keys", error);
      setRecords([]);
      setLoadError("API key list could not be loaded.");
    } finally {
      setLoading(false);
    }
  }, [canManageKeys]);

  useEffect(() => {
    void loadKeys();
  }, [loadKeys]);

  const handleRevoke = useCallback(
    (record: APIKey) => {
      Modal.confirm({
        title: "Revoke API Key",
        content: `Revoking takes effect immediately and cannot be undone. Revoke ${record.agent_name}?`,
        okText: "Revoke",
        okType: "danger",
        cancelText: "Cancel",
        onOk: async () => {
          setPendingAction({ id: record.id, action: "revoke" });
          try {
            await apiKeysApi.revoke(record.id);
            message.success(`Revoked ${record.agent_name}`);
            await loadKeys();
          } catch (error) {
            // Errors thrown by apiClient already carry the backend message (see lib/api/client.ts).
            message.error(extractApiErrorMessage(error) ?? "Failed to revoke API key. Please try again.");
          } finally {
            setPendingAction(null);
          }
        },
      });
    },
    [loadKeys],
  );

  const handleRotate = useCallback((record: APIKey) => {
    Modal.confirm({
      title: "Rotate API Key",
      content: "The old key will be revoked and a new key generated with the same scope and expiry. Continue?",
      okText: "Rotate",
      cancelText: "Cancel",
      onOk: async () => {
        setPendingAction({ id: record.id, action: "rotate" });
        try {
          const rotated = await apiKeysApi.rotate(record.id);
          // The new plaintext is shown once in CopyOnceModal; the list refresh is deferred until the modal closes.
          setRotatedKey(rotated);
        } catch (error) {
          message.error(extractApiErrorMessage(error) ?? "Failed to rotate API key. Please try again.");
        } finally {
          setPendingAction(null);
        }
      },
    });
  }, []);

  const handleViewUsage = useCallback(
    (record: APIKey) => {
      router.push(`/dashboard/api-keys/usage/${record.id}`);
    },
    [router],
  );

  // Sole exit from the plaintext modal (after the "I have saved it" confirmation): clear the in-memory plaintext and refresh the list.
  const handleRotatedKeyModalClose = useCallback(() => {
    setRotatedKey(null);
    void loadKeys();
  }, [loadKeys]);

  const columns: ColumnsType<APIKey> = useMemo(
    () => [
      {
        title: "Agent Name",
        dataIndex: "agent_name",
        width: 200,
        ellipsis: { showTitle: false },
        render: (value: string) => (
          <Tooltip placement="topLeft" title={value}>
            <Text strong>{value}</Text>
          </Tooltip>
        ),
      },
      {
        title: "Key Prefix",
        dataIndex: "key_prefix",
        width: 220,
        ellipsis: { showTitle: false },
        render: (value: string) => (
          <Tooltip placement="topLeft" title={`${value}…`}>
            <Text code>{value}…</Text>
          </Tooltip>
        ),
      },
      {
        title: "Scope",
        dataIndex: "permission_scope",
        width: 240,
        render: (value: string[]) =>
          value?.length ? (
            <Space wrap size={4}>
              {value.map((scope) => (
                <Tooltip key={scope} title={scope}>
                  <Tag style={{ maxWidth: 216, overflow: "hidden", textOverflow: "ellipsis" }}>{scope}</Tag>
                </Tooltip>
              ))}
            </Space>
          ) : (
            "-"
          ),
      },
      {
        title: "Owner",
        dataIndex: "owner_name",
        width: 200,
        ellipsis: { showTitle: false },
        render: (_: string | undefined, record) => {
          const label = record.owner_name || record.owner_email || `user #${record.owner_user_id}`;
          return (
            <Tooltip placement="topLeft" title={record.owner_email ?? label}>
              <Text>{label}</Text>
            </Tooltip>
          );
        },
      },
      {
        title: "Status",
        dataIndex: "status",
        width: 110,
        render: (value: APIKeyStatus) => {
          const meta = statusMeta[value] ?? { label: value, color: "default" };
          return <Tag color={meta.color}>{meta.label}</Tag>;
        },
      },
      {
        title: "Last Used",
        dataIndex: "last_used_at",
        width: 170,
        render: (value?: string | null) => formatDateTime(value) ?? <Text type="secondary">Never used</Text>,
      },
      {
        title: "Expires At",
        dataIndex: "expires_at",
        width: 190,
        render: (value: string | null | undefined, record) => {
          const formatted = formatDateTime(value);
          if (!formatted) {
            return <Text type="secondary">Never</Text>;
          }
          return (
            <Space size={6}>
              <span>{formatted}</span>
              {isExpiringSoon(record) ? (
                <Tooltip title={EXPIRING_SOON_TOOLTIP}>
                  <WarningOutlined style={{ color: "#fa8c16" }} />
                </Tooltip>
              ) : null}
            </Space>
          );
        },
      },
      {
        title: "Actions",
        key: "actions",
        width: 250,
        render: (_, record) => (
          <Space size={8}>
            <Button
              size="small"
              disabled={record.status !== "active"}
              loading={pendingAction?.id === record.id && pendingAction?.action === "rotate"}
              onClick={() => handleRotate(record)}
            >
              Rotate
            </Button>
            <Button
              size="small"
              danger
              disabled={record.status !== "active"}
              loading={pendingAction?.id === record.id && pendingAction?.action === "revoke"}
              onClick={() => handleRevoke(record)}
            >
              Revoke
            </Button>
            <Button size="small" onClick={() => handleViewUsage(record)}>
              View Usage
            </Button>
          </Space>
        ),
      },
    ],
    [handleRevoke, handleRotate, handleViewUsage, pendingAction],
  );

  if (!canManageKeys) {
    return (
      <PageStateNotice
        tone="unavailable"
        title="API Keys unavailable"
        description={`Your account is missing the ${MANAGE_KEYS_PERMISSION} permission required to manage Agent API keys. Contact an administrator to request access before issuing keys for agents.`}
      />
    );
  }

  return (
    <Space direction="vertical" size={24} style={{ width: "100%" }}>
      <Space align="baseline" style={{ justifyContent: "space-between", width: "100%" }}>
        <div>
          <Title level={3} style={{ marginBottom: 4 }}>
            API Keys
          </Title>
          <Paragraph type="secondary" style={{ margin: 0 }}>
            Manage the keys agents use to call the platform API: issue, rotate, and revoke keys, and track last-used and expiry times.
          </Paragraph>
        </div>
        <Space>
          <Button icon={<ReloadOutlined />} onClick={() => void loadKeys()} disabled={loading}>
            Refresh
          </Button>
          <Button type="primary" icon={<PlusOutlined />} onClick={() => router.push("/dashboard/api-keys/new")}>
            Create Key
          </Button>
        </Space>
      </Space>

      <Card>
        <Table<APIKey>
          rowKey={(record) => String(record.id)}
          columns={columns}
          scroll={{ x: 1380 }}
          dataSource={records}
          loading={loading}
          pagination={{ pageSize: 10, hideOnSinglePage: true }}
          onRow={(record) =>
            isExpiringSoon(record)
              ? { style: { background: EXPIRING_SOON_ROW_BACKGROUND }, title: EXPIRING_SOON_TOOLTIP }
              : {}
          }
          locale={{
            emptyText: loadError ? (
              <PageStateNotice
                tone="error"
                compact
                title="API key list unavailable"
                description={`${loadError} Retry loading the list, or create a key if you have none yet.`}
                actions={
                  <Space wrap>
                    <Button icon={<ReloadOutlined />} onClick={() => void loadKeys()}>
                      Retry
                    </Button>
                    <Button type="primary" onClick={() => router.push("/dashboard/api-keys/new")}>
                      Create Key
                    </Button>
                  </Space>
                }
              />
            ) : (
              <PageStateNotice
                tone="empty"
                compact
                title="No API keys yet"
                description="Issue the first API key for an agent to call the platform's open APIs. The plaintext key is shown only once at creation."
                actions={
                  <Button
                    type="primary"
                    icon={<PlusOutlined />}
                    onClick={() => router.push("/dashboard/api-keys/new")}
                  >
                    Create Key
                  </Button>
                }
              />
            ),
          }}
        />
      </Card>

      <CopyOnceModal
        open={Boolean(rotatedKey)}
        apiKey={rotatedKey?.api_key ?? ""}
        title="API Key rotated successfully"
        onClose={handleRotatedKeyModalClose}
      />
    </Space>
  );
}
