// @vitest-environment jsdom
import '../../test/dom-setup';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

vi.mock('../../App', () => ({
  useAuthState: () => ({ mode: 'authenticated', user: { id: 'u1', role: 'admin' } }),
}));

vi.mock('../../api', () => ({
  fetchSkills: vi.fn(async () => [
    { name: 'sys-a', description: 'a system skill', triggers: [], source: 'system', hasDir: true },
  ]),
  fetchSkillDetail: vi.fn(async () => ({
    name: 'sys-a',
    description: 'a system skill',
    triggers: [],
    source: 'system',
    hasDir: true,
    content: 'body',
    raw: '---\nname: sys-a\n---\n\nbody',
    files: [],
    findings: [],
    maxSeverity: 'none',
  })),
  createSkill: vi.fn(),
  updateSkill: vi.fn(),
  deleteSkill: vi.fn(),
  installSkillFromUrl: vi.fn(),
}));

import { SkillsForm } from './SkillsForm';
import { deleteSkill } from '../../api';

function renderForm() {
  const qc = new QueryClient({ defaultOptions: { queries: { retry: false }, mutations: { retry: false } } });
  return render(
    <QueryClientProvider client={qc}>
      <SkillsForm />
    </QueryClientProvider>,
  );
}

beforeEach(() => {
  vi.clearAllMocks();
  vi.stubGlobal('confirm', vi.fn(() => true));
});

describe('SkillsForm delete errors', () => {
  it('shows a delete failure next to the action buttons instead of only at the top', async () => {
    vi.mocked(deleteSkill).mockRejectedValueOnce(new Error('Skill not found'));
    renderForm();

    await userEvent.click(await screen.findByText('sys-a'));
    await userEvent.click(await screen.findByRole('button', { name: 'Delete' }));

    expect(deleteSkill).toHaveBeenCalledWith('sys-a', 'system', undefined);
    const err = await screen.findByTestId('skill-action-error');
    expect(err).toHaveTextContent('Skill not found');
    // The skill stays selected so the user sees the failure in place.
    expect(screen.getByRole('button', { name: 'Delete' })).toBeInTheDocument();
  });

  it('clears the inline error when selecting another skill', async () => {
    vi.mocked(deleteSkill).mockRejectedValueOnce(new Error('Skill not found'));
    renderForm();

    await userEvent.click(await screen.findByText('sys-a'));
    await userEvent.click(await screen.findByRole('button', { name: 'Delete' }));
    await screen.findByTestId('skill-action-error');

    // Re-select from the list (the detail heading also renders the name, so
    // pick the list entry via its description line).
    await userEvent.click(screen.getByText('a system skill', { selector: 'div' }));
    await waitFor(() => {
      expect(screen.queryByTestId('skill-action-error')).not.toBeInTheDocument();
    });
  });

  it('does not keep showing a stale delete error after a later successful edit', async () => {
    const { updateSkill } = await import('../../api');
    vi.mocked(deleteSkill).mockRejectedValueOnce(new Error('Skill not found'));
    vi.mocked(updateSkill).mockResolvedValueOnce({ ok: true });
    renderForm();

    await userEvent.click(await screen.findByText('sys-a'));
    await userEvent.click(await screen.findByRole('button', { name: 'Delete' }));
    await screen.findByTestId('skill-action-error');

    await userEvent.click(screen.getByRole('button', { name: 'Edit' }));
    await userEvent.click(await screen.findByRole('button', { name: 'Save' }));

    await waitFor(() => {
      expect(screen.queryByTestId('skill-action-error')).not.toBeInTheDocument();
    });
  });

  it('deletes and clears the selection on success', async () => {
    vi.mocked(deleteSkill).mockResolvedValueOnce(undefined);
    renderForm();

    await userEvent.click(await screen.findByText('sys-a'));
    await userEvent.click(await screen.findByRole('button', { name: 'Delete' }));

    await waitFor(() => {
      expect(screen.queryByRole('button', { name: 'Delete' })).not.toBeInTheDocument();
    });
    expect(screen.queryByTestId('skill-action-error')).not.toBeInTheDocument();
  });
});
