import React from "react";
import { render, screen, waitFor, fireEvent, act } from "@testing-library/react";
import { jest } from "@jest/globals";
import ActivityTable from "../pages/ActivityTable.js";
import { UserProvider } from "../context/UserContext.js";
import { BrowserRouter } from "react-router-dom";

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

const mockUserContext = {
  permissions: [{ Path: "/activity", Permission_Id: "1" }],
};

const renderComponent = (props = {}) => {
  const defaultProps = {
    employeeId: null,
    title: "",
    ...props,
  };

  return render(
    <BrowserRouter>
      <UserProvider value={mockUserContext}>
        <ActivityTable {...defaultProps} />
      </UserProvider>
    </BrowserRouter>
  );
};

describe("ActivityTable Component", () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockGetApi.mockResolvedValue([
      { Id: "1", Name: "Active" },
      { Id: "2", Name: "Idle" },
      { Id: "3", Name: "Sleep" }
    ]);
    mockPostApi.mockResolvedValue([
      { EmployeeName: "John Doe", IpAddress: "192.168.1.1", SystemStatus: "Active" }
    ]);
  });

  it("should render the component", () => {
    renderComponent();
    expect(screen.getByTestId("common-table")).toBeInTheDocument();
  });

  it("should render loader initially", () => {
    renderComponent();
    expect(screen.getByTestId("loader")).toBeInTheDocument();
  });

  it("should render dropdown menu for Alert Type", () => {
    renderComponent();
    // The dropdown should be present - check for combobox (Alert Type dropdown)
    const comboboxes = screen.getAllByRole("combobox");
    expect(comboboxes.length).toBeGreaterThan(0);
  });

  it("should render date filter dropdown", () => {
    renderComponent();
    // Date filter dropdown should be present
    const comboboxes = screen.getAllByRole("combobox");
    expect(comboboxes.length).toBeGreaterThan(0);
  });

  it("should render search input when no employeeId", () => {
    renderComponent();
    expect(screen.getByRole("textbox")).toBeInTheDocument();
  });

  it("should not render search input when employeeId is provided", () => {
    const { container } = renderComponent({ employeeId: "EMP001" });
    const searchInputs = container.querySelectorAll('input[placeholder*="Search"]');
    expect(searchInputs.length).toBe(0);
  });

  it("should render clear filters button when not userProfile tab", () => {
    renderComponent();
    expect(screen.getByRole("button", { name: /clear/i })).toBeInTheDocument();
  });

  it("should not render clear filters button when userProfile tab", () => {
    renderComponent({ title: "userProfile" });
    const clearButtons = screen.queryAllByRole("button", { name: /clear/i });
    expect(clearButtons.length).toBe(0);
  });

  it("should handle search with text", async () => {
    renderComponent();
    
    const searchInput = screen.getByRole("textbox");
    fireEvent.change(searchInput, { target: { value: "test" } });
    
    await waitFor(() => {
      expect(searchInput.value).toBe("test");
    });
  });

  it("should render with employeeId", () => {
    renderComponent({ employeeId: "E001" });
    expect(screen.getByTestId("common-table")).toBeInTheDocument();
  });

  it("should render as userProfile tab", () => {
    renderComponent({ title: "userProfile" });
    expect(screen.getByTestId("common-table")).toBeInTheDocument();
  });

  it("should handle date filter change", async () => {
    renderComponent();
    
    // Find date filter dropdown and interact
    const dateFilter = screen.getAllByRole("combobox")[0];
    fireEvent.mouseDown(dateFilter);
    
    await waitFor(() => {
      expect(screen.getByTestId("common-table")).toBeInTheDocument();
    });
  });

  it("should handle clear filters button click", async () => {
    renderComponent();
    
    const clearButton = screen.getByRole("button", { name: /clear/i });
    fireEvent.click(clearButton);
    
    await waitFor(() => {
      expect(screen.getByTestId("common-table")).toBeInTheDocument();
    });
  });

  it("should handle dropdown change for Alert Type", async () => {
    renderComponent();
    
    // Find the Alert Type dropdown
    const comboboxes = screen.getAllByRole("combobox");
    const alertTypeDropdown = comboboxes[0];
    
    fireEvent.mouseDown(alertTypeDropdown);
    
    await waitFor(() => {
      expect(screen.getByTestId("common-table")).toBeInTheDocument();
    });
  });

  it("should render with default props", () => {
    const { container } = render(
      <BrowserRouter>
        <UserProvider value={mockUserContext}>
          <ActivityTable />
        </UserProvider>
      </BrowserRouter>
    );
    
    expect(screen.getByTestId("common-table")).toBeInTheDocument();
  });

  it("should handle search clear when input has value", async () => {
    renderComponent();
    
    const searchInput = screen.getByRole("textbox");
    fireEvent.change(searchInput, { target: { value: "test search" } });
    
    await waitFor(() => {
      expect(searchInput.value).toBe("test search");
    });
    
    // Find and click clear button in search input
    const clearButtons = screen.getAllByRole("button");
    const searchClearBtn = clearButtons.find(btn => 
      btn.querySelector('svg[data-testid="CloseIcon"]') || 
      btn.getAttribute('aria-label')?.toLowerCase().includes('clear')
    );
    
    if (searchClearBtn) {
      fireEvent.click(searchClearBtn);
    }
    
    await waitFor(() => {
      expect(screen.getByTestId("common-table")).toBeInTheDocument();
    });
  });

  it("should render activity table wrapper", () => {
    const { container } = renderComponent();
    expect(container.querySelector(".activityTable")).toBeInTheDocument();
  });

  it("should render widgets section", () => {
    const { container } = renderComponent();
    expect(container.querySelector(".widgets")).toBeInTheDocument();
  });

  it("should render with numeric employeeId", () => {
    renderComponent({ employeeId: 12345 });
    expect(screen.getByTestId("common-table")).toBeInTheDocument();
  });

  // Additional tests to cover more lines

  // Test fetchDataDropdown error handling (lines 52-53)
  it("should handle dropdown API error gracefully", async () => {
    mockGetApi.mockRejectedValueOnce(new Error("API Error"));
    
    await act(async () => {
      renderComponent();
    });
    
    await waitFor(() => {
      expect(screen.getByTestId("common-table")).toBeInTheDocument();
    });
  });

  // Test getData error handling (line 75)
  it("should handle main data API error gracefully", async () => {
    mockPostApi.mockRejectedValueOnce(new Error("API Error"));
    
    await act(async () => {
      renderComponent();
    });
    
    await waitFor(() => {
      expect(screen.getByTestId("common-table")).toBeInTheDocument();
    });
  });

  // Test handleSearch (lines 90-95)
  it("should trigger search on search button click", async () => {
    renderComponent();
    
    const searchInput = screen.getByRole("textbox");
    fireEvent.change(searchInput, { target: { value: "john doe" } });
    
    const searchButton = screen.getByTestId("search-button");
    fireEvent.click(searchButton);
    
    await waitFor(() => {
      expect(screen.getByTestId("common-table")).toBeInTheDocument();
    });
  });

  // Test handleDateFilterChange (lines 99-113)
  it("should update filter on date range selection", async () => {
    renderComponent();
    
    const dateFilter = screen.getByRole("combobox", { name: "Date Filter" });
    fireEvent.mouseDown(dateFilter);
    
    await waitFor(() => {
      const options = screen.getAllByRole("option");
      if (options.length > 0) {
        fireEvent.click(options[0]);
      }
    });
    
    expect(screen.getByTestId("common-table")).toBeInTheDocument();
  });

  // Test resetDateRangeSelector (lines 138-150)
  it("should reset all filters on clear button click", async () => {
    renderComponent();
    
    // First set some search text
    const searchInput = screen.getByRole("textbox");
    fireEvent.change(searchInput, { target: { value: "test" } });
    
    // Then click clear filters button (the one with FilterAltOff icon)
    const clearButton = screen.getByLabelText("Clear filters");
    fireEvent.click(clearButton);
    
    await waitFor(() => {
      expect(screen.getByTestId("common-table")).toBeInTheDocument();
    });
  });

  // Test handleClear (lines 180-193)
  it("should clear search text on search clear button click", async () => {
    renderComponent();
    
    const searchInput = screen.getByRole("textbox");
    fireEvent.change(searchInput, { target: { value: "test search" } });
    
    await waitFor(() => {
      expect(searchInput.value).toBe("test search");
    });
    
    // Click the search clear button
    const clearButton = screen.getByTestId("search-clear-button");
    fireEvent.click(clearButton);
    
    await waitFor(() => {
      expect(screen.getByTestId("common-table")).toBeInTheDocument();
    });
  });

  // Test dropdown selection triggers getData
  it("should fetch data when dropdown value changes", async () => {
    renderComponent();
    
    const dropdowns = screen.getAllByRole("combobox");
    const alertTypeDropdown = dropdowns[0];
    
    fireEvent.mouseDown(alertTypeDropdown);
    
    await waitFor(() => {
      const options = screen.queryAllByRole("option");
      if (options.length > 0) {
        fireEvent.click(options[0]);
      }
    });
    
    expect(screen.getByTestId("common-table")).toBeInTheDocument();
  });

  // Test empty dropdown data
  it("should handle empty dropdown data", async () => {
    mockGetApi.mockResolvedValueOnce([]);
    
    await act(async () => {
      renderComponent();
    });
    
    await waitFor(() => {
      expect(screen.getByTestId("common-table")).toBeInTheDocument();
    });
  });

  // Test null result from main API
  it("should handle null result from main API", async () => {
    mockPostApi.mockResolvedValueOnce(null);
    
    await act(async () => {
      renderComponent();
    });
    
    await waitFor(() => {
      expect(screen.getByTestId("common-table")).toBeInTheDocument();
    });
  });

  // Test with both employeeId and searchText
  it("should prioritize employeeId over searchText", async () => {
    renderComponent({ employeeId: "EMP001" });
    
    await waitFor(() => {
      expect(screen.getByTestId("common-table")).toBeInTheDocument();
    });
  });

  // Test handleSelectChange (uncovered line)
  it("should handle activity dropdown selection change", async () => {
    renderComponent();
    
    await waitFor(() => {
      expect(screen.getByTestId("common-table")).toBeInTheDocument();
    });

    const dropdowns = screen.getAllByRole("combobox");
    if (dropdowns.length > 0) {
      fireEvent.mouseDown(dropdowns[0]);
      
      await waitFor(() => {
        const options = screen.queryAllByRole("option");
        if (options.length > 0) {
          fireEvent.click(options[0]);
        }
      });
    }
    
    expect(screen.getByTestId("common-table")).toBeInTheDocument();
  });

  // Test resetDateRangeSelector resets all states
  it("should reset all filters when clear button is clicked", async () => {
    renderComponent();
    
    // Enter search text first
    const searchInput = screen.getByRole("textbox");
    fireEvent.change(searchInput, { target: { value: "test search" } });
    
    await waitFor(() => {
      expect(searchInput.value).toBe("test search");
    });
    
    // Click clear filters button using aria-label="Clear filters"
    const clearButton = screen.getByRole("button", { name: /Clear filters/i });
    fireEvent.click(clearButton);
    
    await waitFor(() => {
      // After reset, search should be empty
      expect(screen.getByTestId("common-table")).toBeInTheDocument();
    });
  });

  // Test handleSearch with empty string
  it("should handle search with empty string", async () => {
    renderComponent();
    
    const searchInput = screen.getByRole("textbox");
    fireEvent.change(searchInput, { target: { value: "" } });
    
    await waitFor(() => {
      expect(searchInput.value).toBe("");
    });
  });

  // Test date filter with custom range
  it("should handle date filter with custom range", async () => {
    renderComponent();
    
    await waitFor(() => {
      expect(screen.getByTestId("common-table")).toBeInTheDocument();
    });
    
    // Date filter dropdown should update the date range
    const dropdowns = screen.getAllByRole("combobox");
    if (dropdowns.length > 1) {
      fireEvent.mouseDown(dropdowns[1]);
    }
    
    expect(screen.getByTestId("common-table")).toBeInTheDocument();
  });

  // Test getData with error
  it("should handle getData error gracefully", async () => {
    mockPostApi.mockRejectedValueOnce(new Error("API Error"));
    
    await act(async () => {
      renderComponent();
    });
    
    await waitFor(() => {
      expect(screen.getByTestId("common-table")).toBeInTheDocument();
    });
  });

  // Test dropdown API error
  it("should handle dropdown API error", async () => {
    mockGetApi.mockRejectedValueOnce(new Error("Dropdown API Error"));
    
    await act(async () => {
      renderComponent();
    });
    
    await waitFor(() => {
      expect(screen.getByTestId("common-table")).toBeInTheDocument();
    });
  });

  // Test without employeeId and userProfile title
  it("should render search and clear button when not userProfile", async () => {
    renderComponent({ title: "activityLog" });
    
    expect(screen.getByRole("textbox")).toBeInTheDocument();
    expect(screen.getByRole("button", { name: /clear/i })).toBeInTheDocument();
  });
});
