import { App as AntApp, ConfigProvider } from 'antd';
import { render, screen, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { MemoryRouter, Route, Routes } from 'react-router-dom';
import { describe, expect, it, vi } from 'vitest';

import { AppContext } from '../../src/frontend/app-context';
import { I18nProvider } from '../../src/frontend/i18n/react';
import { api } from '../../src/frontend/services/api';
import { mailhubTheme } from '../../src/frontend/theme';
import Domains from '../../src/pages/Domains';
import type { AppContextValue } from '../../src/frontend/app-context';
import type { Domain } from '../../src/frontend/types';

describe('Domains dangerous actions', () => {
  it('requires the exact domain before deletion', async () => {
    const user = userEvent.setup();
    const deleteDomain = vi.spyOn(api, 'deleteDomain').mockResolvedValue({ deleted: true });
    vi.spyOn(api, 'domains').mockResolvedValue({ domains: [domain] });
    vi.spyOn(api, 'dnsCredentials').mockResolvedValue({ credentials: [] });
    vi.spyOn(api, 'smtpRelays').mockResolvedValue({ relays: [] });
    vi.spyOn(api, 'events').mockResolvedValue({ events: [], total: 0, page: 1, pageSize: 100 });

    renderPage();
    await screen.findAllByText('example.com');
    await user.click(screen.getByRole('button', { name: '更多操作 example.com' }));
    await user.click(await screen.findByText('删除域名'));

    const dialog = await screen.findByRole('dialog');
    const confirmation = within(dialog).getByLabelText('域名删除确认');
    const destructiveButton = within(dialog).getByRole('button', { name: '删除域名' });
    expect((destructiveButton as HTMLButtonElement).disabled).toBe(true);

    await user.type(confirmation, 'wrong.example.com');
    expect((destructiveButton as HTMLButtonElement).disabled).toBe(true);
    await user.clear(confirmation);
    await user.type(confirmation, 'example.com');
    expect((destructiveButton as HTMLButtonElement).disabled).toBe(false);
    await user.click(destructiveButton);

    await waitFor(() => expect(deleteDomain).toHaveBeenCalledWith(7));
  });
});

function renderPage() {
  const context: AppContextValue = {
    user: { id: 1, username: 'operator', email: 'operator@example.test', role: 'admin', status: 'active' },
    config,
    refreshBootstrap: vi.fn(async () => undefined),
    logout: vi.fn(async () => undefined)
  };
  return render(
    <ConfigProvider theme={mailhubTheme}>
      <AntApp>
        <I18nProvider>
          <AppContext.Provider value={context}>
            <MemoryRouter initialEntries={['/domains']}>
              <Routes><Route path="/domains" element={<Domains />} /></Routes>
            </MemoryRouter>
          </AppContext.Provider>
        </I18nProvider>
      </AntApp>
    </ConfigProvider>
  );
}

const config = {
  appBaseUrl: 'https://mail.example.test',
  mailHostname: 'mail.example.test',
  sendingIp: '192.0.2.10',
  defaultSpfMechanisms: '',
  dmarcPolicy: 'none',
  dmarcRua: '',
  registrationRequiresApproval: false,
  sendRequiresVerified: true,
  engagementTrackingEnabled: true,
  listUnsubscribeMailto: '',
  listUnsubscribeUrl: '',
  listUnsubscribePostEnabled: false,
  feedbackIdEnabled: false,
  reportAbuseTo: '',
  csaComplaintsTo: '',
  bounceAddress: '',
  bounceEnvelopeEnabled: false
};

const domain: Domain = {
  id: 7,
  userId: 1,
  dnsCredentialId: null,
  smtpRelayId: null,
  domain: 'example.com',
  selector: 'mh202607',
  verificationToken: 'verification',
  dkimPublic: 'public-key',
  senderHost: 'mail.example.com',
  sendingIp: '192.0.2.10',
  spfExtra: '',
  dmarcPolicy: 'none',
  dmarcRua: '',
  catchAllAddress: '',
  status: {
    verified: true,
    checkedAt: '2026-07-14T00:00:00.000Z',
    records: [
      { key: 'spf', label: 'SPF', host: 'example.com', type: 'TXT', status: 'ok' },
      { key: 'dkim', label: 'DKIM', host: 'mh._domainkey.example.com', type: 'TXT', status: 'ok' },
      { key: 'dmarc', label: 'DMARC', host: '_dmarc.example.com', type: 'TXT', status: 'ok' }
    ]
  },
  createdAt: '2026-07-14T00:00:00.000Z',
  updatedAt: '2026-07-14T00:00:00.000Z'
};
