import {
  DeleteOutlined,
  EditOutlined,
  PlusOutlined,
  ReloadOutlined,
  ThunderboltOutlined
} from '@ant-design/icons';
import {
  Alert,
  App as AntApp,
  Button,
  Descriptions,
  Drawer,
  Form,
  Input,
  InputNumber,
  Popconfirm,
  Select,
  Skeleton,
  Space,
  Table,
  Typography
} from 'antd';
import type { ColumnsType } from 'antd/es/table';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useLocation, useNavigate, useSearchParams } from 'react-router-dom';

import { EmptyState } from '../components/common/EmptyState';
import { PageHeader } from '../components/common/PageHeader';
import { SectionCard } from '../components/common/SectionCard';
import { StatusPill } from '../components/common/StatusPill';
import { useI18n } from '../frontend/i18n/react';
import { detailHistoryLocation, detailHistoryState } from '../frontend/navigation-state';
import { api } from '../frontend/services/api';
import type { DnsCredential } from '../frontend/types';

interface CredentialFormValues {
  name: string;
  provider: string;
  zoneName: string;
  defaultTtl: number;
  apiToken?: string;
  zoneId?: string;
  accessKeyId?: string;
  accessKeySecret?: string;
  secretId?: string;
  secretKey?: string;
}

export default function DnsApi() {
  const { message } = AntApp.useApp();
  const { t } = useI18n();
  const location = useLocation();
  const navigate = useNavigate();
  const [searchParams, setSearchParams] = useSearchParams();
  const [form] = Form.useForm<CredentialFormValues>();
  const [credentials, setCredentials] = useState<DnsCredential[]>([]);
  const [loading, setLoading] = useState(true);
  const [loadError, setLoadError] = useState('');
  const [actionKey, setActionKey] = useState('');
  const [editorOpen, setEditorOpen] = useState(false);
  const [editing, setEditing] = useState<DnsCredential | null>(null);
  const provider = Form.useWatch('provider', form) || 'cloudflare';
  const requestedCredentialId = positiveInteger(searchParams.get('credentialId'));
  const selected = useMemo(
    () => requestedCredentialId ? credentials.find((credential) => credential.id === requestedCredentialId) || null : null,
    [credentials, requestedCredentialId]
  );

  const loadCredentials = useCallback(async () => {
    setLoading(true);
    setLoadError('');
    try {
      const result = await api.dnsCredentials();
      setCredentials(result.credentials || []);
    } catch (error) {
      setLoadError(error instanceof Error ? error.message : t('common.error'));
    } finally {
      setLoading(false);
    }
  }, [t]);

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

  function openCreate() {
    setEditing(null);
    form.resetFields();
    form.setFieldsValue({ provider: 'cloudflare', defaultTtl: 600 } as CredentialFormValues);
    setEditorOpen(true);
  }

  function openEdit(credential: DnsCredential) {
    setEditing(credential);
    form.resetFields();
    form.setFieldsValue({
      name: credential.name,
      provider: credential.provider,
      zoneName: credential.zoneName,
      defaultTtl: credential.defaultTtl
    });
    setEditorOpen(true);
  }

  async function submit() {
    const values = await form.validateFields();
    const key = editing ? `save:${editing.id}` : 'create';
    setActionKey(key);
    try {
      await api.saveDnsCredential(values, editing?.id);
      message.success(editing ? t('actions.dnsApiUpdated') : t('actions.dnsApiCreated'));
      setEditorOpen(false);
      setEditing(null);
      form.resetFields();
      await loadCredentials();
    } catch (error) {
      message.error(error instanceof Error ? error.message : t('common.error'));
    } finally {
      setActionKey('');
    }
  }

  async function testCredential(credential: DnsCredential) {
    setActionKey(`test:${credential.id}`);
    try {
      const result = await api.testDnsCredential(credential.id);
      if (result.ok) message.success(result.detail || t('actions.dnsApiTestCompleted'));
      else message.error(result.error || t('common.error'));
    } catch (error) {
      message.error(error instanceof Error ? error.message : t('common.error'));
    } finally {
      setActionKey('');
    }
  }

  async function deleteCredential(credential: DnsCredential) {
    setActionKey(`delete:${credential.id}`);
    try {
      await api.deleteDnsCredential(credential.id);
      message.success(t('actions.dnsApiDeleted'));
      if (requestedCredentialId === credential.id) closeDetail();
      await loadCredentials();
    } catch (error) {
      message.error(error instanceof Error ? error.message : t('common.error'));
    } finally {
      setActionKey('');
    }
  }

  function openDetail(credential: DnsCredential) {
    const next = new URLSearchParams(searchParams);
    next.set('credentialId', String(credential.id));
    setSearchParams(next, {
      state: detailHistoryLocation(`${location.pathname}${location.search}`, 1)
    });
  }

  function closeDetail() {
    const historyState = detailHistoryState(location.state);
    if (historyState) {
      navigate(-historyState.depth);
      return;
    }
    const next = new URLSearchParams(searchParams);
    next.delete('credentialId');
    setSearchParams(next, { replace: true, state: null });
  }

  const columns: ColumnsType<DnsCredential> = [
    {
      title: t('tokens.name'),
      dataIndex: 'name',
      render: (value: string) => <Typography.Text strong>{value}</Typography.Text>
    },
    { title: 'Provider', dataIndex: 'provider', render: providerLabel },
    {
      title: t('dnsApi.zone'),
      dataIndex: 'zoneName',
      render: (value: string) => <Typography.Text code>{value}</Typography.Text>
    },
    { title: 'TTL', dataIndex: 'defaultTtl', width: 100 },
    {
      title: t('common.status'),
      dataIndex: 'credentialSet',
      width: 140,
      render: (value?: boolean) => (
        <StatusPill tone={value === false ? 'warning' : 'success'}>
          {value === false ? t('common.notConfigured') : t('smtp.passwordSet')}
        </StatusPill>
      )
    },
    {
      title: t('tokens.createdAt'),
      dataIndex: 'updatedAt',
      width: 190,
      render: (value: string) => value ? new Date(value).toLocaleString() : '—'
    },
    {
      title: t('common.actions'),
      width: 220,
      render: (_, credential) => (
        <Space onClick={(event) => event.stopPropagation()}>
          <Button
            aria-label={`${t('domains.test')} ${credential.name}`}
            icon={<ThunderboltOutlined />}
            loading={actionKey === `test:${credential.id}`}
            onClick={() => void testCredential(credential)}
          >
            {t('domains.test')}
          </Button>
          <Button
            aria-label={`${t('common.edit')} ${credential.name}`}
            icon={<EditOutlined />}
            onClick={() => openEdit(credential)}
          />
          <Popconfirm title={t('dnsApi.deleteConfirm')} onConfirm={() => void deleteCredential(credential)}>
            <Button
              aria-label={`${t('common.delete')} ${credential.name}`}
              danger
              icon={<DeleteOutlined />}
              loading={actionKey === `delete:${credential.id}`}
            />
          </Popconfirm>
        </Space>
      )
    }
  ];

  return (
    <Space direction="vertical" size={20} className="full-width">
      <PageHeader
        title={t('dnsApi.title')}
        subtitle={t('dnsApi.secretHint')}
        extra={
          <Button type="primary" icon={<PlusOutlined />} onClick={openCreate} style={{ minHeight: 44 }}>
            {t('dnsApi.create')}
          </Button>
        }
      />

      {loadError ? (
        <Alert
          type="error"
          showIcon
          message={loadError}
          action={<Button icon={<ReloadOutlined />} onClick={() => void loadCredentials()}>{t('common.refresh')}</Button>}
        />
      ) : null}

      {loadError && !credentials.length ? null : (
        <SectionCard title={t('dnsApi.title')} extra={<StatusPill tone="neutral">{credentials.length}</StatusPill>}>
          {loading ? <Skeleton active paragraph={{ rows: 5 }} /> : credentials.length ? (
            <Table
              rowKey="id"
              columns={columns}
              dataSource={credentials}
              scroll={{ x: 940 }}
              onRow={(credential) => ({
                onClick: () => openDetail(credential),
                style: { cursor: 'pointer' },
                tabIndex: 0,
                onKeyDown: (event) => {
                  if (event.target !== event.currentTarget) return;
                  if (event.key === 'Enter' || event.key === ' ') {
                    event.preventDefault();
                    openDetail(credential);
                  }
                }
              })}
            />
          ) : (
            <EmptyState
              description={t('dnsApi.secretHint')}
              action={<Button icon={<PlusOutlined />} onClick={openCreate}>{t('dnsApi.create')}</Button>}
            />
          )}
        </SectionCard>
      )}

      <Drawer
        title={editing ? `${t('dnsApi.editTitle')} ${editing.name}` : t('dnsApi.createTitle')}
        width={560}
        open={editorOpen}
        onClose={() => setEditorOpen(false)}
        destroyOnHidden
        footer={
          <Space style={{ display: 'flex', justifyContent: 'flex-end' }}>
            <Button onClick={() => setEditorOpen(false)}>{t('common.cancel')}</Button>
            <Button type="primary" loading={actionKey === 'create' || actionKey.startsWith('save:')} onClick={() => void submit()}>
              {editing ? t('dnsApi.save') : t('dnsApi.create')}
            </Button>
          </Space>
        }
      >
        <Alert type="info" showIcon message={t('dnsApi.secretHint')} style={{ marginBottom: 20 }} />
        <Form form={form} layout="vertical" initialValues={{ provider: 'cloudflare', defaultTtl: 600 }}>
          <Form.Item name="name" label={t('tokens.name')} rules={[{ required: true, message: t('tokens.nameRequired') }]}>
            <Input placeholder="Primary Cloudflare" />
          </Form.Item>
          <Form.Item name="provider" label="Provider" rules={[{ required: true }]}>
            <Select options={providerOptions} />
          </Form.Item>
          <Form.Item
            name="zoneName"
            label={t('dnsApi.zone')}
            rules={[{ required: true, message: t('dnsApi.zoneRequired') }]}
            extra={provider === 'cloudflare' ? t('dnsApi.cloudflareZoneExtra') : t('dnsApi.zoneExtra')}
          >
            <Input placeholder="example.com" />
          </Form.Item>
          <Form.Item name="defaultTtl" label="TTL">
            <InputNumber min={60} max={86400} className="full-width" />
          </Form.Item>
          {provider === 'cloudflare' ? (
            <>
              <Form.Item name="apiToken" label="Cloudflare API Token" extra={editing ? t('dnsApi.keepSecret') : t('dnsApi.tokenExtra')}>
                <Input.Password autoComplete="new-password" />
              </Form.Item>
              <Form.Item name="zoneId" label="Cloudflare Zone ID"><Input autoComplete="off" /></Form.Item>
            </>
          ) : null}
          {provider === 'aliyun' ? (
            <>
              <Form.Item name="accessKeyId" label="AccessKeyId" extra={editing ? t('dnsApi.keepSecret') : undefined}><Input autoComplete="off" /></Form.Item>
              <Form.Item name="accessKeySecret" label="AccessKeySecret" extra={editing ? t('dnsApi.keepSecret') : undefined}><Input.Password autoComplete="new-password" /></Form.Item>
            </>
          ) : null}
          {provider === 'dnspod' ? (
            <>
              <Form.Item name="secretId" label="SecretId" extra={editing ? t('dnsApi.keepSecret') : undefined}><Input autoComplete="off" /></Form.Item>
              <Form.Item name="secretKey" label="SecretKey" extra={editing ? t('dnsApi.keepSecret') : undefined}><Input.Password autoComplete="new-password" /></Form.Item>
            </>
          ) : null}
        </Form>
      </Drawer>

      <Drawer title={selected?.name || t('dnsApi.title')} width={480} open={Boolean(requestedCredentialId)} onClose={closeDetail}>
        {loading && !selected ? <Skeleton active paragraph={{ rows: 5 }} /> : selected ? (
          <Descriptions bordered column={1} size="small">
            <Descriptions.Item label="Provider">{providerLabel(selected.provider)}</Descriptions.Item>
            <Descriptions.Item label={t('dnsApi.zone')}><Typography.Text code>{selected.zoneName}</Typography.Text></Descriptions.Item>
            <Descriptions.Item label="TTL">{selected.defaultTtl}</Descriptions.Item>
            <Descriptions.Item label={t('common.status')}>
              <StatusPill tone={selected.credentialSet === false ? 'warning' : 'success'}>
                {selected.credentialSet === false ? t('common.notConfigured') : t('smtp.passwordSet')}
              </StatusPill>
            </Descriptions.Item>
            <Descriptions.Item label={t('tokens.createdAt')}>{new Date(selected.createdAt).toLocaleString()}</Descriptions.Item>
          </Descriptions>
        ) : loadError && requestedCredentialId ? (
          <Alert type="error" showIcon message={loadError} action={<Button icon={<ReloadOutlined />} onClick={() => void loadCredentials()}>{t('common.refresh')}</Button>} />
        ) : requestedCredentialId ? <EmptyState description={t('common.notFound')} /> : null}
      </Drawer>
    </Space>
  );
}

const providerOptions = [
  { value: 'cloudflare', label: 'Cloudflare' },
  { value: 'aliyun', label: 'Aliyun DNS' },
  { value: 'dnspod', label: 'Tencent DNSPod' }
];

function providerLabel(provider: string) {
  return {
    cloudflare: <StatusPill tone="info">Cloudflare</StatusPill>,
    aliyun: <StatusPill tone="warning">Aliyun DNS</StatusPill>,
    dnspod: <StatusPill tone="neutral">Tencent DNSPod</StatusPill>
  }[provider] || <StatusPill tone="neutral">{provider}</StatusPill>;
}

function positiveInteger(value: string | null) {
  const parsed = Number(value);
  return Number.isInteger(parsed) && parsed > 0 ? parsed : null;
}
