import { fireEvent, render, screen } from "@testing-library/react";
import { expect, test, vi } from "vitest";
import { InputCount, Sender, SenderButton } from "../src/sender";

test("InputCount displays count and limit", () => {
  render(<InputCount count={5} limit={10} />);

  const countElement = screen.getByText("5 / 10");
  expect(countElement).toBeInTheDocument();
  expect(countElement).toHaveClass("text-gray-400");
});

test("InputCount with custom className", () => {
  render(<InputCount count={3} limit={5} className="text-sm" />);

  const countElement = screen.getByText("3 / 5");
  expect(countElement).toHaveClass("text-gray-400", "text-sm");
});

test("SenderButton renders with default icon", () => {
  render(<SenderButton />);

  const button = screen.getByRole("button");
  expect(button).toHaveAttribute("data-slot", "sender-button");
  expect(button).toHaveClass("bg-blue-500");
});

test("SenderButton with custom icon", () => {
  render(<SenderButton icon={<span>Send</span>} />);

  const button = screen.getByRole("button");
  expect(button).toHaveTextContent("Send");
});

test("SenderButton shows sending state icon", () => {
  render(<SenderButton isSending={true} />);

  const button = screen.getByRole("button");
  expect(button).toHaveTextContent("■");
});

test("SenderButton shows default arrow icon when not sending", () => {
  render(<SenderButton isSending={false} />);

  const button = screen.getByRole("button");
  expect(button).toHaveTextContent("→");
});

test("Sender renders textarea and send button", () => {
  const sendMessage = vi.fn();
  render(<Sender sendMessage={sendMessage} placeholder="Type a message..." />);

  const textarea = screen.getByPlaceholderText("Type a message...");
  expect(textarea).toBeInTheDocument();

  const sendButton = screen.getByRole("button", { name: "→" });
  expect(sendButton).toBeInTheDocument();
});

test("Sender textarea accepts input", () => {
  const sendMessage = vi.fn();
  render(<Sender sendMessage={sendMessage} />);

  const textarea = screen.getByRole("textbox");
  fireEvent.change(textarea, { target: { value: "Hello world" } });

  expect(textarea).toHaveValue("Hello world");
});

test("Sender sends message on button click", () => {
  const sendMessage = vi.fn();
  render(<Sender sendMessage={sendMessage} />);

  const textarea = screen.getByRole("textbox");
  fireEvent.change(textarea, { target: { value: "Test message" } });

  const sendButton = screen.getByRole("button", { name: "→" });
  fireEvent.click(sendButton);

  expect(sendMessage).toHaveBeenCalledWith({ text: "Test message" });
});

test("Sender does not send empty message", () => {
  const sendMessage = vi.fn();
  render(<Sender sendMessage={sendMessage} />);

  const sendButton = screen.getByRole("button", { name: "→" });
  fireEvent.click(sendButton);

  expect(sendMessage).not.toHaveBeenCalled();
});

test("Sender trims whitespace before sending", () => {
  const sendMessage = vi.fn();
  render(<Sender sendMessage={sendMessage} />);

  const textarea = screen.getByRole("textbox");
  fireEvent.change(textarea, { target: { value: "  Trimmed message  " } });

  const sendButton = screen.getByRole("button", { name: "→" });
  fireEvent.click(sendButton);

  expect(sendMessage).toHaveBeenCalledWith({ text: "Trimmed message" });
});

test("Sender clears textarea after sending", () => {
  const sendMessage = vi.fn();
  render(<Sender sendMessage={sendMessage} />);

  const textarea = screen.getByRole("textbox");
  fireEvent.change(textarea, { target: { value: "Test message" } });

  const sendButton = screen.getByRole("button", { name: "→" });
  fireEvent.click(sendButton);

  expect(textarea).toHaveValue("");
});

test("Sender sends on Enter key press", () => {
  const sendMessage = vi.fn();
  render(<Sender sendMessage={sendMessage} />);

  const textarea = screen.getByRole("textbox");
  fireEvent.change(textarea, { target: { value: "Enter message" } });
  fireEvent.keyDown(textarea, { key: "Enter", shiftKey: false });

  expect(sendMessage).toHaveBeenCalledWith({ text: "Enter message" });
});

test("Sender does not send on Shift+Enter", () => {
  const sendMessage = vi.fn();
  render(<Sender sendMessage={sendMessage} />);

  const textarea = screen.getByRole("textbox");
  fireEvent.change(textarea, { target: { value: "New line" } });
  fireEvent.keyDown(textarea, { key: "Enter", shiftKey: true });

  expect(sendMessage).not.toHaveBeenCalled();
});

test("Sender calls onMessageChange on input", () => {
  const onMessageChange = vi.fn();
  render(<Sender sendMessage={vi.fn()} onMessageChange={onMessageChange} />);

  const textarea = screen.getByRole("textbox");
  fireEvent.change(textarea, { target: { value: "Changed" } });

  expect(onMessageChange).toHaveBeenCalledWith("Changed");
});

test("Sender calls onSend callback after sending", () => {
  const onSend = vi.fn();
  const sendMessage = vi.fn();
  render(<Sender sendMessage={sendMessage} onSend={onSend} />);

  const textarea = screen.getByRole("textbox");
  fireEvent.change(textarea, { target: { value: "Callback test" } });
  fireEvent.click(screen.getByRole("button", { name: "→" }));

  expect(onSend).toHaveBeenCalled();
});

test("Sender renders with initial message", () => {
  const sendMessage = vi.fn();
  render(<Sender sendMessage={sendMessage} initialMessage="Initial" />);

  const textarea = screen.getByRole("textbox");
  expect(textarea).toHaveValue("Initial");
});

test("Sender renders toolbar when provided", () => {
  const sendMessage = vi.fn();
  render(
    <Sender
      sendMessage={sendMessage}
      toolbar={<button type="button">Toolbar Button</button>}
    />,
  );

  expect(screen.getByText("Toolbar Button")).toBeInTheDocument();
});

test("Sender renders suggestion when provided", () => {
  const sendMessage = vi.fn();
  const suggestion = vi.fn(() => <div>Suggestion Content</div>);
  render(<Sender sendMessage={sendMessage} suggestion={suggestion} />);

  expect(suggestion).toHaveBeenCalled();
});