import { cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";

const {
    generateShareLinkMock,
    getSessionMetadataMock,
    getShareAnalyticsMock,
    localizeSessionVariantMock,
} = vi.hoisted(() => ({
    generateShareLinkMock: vi.fn(),
    getSessionMetadataMock: vi.fn(),
    getShareAnalyticsMock: vi.fn(),
    localizeSessionVariantMock: vi.fn(),
}));
const { scanSessionForSensitiveDataMock } = vi.hoisted(() => ({
    scanSessionForSensitiveDataMock: vi.fn(),
}));
const { trackWorkflowEventMock } = vi.hoisted(() => ({
    trackWorkflowEventMock: vi.fn(),
}));

vi.mock("../lib/api", () => ({
    generateShareLink: generateShareLinkMock,
    getSessionMetadata: getSessionMetadataMock,
    getShareAnalytics: getShareAnalyticsMock,
    localizeSessionVariant: localizeSessionVariantMock,
}));
vi.mock("../lib/privacyScan", () => ({
    scanSessionForSensitiveData: scanSessionForSensitiveDataMock,
}));
vi.mock("../lib/usageMetrics", () => ({
    trackWorkflowEvent: trackWorkflowEventMock,
}));

import ShareDialog from "./ShareDialog";

describe("ShareDialog", () => {
    beforeEach(() => {
        generateShareLinkMock.mockReset();
        getSessionMetadataMock.mockReset();
        scanSessionForSensitiveDataMock.mockReset();
        trackWorkflowEventMock.mockReset();
        getShareAnalyticsMock.mockReset();
        localizeSessionVariantMock.mockReset();
        getSessionMetadataMock.mockResolvedValue({
            session_id: "session-abc12345",
            created_at: "1735689600",
            display: { id: "display-1", resolution: "1920x1080", refresh_rate: 60 },
            duration_ms: 1000,
            event_count: 0,
            recording_path: "/tmp/recording.mov",
            events_path: "/tmp/events.ndjson",
            title: "Test",
            thumbnail_path: null,
            has_terminal: false,
            git_branch: null,
            git_commit: null,
        });
        scanSessionForSensitiveDataMock.mockResolvedValue({
            scannedPaths: ["/tmp/events.ndjson"],
            findings: [],
            highSeverityCount: 0,
            mediumSeverityCount: 0,
        });
        getShareAnalyticsMock.mockResolvedValue({
            token: "test-session",
            session_id: "session-abc12345",
            generated_at_ms: 1700000000000,
            total_events: 4,
            unique_visitors: 2,
            unique_accounts: 1,
            viewer_sessions: 2,
            completions: 1,
            hotspot_clicks: 1,
            voiceover_plays: 0,
            step_views: [{ step_id: "step_001", views: 2 }],
            last_event_ts_ms: 1700000000000,
        });
        Object.defineProperty(navigator, "clipboard", {
            configurable: true,
            value: {
                writeText: vi.fn().mockResolvedValue(undefined),
            },
        });
    });

    afterEach(() => {
        cleanup();
    });

    it("generates a share link and shows markdown/embed snippets", async () => {
        generateShareLinkMock.mockResolvedValue("http://localhost:8765/share/test-session");

        render(<ShareDialog sessionId="session-abc12345" onClose={() => {}} />);

        fireEvent.click(screen.getByRole("button", { name: /generate sharing link/i }));

        await waitFor(() => {
            expect(generateShareLinkMock).toHaveBeenCalledWith("session-abc12345");
        });
        expect(scanSessionForSensitiveDataMock).toHaveBeenCalled();

        expect(screen.getByDisplayValue("http://localhost:8765/share/test-session")).toBeTruthy();
        expect(screen.getByDisplayValue(/^\[ShowRunner session session-/i)).toBeTruthy();
        expect(screen.getByDisplayValue(/^<iframe src=/i)).toBeTruthy();
    });

    it("copies URL when copy action is triggered", async () => {
        generateShareLinkMock.mockResolvedValue("http://localhost:8765/share/test-session");
        render(<ShareDialog sessionId="session-abc12345" onClose={() => {}} />);

        fireEvent.click(screen.getByRole("button", { name: /generate sharing link/i }));
        await screen.findByDisplayValue("http://localhost:8765/share/test-session");

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

        await waitFor(() => {
            expect(navigator.clipboard.writeText).toHaveBeenCalledWith(
                "http://localhost:8765/share/test-session"
            );
        });
    });

    it("blocks link generation on high-severity findings unless user overrides", async () => {
        scanSessionForSensitiveDataMock.mockResolvedValueOnce({
            scannedPaths: ["/tmp/events.ndjson"],
            findings: [
                {
                    rule: "OpenAI API key",
                    severity: "high",
                    path: "/tmp/events.ndjson",
                    snippet: "sk-test-key",
                },
            ],
            highSeverityCount: 1,
            mediumSeverityCount: 0,
        });
        generateShareLinkMock.mockResolvedValue("http://localhost:8765/share/test-session");

        render(<ShareDialog sessionId="session-abc12345" onClose={() => {}} />);
        fireEvent.click(screen.getByRole("button", { name: /generate sharing link/i }));

        await waitFor(() => {
            expect(generateShareLinkMock).not.toHaveBeenCalled();
        });
        expect(screen.getByRole("button", { name: /generate anyway/i })).toBeTruthy();

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

        await waitFor(() => {
            expect(generateShareLinkMock).toHaveBeenCalledWith("session-abc12345");
        });
    });

    it("publishes a localized variant and shows localized URL", async () => {
        generateShareLinkMock.mockResolvedValue("http://localhost:8765/share/test-session");
        localizeSessionVariantMock.mockResolvedValue({
            session_id: "session-abc12345",
            target_language: "es",
            translated_step_fields: 6,
            translated_hotspots: 2,
            generated_voiceovers: 3,
        });

        render(<ShareDialog sessionId="session-abc12345" onClose={() => {}} />);
        fireEvent.click(screen.getByRole("button", { name: /generate sharing link/i }));
        await screen.findByDisplayValue("http://localhost:8765/share/test-session");

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

        await waitFor(() => {
            expect(localizeSessionVariantMock).toHaveBeenCalledWith("session-abc12345", "es", {
                includeVoiceover: true,
                overwriteExisting: false,
            });
        });

        expect(
            screen.getByDisplayValue("http://localhost:8765/share/test-session?lang=es")
        ).toBeTruthy();
    });
});
