import { describe, test, expect } from "bun:test";
import { createPoll, addOption, vote, unvote, hasVoted } from "../poll.js";

describe("vote", () => {
  test("prevents double-vote (no duplicate entries)", () => {
    const poll = createPoll("Test");
    addOption(poll, "Red");
    const optionId = poll.options[0]!.id;

    vote(poll, optionId, "peer-1");
    vote(poll, optionId, "peer-1");

    expect(poll.options[0]!.votes).toEqual(["peer-1"]);
    expect(poll.options[0]!.votes).toHaveLength(1);
  });

  test("allows different peers to vote", () => {
    const poll = createPoll("Test");
    addOption(poll, "Red");
    const optionId = poll.options[0]!.id;

    vote(poll, optionId, "peer-1");
    vote(poll, optionId, "peer-2");

    expect(poll.options[0]!.votes).toEqual(["peer-1", "peer-2"]);
  });

  test("is a no-op for non-existent option ID", () => {
    const poll = createPoll("Test");
    addOption(poll, "Red");

    vote(poll, "non-existent-id", "peer-1");

    expect(poll.options[0]!.votes).toEqual([]);
  });

  test("voting on one option does not affect another option", () => {
    const poll = createPoll("Test");
    addOption(poll, "Red");
    addOption(poll, "Blue");
    const redId = poll.options[0]!.id;
    const blueId = poll.options[1]!.id;

    vote(poll, redId, "peer-1");

    expect(poll.options[0]!.votes).toEqual(["peer-1"]);
    expect(poll.options[1]!.votes).toEqual([]);

    vote(poll, blueId, "peer-2");

    expect(poll.options[0]!.votes).toEqual(["peer-1"]);
    expect(poll.options[1]!.votes).toEqual(["peer-2"]);
  });
});

describe("unvote", () => {
  test("removes peer ID from votes array", () => {
    const poll = createPoll("Test");
    addOption(poll, "Red");
    const optionId = poll.options[0]!.id;

    vote(poll, optionId, "peer-1");
    unvote(poll, optionId, "peer-1");

    expect(poll.options[0]!.votes).toEqual([]);
  });

  test("does nothing if peer has not voted", () => {
    const poll = createPoll("Test");
    addOption(poll, "Red");
    const optionId = poll.options[0]!.id;

    unvote(poll, optionId, "peer-1");

    expect(poll.options[0]!.votes).toEqual([]);
  });
});

describe("hasVoted", () => {
  test("returns true when peer has voted", () => {
    const poll = createPoll("Test");
    addOption(poll, "Red");
    const optionId = poll.options[0]!.id;

    vote(poll, optionId, "peer-1");

    expect(hasVoted(poll, optionId, "peer-1")).toBe(true);
  });

  test("returns false for non-existent option", () => {
    const poll = createPoll("Test");
    expect(hasVoted(poll, "non-existent", "peer-1")).toBe(false);
  });
});
