import React from 'react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { I18nextProvider } from 'react-i18next';
import { ThemeProvider } from 'styled-components';
import {
  canSubmitDepartmentInviteRoleFields,
  DepartmentInviteRoleFields,
} from '@/features/admin/components/DepartmentInviteRoleFields';
import * as departmentAdminService from '@/features/admin/services/departmentAdminService';
import i18n from '@/locales/i18n';
import { LocaleProvider } from '@/app/providers/LocaleProvider';
import { lightTheme } from '@/styles/theme';

vi.mock('@/features/admin/services/departmentAdminService', async () => {
  const actual = await vi.importActual<typeof departmentAdminService>(
    '@/features/admin/services/departmentAdminService',
  );
  return {
    ...actual,
    listDepartmentHeads: vi.fn().mockResolvedValue([]),
  };
});

function renderFields(
  props: Partial<React.ComponentProps<typeof DepartmentInviteRoleFields>> = {},
) {
  const onRoleNameChange = vi.fn();
  const onDepartmentHeadChange = vi.fn();
  const onTransferAcknowledgedChange = vi.fn();

  const queryClient = new QueryClient({
    defaultOptions: { queries: { retry: false } },
  });

  render(
    <QueryClientProvider client={queryClient}>
      <I18nextProvider i18n={i18n}>
        <LocaleProvider>
          <ThemeProvider theme={lightTheme}>
            <DepartmentInviteRoleFields
              roleName="agent"
              isDepartmentHead={false}
              onRoleNameChange={onRoleNameChange}
              onDepartmentHeadChange={onDepartmentHeadChange}
              canSetOfficialHead
              showManagerOption
              departmentId="dept-1"
              transferAcknowledged={false}
              onTransferAcknowledgedChange={onTransferAcknowledgedChange}
              {...props}
            />
          </ThemeProvider>
        </LocaleProvider>
      </I18nextProvider>
    </QueryClientProvider>,
  );

  return { onRoleNameChange, onDepartmentHeadChange, onTransferAcknowledgedChange };
}

describe('DepartmentInviteRoleFields', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    vi.mocked(departmentAdminService.listDepartmentHeads).mockResolvedValue([]);
  });

  it('shows renamed department role and official head labels', async () => {
    renderFields();
    expect(await screen.findByText('Department Role')).toBeInTheDocument();
    expect(screen.getByText('Official Department Head')).toBeInTheDocument();
    expect(screen.getByText('Agent')).toBeInTheDocument();
    expect(screen.getByText('Viewer')).toBeInTheDocument();
    expect(screen.getByText('Manager')).toBeInTheDocument();
  });

  it('shows manager-without-head notice when manager is selected without official head', async () => {
    renderFields({ roleName: 'manager', isDepartmentHead: false });
    expect(
      await screen.findByText(
        /Manager gives operational management permissions, but this user will not be treated as the official Department Head\./,
      ),
    ).toBeInTheDocument();
  });

  it('shows ownership notice when official head is checked with agent role', async () => {
    renderFields({ roleName: 'agent', isDepartmentHead: true });
    expect(
      await screen.findByText(
        /This user will be treated as the official Department Head and will receive department ownership permissions\./,
      ),
    ).toBeInTheDocument();
  });

  it('requires transfer acknowledgement when department already has a head', async () => {
    vi.mocked(departmentAdminService.listDepartmentHeads).mockResolvedValue([
      {
        id: 'membership-1',
        department_id: 'dept-1',
        user_id: 'user-1',
        is_department_head: true,
      },
    ]);

    renderFields({ isDepartmentHead: true });

    expect(
      await screen.findByText(/This department already has an Official Department Head\./),
    ).toBeInTheDocument();
    expect(
      screen.getByText(/I understand that department ownership will transfer to this user\./),
    ).toBeInTheDocument();
    expect(
      canSubmitDepartmentInviteRoleFields(true, 1, false),
    ).toBe(false);
    expect(
      canSubmitDepartmentInviteRoleFields(true, 1, true),
    ).toBe(true);
  });

  it('hides official head checkbox when inviter cannot set head', async () => {
    renderFields({ canSetOfficialHead: false });
    expect(await screen.findByText('Department Role')).toBeInTheDocument();
    expect(screen.queryByText('Official Department Head')).not.toBeInTheDocument();
  });

  it('allows checking official head checkbox', async () => {
    const user = userEvent.setup();
    const { onDepartmentHeadChange } = renderFields();

    await user.click(screen.getByRole('checkbox'));
    expect(onDepartmentHeadChange).toHaveBeenCalledWith(true);
  });
});
