
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import { Suspense } from "react";
import JobApplicationPage from "./page";
import { jobsApi, applicationsApi } from "@/lib/api";
import { useNotify } from "@/contexts/notification-context";
import { useRouter } from "next/navigation";

// Mock dependencies
jest.mock("@/lib/i18n", () => ({
    useTranslation: () => ({
        t: (key: string) => key,
        locale: "en",
        setLocale: jest.fn(),
    }),
    useI18n: () => ({
        t: (key: string) => key,
        locale: "en",
        setLocale: jest.fn(),
    }),
}));

jest.mock("next/navigation", () => ({
    useRouter: jest.fn(),
}));

jest.mock("@/lib/api", () => ({
    jobsApi: {
        getById: jest.fn(),
    },
    applicationsApi: {
        create: jest.fn(),
    },
}));

jest.mock("@/contexts/notification-context", () => ({
    useNotify: jest.fn(),
}));

jest.mock("@/components/ui/progress", () => ({
    Progress: () => <div data-testid="progress" />,
}));

jest.mock("framer-motion", () => ({
    motion: { div: ({ children }: any) => <div>{children}</div> },
    AnimatePresence: ({ children }: any) => <>{children}</>,
}));

jest.mock("@/components/ui/select", () => ({
    Select: ({ onValueChange, children }: any) => (
        <div data-testid="select">
            <button data-testid="select-option-3k" onClick={() => onValueChange("up-to-3k")}>
                Select 3k
            </button>
            {children}
        </div>
    ),
    SelectTrigger: ({ children }: any) => <button>{children}</button>,
    SelectValue: ({ placeholder }: any) => <span>{placeholder}</span>,
    SelectContent: ({ children }: any) => <div>{children}</div>,
    SelectItem: ({ children }: any) => <div>{children}</div>,
}));

describe("JobApplicationPage", () => {
    const mockPush = jest.fn();
    const mockNotify = { error: jest.fn(), success: jest.fn(), info: jest.fn() };
    const mockJob = {
        id: "job-123",
        title: "Software Engineer",
        companyName: "Tech Corp",
        location: "Remote",
    };

    beforeEach(() => {
        jest.clearAllMocks();
        (useRouter as jest.Mock).mockReturnValue({ push: mockPush });
        (useNotify as jest.Mock).mockReturnValue(mockNotify);
        (jobsApi.getById as jest.Mock).mockResolvedValue(mockJob);
        window.scrollTo = jest.fn();
    });

    it("renders job title and company info", async () => {
        const params: any = Promise.resolve({ id: "job-123" });
        params.status = "fulfilled";
        params.value = { id: "job-123" };

        render(
            <Suspense fallback={<div>Loading...</div>}>
                <JobApplicationPage params={params} />
            </Suspense>
        );

        expect(await screen.findByText("Application: Software Engineer")).toBeInTheDocument();
        expect(screen.getByText(/Tech Corp/)).toBeInTheDocument();
    });

    it("validates step 1 fields", async () => {
        const params: any = Promise.resolve({ id: "job-123" });
        params.status = "fulfilled";
        params.value = { id: "job-123" };

        render(
            <Suspense fallback={<div>Loading...</div>}>
                <JobApplicationPage params={params} />
            </Suspense>
        );

        // Wait for load
        expect(await screen.findByText("Application: Software Engineer")).toBeInTheDocument();

        // Try next empty
        const nextBtn = screen.getByRole("button", { name: /Next step/i });
        fireEvent.click(nextBtn);
        expect(mockNotify.error).toHaveBeenCalledWith("Required fields", expect.any(String));

        // Fill fields
        fireEvent.change(screen.getByLabelText(/Full name/i), { target: { value: "John Doe" } });
        fireEvent.change(screen.getByLabelText(/Email/i), { target: { value: "john@example.com" } });
        fireEvent.change(screen.getByLabelText(/Phone/i), { target: { value: "11999999999" } });

        // Forgot checkbox
        fireEvent.click(nextBtn);
        expect(mockNotify.error).toHaveBeenCalledWith("Privacy policy", expect.any(String));

        // Check checkbox
        const policyLabel = screen.getByText(/I have read and agree to the/i);
        fireEvent.click(policyLabel);

        fireEvent.click(nextBtn);

        // Should move to step 2
        await waitFor(() => expect(screen.getByText("Resume (CV) *")).toBeInTheDocument());
    });

    it("submits application successfully", async () => {
        const params: any = Promise.resolve({ id: "job-123" });
        params.status = "fulfilled";
        params.value = { id: "job-123" };

        render(
            <Suspense fallback={<div>Loading...</div>}>
                <JobApplicationPage params={params} />
            </Suspense>
        );

        // Wait for load
        expect(await screen.findByText("Application: Software Engineer")).toBeInTheDocument();
        await waitFor(() => expect(screen.getByLabelText(/Full name/i)).toBeInTheDocument());

        // Step 1
        fireEvent.change(screen.getByLabelText(/Full name/i), { target: { value: "John Doe" } });
        fireEvent.change(screen.getByLabelText(/Email/i), { target: { value: "john@example.com" } });
        fireEvent.change(screen.getByLabelText(/Phone/i), { target: { value: "11999999999" } });
        fireEvent.click(screen.getByText(/I have read and agree to the/i));
        fireEvent.click(screen.getByRole("button", { name: /Next step/i }));

        // Step 2
        await waitFor(() => expect(screen.getByText("Resume (CV) *")).toBeInTheDocument());
        fireEvent.click(screen.getByRole("button", { name: /Next step/i }));

        // Wait for Step 3
        await waitFor(() => expect(screen.getByText("Salary expectation *")).toBeInTheDocument());

        // Step 3
        const trigger = screen.getByText("Select a range");
        fireEvent.click(trigger);
        fireEvent.click(screen.getByTestId("select-option-3k"));

        fireEvent.click(screen.getByLabelText("Yes, I do")); // Radio

        fireEvent.click(screen.getByRole("button", { name: /Next step/i }));

        await waitFor(() => expect(screen.getByLabelText(/Why do you want to work/i)).toBeInTheDocument());

        // Step 4
        // Why Us and Availability
        fireEvent.change(screen.getByLabelText(/Why do you want to work/i), { target: { value: "Because I like it." } });
        fireEvent.click(screen.getByLabelText("Immediate start"));

        // Submit
        fireEvent.click(screen.getByRole("button", { name: /Submit application/i }));

        await waitFor(() => {
            expect(applicationsApi.create).toHaveBeenCalledWith(expect.objectContaining({
                name: "John Doe",
                email: "john@example.com",
                jobId: "job-123"
            }));
            expect(mockNotify.success).toHaveBeenCalled();
            expect(mockPush).toHaveBeenCalledWith("/dashboard/my-applications");
        });
    });
});
