import React from "react";
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import { jest } from "@jest/globals";
import { MemoryRouter } from "react-router-dom";

// Mock API Service
const mockPostApi = jest.fn();
const mockGetApi = jest.fn();
jest.unstable_mockModule("../services/apiService.js", () => ({
  __esModule: true,
  default: () => ({
    postApi: mockPostApi,
    getApi: mockGetApi,
  }),
}));

// Mock charts
jest.unstable_mockModule("../components/Barchart.js", () => ({
  __esModule: true,
  default: ({ data, selectedValue }) => (
    <div data-testid="bar-chart" data-value={selectedValue}>
      Bar Chart
    </div>
  ),
}));

jest.unstable_mockModule("../utils/PieCharts.js", () => ({
  __esModule: true,
  default: ({ data, selectedValue }) => (
    <div data-testid="pie-chart" data-value={selectedValue}>
      Pie Chart
    </div>
  ),
}));

jest.unstable_mockModule("../components/BarChartStack.js", () => ({
  __esModule: true,
  default: ({ data, selectedValue }) => (
    <div data-testid="bar-chart-stack" data-value={selectedValue}>
      Bar Chart Stack
    </div>
  ),
}));

jest.unstable_mockModule("../components/Loader.js", () => ({
  __esModule: true,
  default: () => <div data-testid="loader">Loading...</div>,
}));

jest.unstable_mockModule("../components/DateFilterDropdown.js", () => ({
  __esModule: true,
  default: ({ onChange }) => (
    <select data-testid="date-filter" onChange={(e) => onChange(e.target.value)}>
      <option value="Today">Today</option>
      <option value="Yesterday">Yesterday</option>
    </select>
  ),
}));

jest.unstable_mockModule("../components/SmartDateSelector.js", () => ({
  __esModule: true,
  default: ({ onDateChange }) => (
    <div data-testid="smart-date-selector">
      <button onClick={() => onDateChange({ startDate: "2023-01-01", endDate: "2023-01-31" })}>
        Select Date
      </button>
    </div>
  ),
}));

jest.unstable_mockModule("../components/DateFilterDropdown.js", () => ({
  __esModule: true,
  default: ({ onChange, value }) => (
    <select 
      data-testid="dropdown-dateFilter" 
      value={value || ""} 
      onChange={(e) => onChange?.("filterType", { type: e.target.value })}
    >
      <option value="">Select Date Range</option>
      <option value="Today">Today</option>
      <option value="Yesterday">Yesterday</option>
      <option value="Last 7 Days">Last 7 Days</option>
      <option value="Last 30 Days">Last 30 Days</option>
    </select>
  ),
}));

jest.unstable_mockModule("../utils/Dropdown.js", () => ({
  __esModule: true,
  default: ({ onSelectChange, dropDownData, dropDownKeys, value }) => (
    <select 
      data-testid={`dropdown-${dropDownKeys?.key || "unknown"}`} 
      value={value || ""} 
      onChange={(e) => onSelectChange?.(e.target.value, dropDownKeys?.key)}
    >
      <option value="">Select {dropDownKeys?.title}</option>
      {Array.isArray(dropDownData) && dropDownData.map((item, index) => (
        <option key={index} value={typeof item === 'object' ? item.Name : item}>
          {typeof item === 'object' ? item.Name : item}
        </option>
      ))}
    </select>
  ),
}));

jest.unstable_mockModule("../components/SearchInput.js", () => ({
  __esModule: true,
  default: ({ onSearch, onClear, placeholder }) => (
    <div data-testid="search-input">
      <input
        data-testid="search-field"
        placeholder={placeholder || "Search"}
        onChange={(e) => onSearch?.(e.target.value)}
      />
      <button onClick={onClear} data-testid="clear-btn">Clear</button>
    </div>
  ),
}));

// Import after mocks
const { default: ActivityReportsCharts } = await import("../pages/ActivityReportsCharts/ActivityReportsCharts.js");

const mockChartData = [
  {
    Results: [
      { Name: "App1", Value: 100 },
      { Name: "App2", Value: 200 },
    ],
  },
];

const renderComponent = (props = {}) => {
  return render(
    <MemoryRouter>
      <ActivityReportsCharts {...props} />
    </MemoryRouter>
  );
};

