import { describe, it, expect, vi, beforeEach } from 'vitest';
import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { renderWithProviders } from '../test/utils';

vi.mock('sonner', () => ({ toast: { success: vi.fn(), error: vi.fn() } }));
vi.mock('../hooks/usePermissions', () => ({ usePermissions: () => ({ can: () => true }) }));

const setOverride = { mutate: vi.fn(), isPending: false };
const removeOverride = { mutate: vi.fn(), isPending: false };

let holidays: Array<{ uuid: string; date: number; jalali_date: string; title: string }> = [];
let overrides: Array<{ uuid: string; date: number; is_working: boolean; note: string | null }> = [];
let error: string | null = null;

vi.mock('../hooks/useResourceCalendar', () => ({
  useHolidays: () => ({ holidays, overrides, loading: false, error, setOverride, removeOverride }),
}));

import HolidaysSettingsPage from './HolidaysSettingsPage';

// ۱۴۰۵-۰۵-۱۳ ⇒ ۲۰۲۶-۰۸-۰۴
const MARTYRDOM = {
  uuid: 'h-1',
  date: Math.floor(new Date(2026, 7, 4).getTime() / 1000),
  jalali_date: '1405-05-13',
  title: 'شهادت',
};

describe('HolidaysSettingsPage', () => {
  beforeEach(() => {
    holidays = [MARTYRDOM];
    overrides = [];
    error = null;
    vi.clearAllMocks();
  });

  /**
   * پیش‌تر دو ستون تاریخ بود: «تاریخ» رشتهٔ خامِ `1405-05-13` و «میلادی» که با
   * formatDate همان روز را **شمسی** می‌داد. یک تاریخ، دو بار، با برچسبی که دروغ می‌گفت.
   */
  it('یک ستون تاریخ دارد و شمسی است، نه رشتهٔ خام', () => {
    renderWithProviders(<HolidaysSettingsPage />);

    expect(screen.getByText('۱۴۰۵/۰۵/۱۳')).toBeInTheDocument();
    expect(screen.queryByText('1405-05-13')).not.toBeInTheDocument();
    expect(screen.queryByText('میلادی')).not.toBeInTheDocument();
  });

  it('روز تعطیل را برای این محیط باز می‌کند', async () => {
    const user = userEvent.setup();
    renderWithProviders(<HolidaysSettingsPage />);

    await user.click(screen.getByRole('button', { name: 'این روز باز است' }));

    expect(setOverride.mutate).toHaveBeenCalledWith({ date: MARTYRDOM.date, is_working: true });
  });

  it('روزِ استثنا خورده را دوباره تعطیل می‌کند', async () => {
    overrides = [{ uuid: 'o-1', date: MARTYRDOM.date, is_working: true, note: null }];
    const user = userEvent.setup();
    renderWithProviders(<HolidaysSettingsPage />);

    expect(screen.getByText('باز است')).toBeInTheDocument();
    await user.click(screen.getByRole('button', { name: 'تعطیل کن' }));

    expect(removeOverride.mutate).toHaveBeenCalledWith('o-1');
  });

  /** بدون این، درخواستِ شکست‌خورده مثل «سالِ خالی» دیده می‌شد. */
  it('خطای سرور را نشان می‌دهد، نه سالِ خالی', () => {
    error = 'خطای داخلی سرور';
    holidays = [];
    renderWithProviders(<HolidaysSettingsPage />);

    expect(screen.getByText('خطای داخلی سرور')).toBeInTheDocument();
  });

  it('سالِ خالی را با ارقام فارسی می‌گوید', () => {
    holidays = [];
    renderWithProviders(<HolidaysSettingsPage />, { route: '/admin/holidays?year=1404' });

    expect(screen.getByText('برای سال ۱۴۰۴ تعطیلی ثبت نشده است')).toBeInTheDocument();
  });

  /** انتخابگر سال و ورودی تاریخ هر دو باید نام دسترس‌پذیر داشته باشند. */
  it('فیلدها نام دارند', () => {
    renderWithProviders(<HolidaysSettingsPage />);

    expect(screen.getByRole('button', { name: 'تاریخ تعطیلی' })).toBeInTheDocument();
    expect(screen.getByLabelText('توضیح')).toBeInTheDocument();
  });

  /** ورودی نیتیو میلادی بود و در دارک‌مود سفید می‌ماند؛ باید رفته باشد. */
  it('ورودی تاریخ نیتیو ندارد', () => {
    const { container } = renderWithProviders(<HolidaysSettingsPage />);

    expect(container.querySelector('input[type="date"]')).toBeNull();
  });

  it('تعطیلی محیط را با تاریخ و توضیح ثبت می‌کند', async () => {
    const user = userEvent.setup();
    renderWithProviders(<HolidaysSettingsPage />);

    // بدون تاریخ، ثبت ممکن نیست.
    expect(screen.getByRole('button', { name: 'افزودن' })).toBeDisabled();

    await user.type(screen.getByLabelText('توضیح'), 'تعطیلی داخلی');
    expect(screen.getByRole('button', { name: 'افزودن' })).toBeDisabled();
  });
});
