import { render, screen, waitFor } from "@testing-library/react"
import userEvent from "@testing-library/user-event"
import { MemoryRouter } from "react-router-dom"
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
import { SchedulePage } from "./SchedulePage"
import { AuthProvider } from "@/auth/AuthContext"
import { api } from "@/api/client"
import { vi, beforeEach, test, expect } from "vitest"

const PROJECT_ID = "p1"

function renderPage() {
  const qc = new QueryClient()
  return render(
    <QueryClientProvider client={qc}>
      <AuthProvider>
        <MemoryRouter initialEntries={["/schedule"]}>
          <SchedulePage />
        </MemoryRouter>
      </AuthProvider>
    </QueryClientProvider>,
  )
}

beforeEach(() => {
  vi.restoreAllMocks()
  vi.spyOn(api.auth, "me").mockResolvedValue({
    user: { id: "u1", email: "a@b.com" },
    project: { id: PROJECT_ID, name: "Default" },
  })
  vi.spyOn(api, "getSchedule").mockResolvedValue({ intervalSeconds: 120, enabled: true })
})

test("показывает текущий интервал и enabled", async () => {
  renderPage()

  const intervalInput = await screen.findByLabelText(/интервал/i)
  expect(intervalInput).toHaveValue(120)
  expect(screen.getByRole("checkbox", { name: /включ/i })).toBeChecked()
})

test("сохранение вызывает updateSchedule с новыми значениями", async () => {
  const updateSpy = vi.spyOn(api, "putSchedule").mockResolvedValue({ intervalSeconds: 300, enabled: false })
  const user = userEvent.setup()
  renderPage()

  const intervalInput = await screen.findByLabelText(/интервал/i)
  await user.clear(intervalInput)
  await user.type(intervalInput, "300")
  await user.click(screen.getByRole("checkbox", { name: /включ/i }))
  await user.click(screen.getByRole("button", { name: /сохранить/i }))

  await waitFor(() =>
    expect(updateSpy).toHaveBeenCalledWith(PROJECT_ID, { intervalSeconds: 300, enabled: false }),
  )
})

test("валидация: интервал меньше 60 блокирует сохранение", async () => {
  const updateSpy = vi.spyOn(api, "putSchedule").mockResolvedValue({ intervalSeconds: 120, enabled: true })
  const user = userEvent.setup()
  renderPage()

  const intervalInput = await screen.findByLabelText(/интервал/i)
  await user.clear(intervalInput)
  await user.type(intervalInput, "30")
  await user.click(screen.getByRole("button", { name: /сохранить/i }))

  expect(await screen.findByRole("alert")).toHaveTextContent(/60/)
  expect(updateSpy).not.toHaveBeenCalled()
})

test("ошибка сохранения отображается пользователю", async () => {
  vi.spyOn(api, "putSchedule").mockRejectedValue(new Error("Не удалось сохранить расписание"))
  const user = userEvent.setup()
  renderPage()

  const intervalInput = await screen.findByLabelText(/интервал/i)
  await user.clear(intervalInput)
  await user.type(intervalInput, "180")
  await user.click(screen.getByRole("button", { name: /сохранить/i }))

  expect(await screen.findByRole("alert")).toHaveTextContent("Не удалось сохранить расписание")
})
