import { describe, it, expect, beforeEach, vi } from "vitest";
import { mount } from "@vue/test-utils";
import { createPinia, setActivePinia } from "pinia";
import RunnersOnBase from "~/components/Game/RunnersOnBase.vue";
import RunnerCard from "~/components/Game/RunnerCard.vue";
import { useGameStore } from "~/store/game";
import type { LineupPlayerState, Lineup } from "~/types/game";

describe("RunnersOnBase", () => {
    let pinia: ReturnType<typeof createPinia>;

    beforeEach(() => {
        pinia = createPinia();
        setActivePinia(pinia);
    });

    const mockRunnerFirst: LineupPlayerState = {
        lineup_id: 1,
        batting_order: 1,
        position: "LF",
        card_id: 101,
    };

    const mockRunnerSecond: LineupPlayerState = {
        lineup_id: 2,
        batting_order: 2,
        position: "CF",
        card_id: 102,
    };

    const mockRunnerThird: LineupPlayerState = {
        lineup_id: 3,
        batting_order: 3,
        position: "RF",
        card_id: 103,
    };

    const mockCatcher: Lineup = {
        id: 1,
        lineup_id: 4,
        team_id: 1,
        batting_order: 4,
        position: "C",
        is_active: true,
        player: {
            id: 104,
            name: "Buster Posey",
            image: "https://example.com/posey.jpg",
            headshot: "https://example.com/posey-headshot.jpg",
        },
    };

    const mockFieldingLineup: Lineup[] = [mockCatcher];

    describe("component visibility", () => {
        it("does not render when no runners on base", () => {
            const wrapper = mount(RunnersOnBase, {
                global: { plugins: [pinia] },
                props: {
                    runners: { first: null, second: null, third: null },
                    fieldingLineup: mockFieldingLineup,
                    battingTeamColor: "#3b82f6",
                    fieldingTeamColor: "#10b981",
                    battingTeamAbbrev: "BOS",
                    fieldingTeamAbbrev: "NYY",
                },
            });

            expect(wrapper.find(".runners-on-base-container").exists()).toBe(
                false,
            );
        });

        it("renders when at least one runner on base", () => {
            const wrapper = mount(RunnersOnBase, {
                global: { plugins: [pinia] },
                props: {
                    runners: {
                        first: null,
                        second: mockRunnerSecond,
                        third: null,
                    },
                    fieldingLineup: mockFieldingLineup,
                    battingTeamColor: "#3b82f6",
                    fieldingTeamColor: "#10b981",
                    battingTeamAbbrev: "BOS",
                    fieldingTeamAbbrev: "NYY",
                },
            });

            expect(wrapper.find(".runners-on-base-container").exists()).toBe(
                true,
            );
        });

        it("renders when bases loaded", () => {
            const wrapper = mount(RunnersOnBase, {
                global: { plugins: [pinia] },
                props: {
                    runners: {
                        first: mockRunnerFirst,
                        second: mockRunnerSecond,
                        third: mockRunnerThird,
                    },
                    fieldingLineup: mockFieldingLineup,
                    battingTeamColor: "#3b82f6",
                    fieldingTeamColor: "#10b981",
                    battingTeamAbbrev: "BOS",
                    fieldingTeamAbbrev: "NYY",
                },
            });

            expect(wrapper.find(".runners-on-base-container").exists()).toBe(
                true,
            );
        });
    });

    describe("runner cards", () => {
        it("renders three RunnerCard components", () => {
            const wrapper = mount(RunnersOnBase, {
                global: { plugins: [pinia] },
                props: {
                    runners: {
                        first: mockRunnerFirst,
                        second: null,
                        third: null,
                    },
                    fieldingLineup: mockFieldingLineup,
                    battingTeamColor: "#3b82f6",
                    fieldingTeamColor: "#10b981",
                    battingTeamAbbrev: "BOS",
                    fieldingTeamAbbrev: "NYY",
                },
            });

            const runnerCards = wrapper.findAllComponents(RunnerCard);
            expect(runnerCards).toHaveLength(3);
        });

        it("passes correct base labels to RunnerCard components", async () => {
            const wrapper = mount(RunnersOnBase, {
                global: { plugins: [pinia] },
                props: {
                    runners: {
                        first: mockRunnerFirst,
                        second: null,
                        third: null,
                    },
                    fieldingLineup: mockFieldingLineup,
                    battingTeamColor: "#3b82f6",
                    fieldingTeamColor: "#10b981",
                    battingTeamAbbrev: "BOS",
                    fieldingTeamAbbrev: "NYY",
                },
            });

            await wrapper.vm.$nextTick();

            const runnerCards = wrapper.findAllComponents(RunnerCard);
            expect(runnerCards.length).toBeGreaterThanOrEqual(3);
            expect(runnerCards[0].props("base")).toBe("1B");
            expect(runnerCards[1].props("base")).toBe("2B");
            expect(runnerCards[2].props("base")).toBe("3B");
        });

        it("passes runner data to RunnerCard components", () => {
            const wrapper = mount(RunnersOnBase, {
                global: { plugins: [pinia] },
                props: {
                    runners: {
                        first: mockRunnerFirst,
                        second: mockRunnerSecond,
                        third: null,
                    },
                    fieldingLineup: mockFieldingLineup,
                    battingTeamColor: "#3b82f6",
                    fieldingTeamColor: "#10b981",
                    battingTeamAbbrev: "BOS",
                    fieldingTeamAbbrev: "NYY",
                },
            });

            const runnerCards = wrapper.findAllComponents(RunnerCard);
            expect(runnerCards[0].props("runner")).toEqual(mockRunnerFirst);
            expect(runnerCards[1].props("runner")).toEqual(mockRunnerSecond);
            expect(runnerCards[2].props("runner")).toBeNull();
        });

        it("passes team color to RunnerCard components", () => {
            const wrapper = mount(RunnersOnBase, {
                global: { plugins: [pinia] },
                props: {
                    runners: {
                        first: mockRunnerFirst,
                        second: null,
                        third: null,
                    },
                    fieldingLineup: mockFieldingLineup,
                    battingTeamColor: "#ff0000",
                    fieldingTeamColor: "#00ff00",
                    battingTeamAbbrev: "BOS",
                    fieldingTeamAbbrev: "NYY",
                },
            });

            const runnerCards = wrapper.findAllComponents(RunnerCard);
            runnerCards.forEach((card) => {
                expect(card.props("teamColor")).toBe("#ff0000");
            });
        });
    });

    describe("catcher display", () => {
        it("shows collapsed catcher card by default", () => {
            const wrapper = mount(RunnersOnBase, {
                global: { plugins: [pinia] },
                props: {
                    runners: {
                        first: mockRunnerFirst,
                        second: null,
                        third: null,
                    },
                    fieldingLineup: mockFieldingLineup,
                    battingTeamColor: "#3b82f6",
                    fieldingTeamColor: "#10b981",
                    battingTeamAbbrev: "BOS",
                    fieldingTeamAbbrev: "NYY",
                },
            });

            // Collapsed state shows border-l-4, expanded state shows .matchup-card
            expect(wrapper.find(".border-l-4.border-gray-600").exists()).toBe(
                true,
            );
            expect(wrapper.find(".matchup-card").exists()).toBe(false);
        });

        it("displays catcher name", () => {
            const wrapper = mount(RunnersOnBase, {
                global: { plugins: [pinia] },
                props: {
                    runners: {
                        first: mockRunnerFirst,
                        second: null,
                        third: null,
                    },
                    fieldingLineup: mockFieldingLineup,
                    battingTeamColor: "#3b82f6",
                    fieldingTeamColor: "#10b981",
                    battingTeamAbbrev: "BOS",
                    fieldingTeamAbbrev: "NYY",
                },
            });

            expect(wrapper.text()).toContain("Buster Posey");
        });

        it('shows "Unknown Catcher" when no catcher in lineup', () => {
            const wrapper = mount(RunnersOnBase, {
                global: { plugins: [pinia] },
                props: {
                    runners: {
                        first: mockRunnerFirst,
                        second: null,
                        third: null,
                    },
                    fieldingLineup: [],
                    battingTeamColor: "#3b82f6",
                    fieldingTeamColor: "#10b981",
                    battingTeamAbbrev: "BOS",
                    fieldingTeamAbbrev: "NYY",
                },
            });

            expect(wrapper.text()).toContain("Unknown Catcher");
        });
    });

    describe("runner selection", () => {
        it("expands catcher card when runner is selected", async () => {
            const gameStore = useGameStore();
            gameStore.setGameState({
                id: 1,
                home_team_id: 1,
                away_team_id: 2,
                status: "active",
                inning: 1,
                half: "top",
                outs: 0,
                home_score: 0,
                away_score: 0,
                home_team_abbrev: "NYY",
                away_team_abbrev: "BOS",
                home_team_dice_color: "3b82f6",
                current_batter: null,
                current_pitcher: null,
                on_first: null,
                on_second: null,
                on_third: null,
                decision_phase: "idle",
                play_count: 0,
            });
            gameStore.updateLineup(1, [
                {
                    id: 1,
                    lineup_id: 1,
                    team_id: 1,
                    batting_order: 1,
                    position: "LF",
                    is_active: true,
                    player: {
                        id: 101,
                        name: "Mike Trout",
                        image: "https://example.com/trout.jpg",
                    },
                },
            ]);

            const wrapper = mount(RunnersOnBase, {
                global: { plugins: [pinia] },
                props: {
                    runners: {
                        first: mockRunnerFirst,
                        second: null,
                        third: null,
                    },
                    fieldingLineup: mockFieldingLineup,
                    battingTeamColor: "#3b82f6",
                    fieldingTeamColor: "#10b981",
                    battingTeamAbbrev: "BOS",
                    fieldingTeamAbbrev: "NYY",
                },
            });

            const runnerCards = wrapper.findAllComponents(RunnerCard);
            await runnerCards[0].trigger("click");

            // When runner selected, collapsed state hidden and expanded state shown
            expect(wrapper.find(".border-l-4.border-gray-600").exists()).toBe(
                false,
            );
            expect(wrapper.find(".matchup-card").exists()).toBe(true);
        });

        it("collapses catcher card when runner is deselected", async () => {
            const gameStore = useGameStore();
            gameStore.setGameState({
                id: 1,
                home_team_id: 1,
                away_team_id: 2,
                status: "active",
                inning: 1,
                half: "top",
                outs: 0,
                home_score: 0,
                away_score: 0,
                home_team_abbrev: "NYY",
                away_team_abbrev: "BOS",
                home_team_dice_color: "3b82f6",
                current_batter: null,
                current_pitcher: null,
                on_first: null,
                on_second: null,
                on_third: null,
                decision_phase: "idle",
                play_count: 0,
            });
            gameStore.updateLineup(1, [
                {
                    id: 1,
                    lineup_id: 1,
                    team_id: 1,
                    batting_order: 1,
                    position: "LF",
                    is_active: true,
                    player: {
                        id: 101,
                        name: "Mike Trout",
                        image: "https://example.com/trout.jpg",
                    },
                },
            ]);

            const wrapper = mount(RunnersOnBase, {
                global: { plugins: [pinia] },
                props: {
                    runners: {
                        first: mockRunnerFirst,
                        second: null,
                        third: null,
                    },
                    fieldingLineup: mockFieldingLineup,
                    battingTeamColor: "#3b82f6",
                    fieldingTeamColor: "#10b981",
                    battingTeamAbbrev: "BOS",
                    fieldingTeamAbbrev: "NYY",
                },
            });

            const runnerCards = wrapper.findAllComponents(RunnerCard);

            // Click to expand
            await runnerCards[0].trigger("click");
            expect(wrapper.find(".matchup-card").exists()).toBe(true);

            // Click again to collapse
            await runnerCards[0].trigger("click");
            expect(wrapper.find(".border-l-4.border-gray-600").exists()).toBe(
                true,
            );
            expect(wrapper.find(".matchup-card").exists()).toBe(false);
        });

        it("switches selection when clicking different runner", async () => {
            const gameStore = useGameStore();
            gameStore.setGameState({
                id: 1,
                home_team_id: 1,
                away_team_id: 2,
                status: "active",
                inning: 1,
                half: "top",
                outs: 0,
                home_score: 0,
                away_score: 0,
                home_team_abbrev: "NYY",
                away_team_abbrev: "BOS",
                home_team_dice_color: "3b82f6",
                current_batter: null,
                current_pitcher: null,
                on_first: null,
                on_second: null,
                on_third: null,
                decision_phase: "idle",
                play_count: 0,
            });
            gameStore.updateLineup(1, [
                {
                    id: 1,
                    lineup_id: 1,
                    team_id: 1,
                    batting_order: 1,
                    position: "LF",
                    is_active: true,
                    player: {
                        id: 101,
                        name: "Mike Trout",
                        image: "https://example.com/trout.jpg",
                    },
                },
                {
                    id: 2,
                    lineup_id: 2,
                    team_id: 1,
                    batting_order: 2,
                    position: "CF",
                    is_active: true,
                    player: {
                        id: 102,
                        name: "Aaron Judge",
                        image: "https://example.com/judge.jpg",
                    },
                },
            ]);

            const wrapper = mount(RunnersOnBase, {
                global: { plugins: [pinia] },
                props: {
                    runners: {
                        first: mockRunnerFirst,
                        second: mockRunnerSecond,
                        third: null,
                    },
                    fieldingLineup: mockFieldingLineup,
                    battingTeamColor: "#3b82f6",
                    fieldingTeamColor: "#10b981",
                    battingTeamAbbrev: "BOS",
                    fieldingTeamAbbrev: "NYY",
                },
            });

            const runnerCards = wrapper.findAllComponents(RunnerCard);

            // Select first runner
            await runnerCards[0].trigger("click");
            expect(runnerCards[0].props("isExpanded")).toBe(true);
            expect(runnerCards[1].props("isExpanded")).toBe(false);

            // Select second runner
            await runnerCards[1].trigger("click");
            expect(runnerCards[0].props("isExpanded")).toBe(false);
            expect(runnerCards[1].props("isExpanded")).toBe(true);
        });
    });

    describe("team information", () => {
        it("displays team abbreviations when provided", async () => {
            const gameStore = useGameStore();
            gameStore.setGameState({
                id: 1,
                home_team_id: 1,
                away_team_id: 2,
                status: "active",
                inning: 1,
                half: "top",
                outs: 0,
                home_score: 0,
                away_score: 0,
                home_team_abbrev: "NYY",
                away_team_abbrev: "BOS",
                home_team_dice_color: "3b82f6",
                current_batter: null,
                current_pitcher: null,
                on_first: null,
                on_second: null,
                on_third: null,
                decision_phase: "idle",
                play_count: 0,
            });
            gameStore.updateLineup(1, [
                {
                    id: 1,
                    lineup_id: 1,
                    team_id: 1,
                    batting_order: 1,
                    position: "LF",
                    is_active: true,
                    player: {
                        id: 101,
                        name: "Mike Trout",
                        image: "https://example.com/trout.jpg",
                    },
                },
            ]);

            const wrapper = mount(RunnersOnBase, {
                global: { plugins: [pinia] },
                props: {
                    runners: {
                        first: mockRunnerFirst,
                        second: null,
                        third: null,
                    },
                    fieldingLineup: mockFieldingLineup,
                    battingTeamColor: "#3b82f6",
                    fieldingTeamColor: "#10b981",
                    battingTeamAbbrev: "BOS",
                    fieldingTeamAbbrev: "NYY",
                },
            });

            // Click runner to expand and show team abbreviation
            const runnerCards = wrapper.findAllComponents(RunnerCard);
            await runnerCards[0].trigger("click");

            expect(wrapper.text()).toContain("NYY");
        });

        it("uses default colors when not provided", () => {
            const wrapper = mount(RunnersOnBase, {
                global: { plugins: [pinia] },
                props: {
                    runners: {
                        first: mockRunnerFirst,
                        second: null,
                        third: null,
                    },
                    fieldingLineup: mockFieldingLineup,
                },
            });

            const runnerCards = wrapper.findAllComponents(RunnerCard);
            expect(runnerCards[0].props("teamColor")).toBe("#3b82f6");
        });
    });
});