describe("ActivityReportsCharts Component", () => {
  beforeEach(() => {
    jest.clearAllMocks();
    localStorage.clear();
    
    // Default API responses - must match expected structure
    mockGetApi.mockResolvedValue({
      ActivityType: [
        { Name: "Applications", ActivityTypeData: [{ Name: "All Applications" }, { Name: "Application(Top 10)" }] },
        { Name: "Calls", ActivityTypeData: [{ Name: "All Calls" }, { Name: "Calls(Top 10)" }] },
        { Name: "Sessions", ActivityTypeData: [{ Name: "Active" }, { Name: "Idle" }] },
      ],
      DeviceType: [{ Name: "Desktop" }, { Name: "Mobile" }],
    });
    mockPostApi.mockResolvedValue(mockChartData);
  });

  afterEach(() => {
    localStorage.clear();
  });

  it("renders the component with activity-reports-charts class", async () => {
    renderComponent();
    const container = document.querySelector(".activity-reports-charts");
    expect(container).toBeInTheDocument();
  });

  it("renders dropdown menus", async () => {
    renderComponent();
    
    await waitFor(() => {
      expect(screen.getByTestId("dropdown-activityType")).toBeInTheDocument();
    });
  });

  it("renders date filter dropdown", async () => {
    renderComponent();
    
    await waitFor(() => {
      expect(screen.getByTestId("dropdown-dateFilter")).toBeInTheDocument();
    });
  });

  it("fetches dropdown data on mount", async () => {
    renderComponent();
    
    await waitFor(() => {
      expect(mockGetApi).toHaveBeenCalled();
    });
  });

  it("fetches chart data on mount", async () => {
    renderComponent();
    
    await waitFor(() => {
      expect(mockPostApi).toHaveBeenCalled();
    });
  });

  it("handles activity type dropdown change", async () => {
    renderComponent();
    
    await waitFor(() => {
      const dropdown = screen.getByTestId("dropdown-activityType");
      expect(dropdown).toBeInTheDocument();
    });
    
    const dropdown = screen.getByTestId("dropdown-activityType");
    fireEvent.change(dropdown, { target: { value: "Sessions" } });
    
    expect(dropdown).toBeInTheDocument();
  });

  it("handles result type dropdown change", async () => {
    renderComponent();
    
    await waitFor(() => {
      const dropdown = screen.getByTestId("dropdown-resultType");
      expect(dropdown).toBeInTheDocument();
    });
  });

  it("handles date filter change", async () => {
    renderComponent();
    
    await waitFor(() => {
      const dateFilter = screen.getByTestId("dropdown-dateFilter");
      expect(dateFilter).toBeInTheDocument();
    });
    
    const dateFilter = screen.getByTestId("dropdown-dateFilter");
    fireEvent.change(dateFilter, { target: { value: "Yesterday" } });
    
    expect(dateFilter).toBeInTheDocument();
  });

  it("renders search input when no employeeId prop", async () => {
    renderComponent();
    
    await waitFor(() => {
      expect(screen.getByTestId("search-input")).toBeInTheDocument();
    });
  });

  it("does not render search input when employeeId prop is provided", async () => {
    renderComponent({ employeeId: "123" });
    
    expect(screen.queryByTestId("search-input")).not.toBeInTheDocument();
  });

  it("handles empty chart data", async () => {
    mockPostApi.mockResolvedValue([{ Results: [] }]);
    
    renderComponent();
    
    await waitFor(() => {
      const container = document.querySelector(".activity-reports-charts");
      expect(container).toBeInTheDocument();
    });
  });

  it("handles API error gracefully", async () => {
    // Mock both APIs to return valid data but with error on one
    mockGetApi.mockResolvedValue({
      ActivityType: [{ Name: "Applications", ActivityTypeData: [{ Name: "All Applications" }] }],
      DeviceType: [],
    });
    mockPostApi.mockRejectedValue(new Error("API Error"));
    
    renderComponent();
    
    // Component should still render without crashing
    const container = document.querySelector(".activity-reports-charts");
    expect(container).toBeInTheDocument();
  });

  it("renders chart container", async () => {
    renderComponent();
    
    await waitFor(() => {
      const chartContainer = document.querySelector(".activity-reports-charts");
      expect(chartContainer).toBeInTheDocument();
    });
  });

  it("renders clear filters button", async () => {
    renderComponent();
    
    await waitFor(() => {
      const clearBtn = screen.getByRole("button", { name: /clear filters/i });
      expect(clearBtn).toBeInTheDocument();
    });
  });

  it("renders create chart button", async () => {
    renderComponent();
    
    await waitFor(() => {
      const createChartBtn = screen.getByRole("button", { name: /create chart/i });
      expect(createChartBtn).toBeInTheDocument();
    });
  });

  it("handles clear filters click", async () => {
    renderComponent();
    
    await waitFor(() => {
      const clearBtn = screen.getByRole("button", { name: /clear filters/i });
      expect(clearBtn).toBeInTheDocument();
    });
    
    const clearBtn = screen.getByRole("button", { name: /clear filters/i });
    fireEvent.click(clearBtn);
    
    expect(clearBtn).toBeInTheDocument();
  });

  it("handles create chart click", async () => {
    renderComponent();
    
    await waitFor(() => {
      const createChartBtn = screen.getByRole("button", { name: /create chart/i });
      expect(createChartBtn).toBeInTheDocument();
    });
    
    const createChartBtn = screen.getByRole("button", { name: /create chart/i });
    fireEvent.click(createChartBtn);
    
    expect(mockPostApi).toHaveBeenCalled();
  });

  it("renders widgets-activity-reports grid", async () => {
    renderComponent();
    
    await waitFor(() => {
      const widgetsGrid = document.querySelector(".widgets-activity-reports");
      expect(widgetsGrid).toBeInTheDocument();
    });
  });

  it("renders charts container", async () => {
    renderComponent();
    
    await waitFor(() => {
      const chartsContainer = document.querySelector(".charts");
      expect(chartsContainer).toBeInTheDocument();
    });
  });

  it("handles Sessions activity type selection", async () => {
    renderComponent();
    
    await waitFor(() => {
      const dropdown = screen.getByTestId("dropdown-activityType");
      expect(dropdown).toBeInTheDocument();
    });
    
    const dropdown = screen.getByTestId("dropdown-activityType");
    fireEvent.change(dropdown, { target: { value: "Sessions" } });
    
    // Click create chart to trigger sessions data fetch
    const createChartBtn = screen.getByRole("button", { name: /create chart/i });
    fireEvent.click(createChartBtn);
    
    expect(dropdown).toBeInTheDocument();
  });

  it("handles Calls activity type selection", async () => {
    renderComponent();
    
    await waitFor(() => {
      const dropdown = screen.getByTestId("dropdown-activityType");
      expect(dropdown).toBeInTheDocument();
    });
    
    const dropdown = screen.getByTestId("dropdown-activityType");
    fireEvent.change(dropdown, { target: { value: "Calls" } });
    
    expect(dropdown).toBeInTheDocument();
  });

  it("handles Applications activity type selection", async () => {
    renderComponent();
    
    await waitFor(() => {
      const dropdown = screen.getByTestId("dropdown-activityType");
      expect(dropdown).toBeInTheDocument();
    });
    
    const dropdown = screen.getByTestId("dropdown-activityType");
    fireEvent.change(dropdown, { target: { value: "Applications" } });
    
    expect(dropdown).toBeInTheDocument();
  });

  it("handles search input", async () => {
    renderComponent();
    
    await waitFor(() => {
      expect(screen.getByTestId("search-input")).toBeInTheDocument();
    });
    
    const searchField = screen.getByTestId("search-field");
    fireEvent.change(searchField, { target: { value: "test search" } });
    
    expect(searchField).toBeInTheDocument();
  });

  it("handles clear button click", async () => {
    renderComponent();
    
    await waitFor(() => {
      expect(screen.getByTestId("search-input")).toBeInTheDocument();
    });
    
    const clearSearchBtn = screen.getByTestId("clear-btn");
    fireEvent.click(clearSearchBtn);
    
    expect(clearSearchBtn).toBeInTheDocument();
  });

  it("handles result type dropdown change for pie chart", async () => {
    renderComponent();
    
    await waitFor(() => {
      const dropdown = screen.getByTestId("dropdown-resultType");
      expect(dropdown).toBeInTheDocument();
    });
    
    const dropdown = screen.getByTestId("dropdown-resultType");
    fireEvent.change(dropdown, { target: { value: "Application(Top 10)" } });
    
    expect(dropdown).toBeInTheDocument();
  });

  it("handles smart date selector", async () => {
    renderComponent();
    
    await waitFor(() => {
      const container = document.querySelector(".activity-reports-charts");
      expect(container).toBeInTheDocument();
    });
  });

  it("handles dropdown data transformation", async () => {
    mockGetApi.mockResolvedValue({
      ActivityType: [
        { ParentId: 1, ParentName: "Applications", ActivityTypeData: [{ Id: 1, Name: "All Applications", Type: "app", UniqueId: "1" }] },
      ],
      DeviceType: [{ Name: "Desktop" }],
    });
    
    renderComponent();
    
    await waitFor(() => {
      expect(mockGetApi).toHaveBeenCalled();
    });
  });

  it("handles empty ActivityType array", async () => {
    mockGetApi.mockResolvedValue({
      ActivityType: [],
      DeviceType: [],
    });
    
    renderComponent();
    
    await waitFor(() => {
      const container = document.querySelector(".activity-reports-charts");
      expect(container).toBeInTheDocument();
    });
  });

  it("handles null dropdown response", async () => {
    mockGetApi.mockResolvedValue({
      ActivityType: [],
      DeviceType: [],
    });
    
    renderComponent();
    
    await waitFor(() => {
      const container = document.querySelector(".activity-reports-charts");
      expect(container).toBeInTheDocument();
    });
  });

  it("handles no results in chart data", async () => {
    mockPostApi.mockResolvedValue([{ Results: [] }]);
    
    renderComponent();
    
    await waitFor(() => {
      const container = document.querySelector(".activity-reports-charts");
      expect(container).toBeInTheDocument();
    });
    
    // Click create chart to trigger rendering with no data
    const createChartBtn = screen.getByRole("button", { name: /create chart/i });
    fireEvent.click(createChartBtn);
    
    await waitFor(() => {
      // The no-data message may or may not be rendered depending on state
      const container = document.querySelector(".activity-reports-charts");
      expect(container).toBeInTheDocument();
    });
  });

  it("handles device type dropdown", async () => {
    renderComponent();
    
    await waitFor(() => {
      const dropdown = screen.getByTestId("dropdown-deviceType");
      expect(dropdown).toBeInTheDocument();
    });
  });

  it("renders other-filters container", async () => {
    renderComponent();
    
    await waitFor(() => {
      const otherFilters = document.querySelector(".other-filters");
      expect(otherFilters).toBeInTheDocument();
    });
  });

  it("handles reset filters", async () => {
    renderComponent();
    
    await waitFor(() => {
      const clearBtn = screen.queryByTestId("clear-btn");
      expect(clearBtn).toBeInTheDocument();
    });
    
    // Make some changes first
    const dropdown = screen.getByTestId("dropdown-activityType");
    fireEvent.change(dropdown, { target: { value: "Sessions" } });
    
    // Then reset
    const clearBtn = screen.getByTestId("clear-btn");
    fireEvent.click(clearBtn);
    
    expect(clearBtn).toBeInTheDocument();
  });

  it("handles log activity type", async () => {
    mockGetApi.mockResolvedValue({
      ActivityType: [
        { Name: "Applications", ActivityTypeData: [{ Name: "All Applications" }] },
        { Name: "Calls", ActivityTypeData: [{ Name: "All Calls" }] },
        { Name: "Sessions", ActivityTypeData: [{ Name: "Log In" }, { Name: "Log Out" }] },
      ],
      DeviceType: [],
    });
    
    renderComponent();
    
    await waitFor(() => {
      expect(mockGetApi).toHaveBeenCalled();
    });
  });

  it("handles calls top 10 result type", async () => {
    renderComponent();
    
    await waitFor(() => {
      const dropdown = screen.getByTestId("dropdown-resultType");
      expect(dropdown).toBeInTheDocument();
    });
    
    const dropdown = screen.getByTestId("dropdown-resultType");
    fireEvent.change(dropdown, { target: { value: "Calls(Top 10)" } });
    
    expect(dropdown).toBeInTheDocument();
  });

  it("handles Calls with Top 10 result and creates chart", async () => {
    renderComponent();
    
    await waitFor(() => {
      const activityDropdown = screen.getByTestId("dropdown-activityType");
      expect(activityDropdown).toBeInTheDocument();
    });

    // Set to Calls
    const activityDropdown = screen.getByTestId("dropdown-activityType");
    fireEvent.change(activityDropdown, { target: { value: "Calls" } });

    // Set result type to Top 10
    const resultDropdown = screen.getByTestId("dropdown-resultType");
    fireEvent.change(resultDropdown, { target: { value: "Calls(Top 10)" } });

    // Click create chart
    const createChartBtn = screen.getByRole("button", { name: /create chart/i });
    fireEvent.click(createChartBtn);
    
    expect(mockPostApi).toHaveBeenCalled();
  });

  it("handles Calls All Calls result type", async () => {
    renderComponent();
    
    await waitFor(() => {
      const activityDropdown = screen.getByTestId("dropdown-activityType");
      expect(activityDropdown).toBeInTheDocument();
    });

    // Set to Calls
    const activityDropdown = screen.getByTestId("dropdown-activityType");
    fireEvent.change(activityDropdown, { target: { value: "Calls" } });

    // Set result type to All Calls
    const resultDropdown = screen.getByTestId("dropdown-resultType");
    fireEvent.change(resultDropdown, { target: { value: "All Calls" } });

    // Click create chart
    const createChartBtn = screen.getByRole("button", { name: /create chart/i });
    fireEvent.click(createChartBtn);
    
    expect(mockPostApi).toHaveBeenCalled();
  });

  it("handles empty Calls result", async () => {
    mockPostApi.mockResolvedValueOnce([{ Results: [] }]);
    
    renderComponent();
    
    await waitFor(() => {
      const activityDropdown = screen.getByTestId("dropdown-activityType");
      expect(activityDropdown).toBeInTheDocument();
    });

    // Set to Calls
    const activityDropdown = screen.getByTestId("dropdown-activityType");
    fireEvent.change(activityDropdown, { target: { value: "Calls" } });

    // Click create chart
    const createChartBtn = screen.getByRole("button", { name: /create chart/i });
    fireEvent.click(createChartBtn);
    
    expect(mockPostApi).toHaveBeenCalled();
  });

  it("handles Sessions with Log In result type", async () => {
    mockGetApi.mockResolvedValue({
      ActivityType: [
        { Name: "Applications", ActivityTypeData: [{ Name: "All Applications" }] },
        { Name: "Calls", ActivityTypeData: [{ Name: "All Calls" }] },
        { Name: "Sessions", ActivityTypeData: [{ Name: "Log In" }, { Name: "Log Out" }, { Name: "All Sessions" }] },
      ],
      DeviceType: [{ Name: "Desktop" }],
    });
    
    renderComponent();
    
    await waitFor(() => {
      const activityDropdown = screen.getByTestId("dropdown-activityType");
      expect(activityDropdown).toBeInTheDocument();
    });

    // Set to Sessions
    const activityDropdown = screen.getByTestId("dropdown-activityType");
    fireEvent.change(activityDropdown, { target: { value: "Sessions" } });

    // Set result type to Log In
    const resultDropdown = screen.getByTestId("dropdown-resultType");
    fireEvent.change(resultDropdown, { target: { value: "Log In" } });

    // Click create chart
    const createChartBtn = screen.getByRole("button", { name: /create chart/i });
    fireEvent.click(createChartBtn);
    
    expect(mockPostApi).toHaveBeenCalled();
  });

  it("handles Sessions with All Sessions result type", async () => {
    mockGetApi.mockResolvedValue({
      ActivityType: [
        { Name: "Applications", ActivityTypeData: [{ Name: "All Applications" }] },
        { Name: "Calls", ActivityTypeData: [{ Name: "All Calls" }] },
        { Name: "Sessions", ActivityTypeData: [{ Name: "All Sessions" }, { Name: "Active" }] },
      ],
      DeviceType: [{ Name: "Desktop" }],
    });
    
    renderComponent();
    
    await waitFor(() => {
      const activityDropdown = screen.getByTestId("dropdown-activityType");
      expect(activityDropdown).toBeInTheDocument();
    });

    // Set to Sessions
    const activityDropdown = screen.getByTestId("dropdown-activityType");
    fireEvent.change(activityDropdown, { target: { value: "Sessions" } });

    // Set result type to All Sessions
    const resultDropdown = screen.getByTestId("dropdown-resultType");
    fireEvent.change(resultDropdown, { target: { value: "All Sessions" } });

    // Click create chart
    const createChartBtn = screen.getByRole("button", { name: /create chart/i });
    fireEvent.click(createChartBtn);
    
    expect(mockPostApi).toHaveBeenCalled();
  });

  it("handles empty Sessions result", async () => {
    mockPostApi.mockResolvedValue([{ Results: [] }]);
    
    renderComponent();
    
    await waitFor(() => {
      const activityDropdown = screen.getByTestId("dropdown-activityType");
      expect(activityDropdown).toBeInTheDocument();
    });

    // Set to Sessions
    const activityDropdown = screen.getByTestId("dropdown-activityType");
    fireEvent.change(activityDropdown, { target: { value: "Sessions" } });

    // Click create chart
    const createChartBtn = screen.getByRole("button", { name: /create chart/i });
    fireEvent.click(createChartBtn);
    
    expect(mockPostApi).toHaveBeenCalled();
  });

  it("handles API error in fetching data", async () => {
    mockPostApi.mockRejectedValueOnce(new Error("API Error"));
    
    renderComponent();
    
    await waitFor(() => {
      expect(mockPostApi).toHaveBeenCalled();
    });
  });
});
