import { render, screen, waitFor } from "@testing-library/react"
import { MemoryRouter } from "react-router-dom"
import type { User } from "@/lib/mock-data"
import { MEMORY_ROUTER_TEST_FUTURE } from "@/testing/reactRouterTest"
import { ConstitutionalChangeDetails } from "../pages/ConstitutionalChangeDetails"

jest.mock("sonner", () => ({
    toast: {
        error: jest.fn(),
        success: jest.fn(),
    },
}))

const mockGetConstitutionalChangeById = jest.fn()
const mockGetAuditLogs = jest.fn()

jest.mock("@/api/API", () => ({
    API: {
        getConstitutionalChangeById: (...args: unknown[]) =>
            mockGetConstitutionalChangeById(...args),
        getAuditLogs: (...args: unknown[]) => mockGetAuditLogs(...args),
        updateConstitutionalChange: jest.fn(),
        uploadConstitutionalDocuments: jest.fn(),
    },
}))

function buildAsmUser(): User {
    return {
        id: "u1",
        name: "ASM Person",
        email: "asm@test.com",
        password: "",
        role: "ASM",
        roleCode: "ASM",
    }
}

function minimalRequest() {
    return {
        id: "req-internal-id",
        requestId: "CCR-500",
        status: "Submitted",
        currentStage: "Submitted",
        changeType: "Partnership",
        description: "Expansion requires partnership.",
        createdAt: "2025-03-15T09:30:00.000Z",
        progressPercentage: 12,
        dealer: {
            fullName: "Jane Dealer",
            dealerProfile: {
                businessName: "Highway Garage",
                dealerCode: {
                    dealerCode: "HG-01",
                    salesCode: "S1",
                    serviceCode: "V1",
                    gmaCode: "G1",
                    gearCode: "GR1",
                },
                registeredAddress: "Plot 9, Industrial Area",
                application: { loiRequests: [], loaRequests: [] },
            },
        },
        outlet: {
            type: "Proprietorship",
            name: "Main Outlet",
            code: "OUT-1",
            city: "Chennai",
            state: "TN",
            address: "Street 1",
        },
        documents: [],
        timeline: [],
        metadata: { jointApprovals: { zmRbm: {} } },
        worknotes: [],
    }
}

describe("ConstitutionalChangeDetails", () => {
    const onBack = jest.fn()

    beforeEach(() => {
        jest.clearAllMocks()
        mockGetAuditLogs.mockResolvedValue({
            data: { success: true, data: [] },
        })
    })

    function setup(requestId = "CCR-500", user: User | null = buildAsmUser()) {
        render(
            <MemoryRouter future={MEMORY_ROUTER_TEST_FUTURE}>
                <ConstitutionalChangeDetails
                    requestId={requestId}
                    onBack={onBack}
                    currentUser={user}
                />
            </MemoryRouter>,
        )
    }

    it("shows loading then not found when API returns no request", async () => {
        mockGetConstitutionalChangeById.mockResolvedValue({
            data: { success: false },
        })

        setup()

        expect(screen.getByText(/loading request details/i)).toBeInTheDocument()

        await waitFor(() => {
            expect(screen.getByRole("heading", { name: /request not found/i })).toBeInTheDocument()
        })

        expect(
            screen.getByText(/doesn't exist/i),
        ).toBeInTheDocument()
    })

    it("renders overview when request loads", async () => {
        mockGetConstitutionalChangeById.mockResolvedValue({
            data: { success: true, request: minimalRequest() },
        })

        setup()

        await waitFor(() => {
            expect(
                screen.getByRole("heading", {
                    name: /CCR-500 - constitutional change details/i,
                }),
            ).toBeInTheDocument()
        })

        expect(screen.getAllByText(/Highway Garage/i).length).toBeGreaterThanOrEqual(
            1,
        )
        expect(screen.getByText(/request overview/i)).toBeInTheDocument()
        expect(screen.getByText(/expansion requires partnership/i)).toBeInTheDocument()
        expect(screen.getByText(/workflow progress/i)).toBeInTheDocument()
    })

    it("invokes onBack from Go Back when request missing", async () => {
        mockGetConstitutionalChangeById.mockResolvedValue({
            data: { success: false },
        })

        setup()

        await waitFor(() => {
            expect(screen.getByRole("button", { name: /^go back$/i })).toBeInTheDocument()
        })

        screen.getByRole("button", { name: /^go back$/i }).click()

        expect(onBack).toHaveBeenCalled()
    })
})
