import {
  renderWithProviders as render,
  screen,
  cleanup,
  waitFor,
} from "../utils/test-utils";
import userEvent from "@testing-library/user-event";
import { vi, describe, test, expect, afterEach } from "vitest";
import React from "react";
import Page from "../../app/page";

// Mock next/dynamic to return components synchronously in tests
vi.mock("next/dynamic", () => {
  return {
    default: (importFn, options) => {
      // In tests, resolve the dynamic import immediately and return the component
      let Component = null;
      importFn().then((mod) => {
        Component = mod.default || mod;
      });
      // Return a synchronous wrapper that uses the mocked component
      return (props) => {
        // Use the mocked component directly
        if (Component) {
          return <Component {...props} />;
        }
        // Fallback: return the loading placeholder if component not ready
        return options?.loading ? options.loading() : null;
      };
    },
  };
});
import Header from "../../app/components/Header";
import Footer from "../../app/components/Footer";

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

describe("User Journey Integration", () => {
  // TODO: Fix next/dynamic mock to properly handle async component loading
  test.skip("new user discovers the application through hero section", async () => {
    const user = userEvent.setup();
    render(
      <div>
        <Header />
        <Page />
        <Footer />
      </div>,
    );

    // User sees the main value proposition
    expect(
      screen.getByText(/Help your community make important decisions/),
    ).toBeInTheDocument();

    // User clicks the main CTA to learn more
    const learnButtons = screen.getAllByRole("button", {
      name: "Learn how CommunityRule works",
    });
    const learnButton = learnButtons[0];
    await user.click(learnButton);

    // Wait for dynamically imported NumberedCards component
    await waitFor(() => {
      expect(screen.getByText("How CommunityRule works")).toBeInTheDocument();
    });
  });

  // TODO: Fix next/dynamic mock to properly handle async component loading
  test.skip("user explores different governance types", async () => {
    const user = userEvent.setup();
    render(<Page />);

    // Wait for dynamically imported RuleStack component
    await waitFor(() => {
      expect(screen.getByText("Consensus clusters")).toBeInTheDocument();
    });
    expect(screen.getByText("Elected Board")).toBeInTheDocument();
    expect(screen.getByText("Consensus")).toBeInTheDocument();
    expect(screen.getByText("Petition")).toBeInTheDocument();

    // User clicks on a governance type to create a rule
    const createButtons = screen.getAllByRole("button", {
      name: "Create CommunityRule",
    });
    expect(createButtons.length).toBeGreaterThan(0);

    await user.click(createButtons[0]);
    // Button should remain interactive
    expect(createButtons[0]).toBeInTheDocument();
  });

  test("user navigates through the application using header navigation", async () => {
    render(
      <div>
        <Header />
        <Page />
        <Footer />
      </div>,
    );

    // User clicks on navigation links in header (check that they exist and are clickable)
    const navigationLinks = screen.getAllByRole("link");
    const headerNavLinks = navigationLinks.filter(
      (link) =>
        link.textContent?.includes("Use Cases") ||
        link.textContent?.includes("Learn") ||
        link.textContent?.includes("About"),
    );

    // Test that navigation links are present and clickable
    for (const link of headerNavLinks) {
      expect(link).toBeInTheDocument();
      expect(link).toHaveAttribute("href");
    }
  });

  test("user seeks help through ask organizer section", async () => {
    const user = userEvent.setup();
    render(<Page />);

    // User scrolls to the bottom and sees the help section
    expect(screen.getByText("Still have questions?")).toBeInTheDocument();
    expect(
      screen.getByText("Get answers from an experienced organizer"),
    ).toBeInTheDocument();

    // User clicks the ask organizer button (it's actually a link, not a button)
    const askLink = screen.getByRole("link", { name: /Ask an organizer/i });
    await user.click(askLink);
    expect(askLink).toHaveAttribute("href", "#contact");
  });

  test("user explores the process through numbered cards", async () => {
    render(<Page />);

    // Wait for dynamically imported NumberedCards component
    await waitFor(() => {
      expect(
        screen.getByText("Document how your community makes decisions"),
      ).toBeInTheDocument();
    });
    expect(
      screen.getByText("Build an operating manual for a successful community"),
    ).toBeInTheDocument();
    expect(
      screen.getByText(
        "Get a link to your manual for your group to review and evolve",
      ),
    ).toBeInTheDocument();

    // User sees the step numbers
    const stepNumbers = screen.getAllByText(/1|2|3/);
    expect(stepNumbers.length).toBeGreaterThan(0);
  });

  test("user accesses contact information through footer", async () => {
    render(
      <div>
        <Header />
        <Page />
        <Footer />
      </div>,
    );

    // User finds contact email in footer
    const emailLink = screen.getByRole("link", { name: "medlab@colorado.edu" });
    expect(emailLink).toHaveAttribute("href", "mailto:medlab@colorado.edu");

    // User finds social media links
    const blueskyLink = screen.getByRole("link", {
      name: "Follow us on Bluesky",
    });
    const gitlabLink = screen.getByRole("link", {
      name: "Follow us on GitLab",
    });

    expect(blueskyLink).toBeInTheDocument();
    expect(gitlabLink).toBeInTheDocument();
  });

  test("user explores features and benefits", async () => {
    render(<Page />);

    // Wait for dynamically imported FeatureGrid component
    await waitFor(() => {
      expect(
        screen.getByText("We've got your back, every step of the way"),
      ).toBeInTheDocument();
    });
    expect(
      screen.getByText(
        "Use our toolkit to improve, document, and evolve your organization.",
      ),
    ).toBeInTheDocument();

    // User sees the testimonial/quote (check for the actual quote content)
    expect(
      screen.getByText(/The rules of decision-making must be open/),
    ).toBeInTheDocument();
  });

  test("user interacts with logo wall and social proof", async () => {
    render(
      <div>
        <Page />
        <Footer />
      </div>,
    );

    // Wait for dynamically imported LogoWall component
    await waitFor(() => {
      const logoImages = screen.getAllByRole("img");
      const partnerLogos = logoImages.filter(
        (img) =>
          img.alt?.includes("Food Not Bombs") ||
          img.alt?.includes("Start COOP") ||
          img.alt?.includes("Metagov") ||
          img.alt?.includes("Open Civics") ||
          img.alt?.includes("Mutual Aid CO") ||
          img.alt?.includes("CU Boulder"),
      );
      expect(partnerLogos.length).toBeGreaterThan(0);
    });

    // Social links should be present in footer
    const blueskyLink = screen.getByRole("link", { name: /Bluesky/i });
    const gitlabLink = screen.getByRole("link", { name: /GitLab/i });
    expect(blueskyLink).toBeInTheDocument();
    expect(gitlabLink).toBeInTheDocument();
  });

  test("user completes the full journey from discovery to action", async () => {
    render(
      <div>
        <Header />
        <Page />
        <Footer />
      </div>,
    );

    // 1. User discovers the application
    expect(screen.getByText("Collaborate")).toBeInTheDocument();
    expect(screen.getByText("with clarity")).toBeInTheDocument();

    // 2. User learns how it works - wait for dynamically imported component
    await waitFor(() => {
      expect(screen.getByText("How CommunityRule works")).toBeInTheDocument();
    });

    // 3. User sees governance options - wait for dynamically imported component
    await waitFor(() => {
      expect(screen.getByText("Consensus clusters")).toBeInTheDocument();
    });

    // 4. User sees features and benefits - wait for dynamically imported component
    await waitFor(() => {
      expect(
        screen.getByText("We've got your back, every step of the way"),
      ).toBeInTheDocument();
    });

    // 5. User sees social proof
    expect(
      screen.getByText(/The rules of decision-making must be open/),
    ).toBeInTheDocument();

    // 6. User can take action
    const createButtons = screen.getAllByRole("button", {
      name: "Create CommunityRule",
    });
    expect(createButtons.length).toBeGreaterThan(0);

    // 7. User can get help if needed
    expect(screen.getByText("Still have questions?")).toBeInTheDocument();
  });

  test("user can access all navigation options consistently", async () => {
    render(
      <div>
        <Header />
        <Page />
        <Footer />
      </div>,
    );

    // Header navigation
    const headerNav = screen.getByRole("navigation");
    expect(headerNav).toBeInTheDocument();

    // Footer navigation
    const footerLinks = screen.getAllByRole("link");
    const navigationLinks = footerLinks.filter(
      (link) =>
        link.textContent?.includes("Use cases") ||
        link.textContent?.includes("Learn") ||
        link.textContent?.includes("About"),
    );
    expect(navigationLinks.length).toBeGreaterThan(0);

    // All navigation links should be accessible
    navigationLinks.forEach((link) => {
      expect(link).not.toHaveAttribute("tabindex", "-1");
    });
  });

  test("user can complete actions without errors", async () => {
    const user = userEvent.setup();
    render(
      <div>
        <Header />
        <Page />
        <Footer />
      </div>,
    );

    // Test all interactive elements
    const buttons = screen.getAllByRole("button");
    const links = screen.getAllByRole("link");

    // All buttons should be clickable
    for (const button of buttons) {
      await user.click(button);
      expect(button).toBeInTheDocument();
    }

    // All links should be accessible
    for (const link of links) {
      expect(link).toBeInTheDocument();
      expect(link).not.toHaveAttribute("tabindex", "-1");
    }
  });
});
