import { describe, it, expect } from "vitest";
import { parseReqCommand } from "./req-parser";
import { nip19 } from "nostr-tools";

describe("parseReqCommand", () => {
  describe("kind flag (-k, --kind)", () => {
    it("should parse single kind", () => {
      const result = parseReqCommand(["-k", "1"]);
      expect(result.filter.kinds).toEqual([1]);
    });

    it("should parse comma-separated kinds", () => {
      const result = parseReqCommand(["-k", "1,3,7"]);
      expect(result.filter.kinds).toEqual([1, 3, 7]);
    });

    it("should parse comma-separated kinds with spaces", () => {
      const result = parseReqCommand(["-k", "1, 3, 7"]);
      expect(result.filter.kinds).toEqual([1, 3, 7]);
    });

    it("should deduplicate kinds", () => {
      const result = parseReqCommand(["-k", "1,3,1,3"]);
      expect(result.filter.kinds).toEqual([1, 3]);
    });

    it("should deduplicate across multiple -k flags", () => {
      const result = parseReqCommand(["-k", "1", "-k", "3", "-k", "1"]);
      expect(result.filter.kinds).toEqual([1, 3]);
    });

    it("should handle --kind long form", () => {
      const result = parseReqCommand(["--kind", "1,3,7"]);
      expect(result.filter.kinds).toEqual([1, 3, 7]);
    });

    it("should ignore invalid kinds", () => {
      const result = parseReqCommand(["-k", "1,invalid,3"]);
      expect(result.filter.kinds).toEqual([1, 3]);
    });
  });

  describe("author flag (-a, --author)", () => {
    it("should parse hex pubkey", () => {
      const hex = "a".repeat(64);
      const result = parseReqCommand(["-a", hex]);
      expect(result.filter.authors).toEqual([hex]);
    });

    it("should parse npub", () => {
      // Real npub for pubkey: 3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d
      const npub =
        "npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6";
      const result = parseReqCommand(["-a", npub]);
      expect(result.filter.authors).toEqual([
        "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d",
      ]);
    });

    it("should parse nprofile", () => {
      // Real nprofile for same pubkey with relay hints
      const nprofile =
        "nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p";
      const result = parseReqCommand(["-a", nprofile]);
      expect(result.filter.authors).toEqual([
        "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d",
      ]);
    });

    it("should extract and normalize relay hints from nprofile in -a flag", () => {
      // nprofile with relay hints
      const nprofile =
        "nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p";
      const result = parseReqCommand(["-a", nprofile]);
      // Relay hints should be normalized (lowercase, trailing slash)
      expect(result.relays).toContain("wss://r.x.com/");
      expect(result.relays).toContain("wss://djbas.sadkb.com/");
    });

    it("should combine explicit relays with nprofile relay hints and normalize all", () => {
      const nprofile =
        "nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p";
      const result = parseReqCommand(["-a", nprofile, "wss://relay.damus.io"]);
      // All relays should be normalized
      expect(result.relays).toEqual([
        "wss://r.x.com/",
        "wss://djbas.sadkb.com/",
        "wss://relay.damus.io/",
      ]);
    });

    it("should extract relays from comma-separated nprofiles", () => {
      const nprofile1 =
        "nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p";
      const nprofile2 =
        "nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p";
      const result = parseReqCommand(["-a", `${nprofile1},${nprofile2}`]);
      // Should get normalized relays from both (even though they're duplicates in this test)
      expect(result.relays).toContain("wss://r.x.com/");
      expect(result.relays).toContain("wss://djbas.sadkb.com/");
    });

    it("should parse comma-separated hex pubkeys", () => {
      const hex1 = "a".repeat(64);
      const hex2 = "b".repeat(64);
      const result = parseReqCommand(["-a", `${hex1},${hex2}`]);
      expect(result.filter.authors).toEqual([hex1, hex2]);
    });

    it("should parse comma-separated mix of npub and nprofile", () => {
      const npub =
        "npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6";
      const nprofile =
        "nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p";
      const result = parseReqCommand(["-a", `${npub},${nprofile}`]);
      // Both should decode to the same pubkey, so should be deduplicated
      expect(result.filter.authors).toEqual([
        "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d",
      ]);
    });

    it("should deduplicate authors", () => {
      const hex = "a".repeat(64);
      const result = parseReqCommand(["-a", `${hex},${hex}`]);
      expect(result.filter.authors).toEqual([hex]);
    });

    it("should accumulate NIP-05 identifiers for async resolution", () => {
      const result = parseReqCommand([
        "-a",
        "user@domain.com,alice@example.com",
      ]);
      expect(result.nip05Authors).toEqual([
        "user@domain.com",
        "alice@example.com",
      ]);
      expect(result.filter.authors).toBeUndefined();
    });

    it("should handle mixed hex, npub, nprofile, and NIP-05", () => {
      const hex = "a".repeat(64);
      const npub =
        "npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6";
      const result = parseReqCommand(["-a", `${hex},${npub},user@domain.com`]);
      expect(result.filter.authors).toEqual([
        hex,
        "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d",
      ]);
      expect(result.nip05Authors).toEqual(["user@domain.com"]);
    });

    it("should deduplicate NIP-05 identifiers", () => {
      const result = parseReqCommand(["-a", "user@domain.com,user@domain.com"]);
      expect(result.nip05Authors).toEqual(["user@domain.com"]);
    });

    it("should accumulate @domain syntax for async resolution", () => {
      const result = parseReqCommand(["-a", "@habla.news"]);
      expect(result.domainAuthors).toEqual(["habla.news"]);
      expect(result.filter.authors).toBeUndefined();
    });

    it("should accumulate multiple @domains for async resolution", () => {
      const result = parseReqCommand(["-a", "@habla.news,@nostr.com"]);
      expect(result.domainAuthors).toEqual(["habla.news", "nostr.com"]);
      expect(result.filter.authors).toBeUndefined();
    });

    it("should handle mixed hex, NIP-05, and @domain", () => {
      const hex = "a".repeat(64);
      const result = parseReqCommand([
        "-a",
        `${hex},user@domain.com,@habla.news`,
      ]);
      expect(result.filter.authors).toEqual([hex]);
      expect(result.nip05Authors).toEqual(["user@domain.com"]);
      expect(result.domainAuthors).toEqual(["habla.news"]);
    });

    it("should deduplicate @domain identifiers", () => {
      const result = parseReqCommand(["-a", "@habla.news,@habla.news"]);
      expect(result.domainAuthors).toEqual(["habla.news"]);
    });

    it("should preserve @domain case (normalization happens in resolution)", () => {
      const result = parseReqCommand(["-a", "@Habla.News"]);
      expect(result.domainAuthors).toEqual(["Habla.News"]);
    });

    it("should reject invalid @domain formats", () => {
      const result = parseReqCommand(["-a", "@invalid"]);
      expect(result.domainAuthors).toBeUndefined();
      expect(result.filter.authors).toBeUndefined();
    });
  });

  describe("event ID flag (-e)", () => {
    it("should parse hex event ID", () => {
      const hex = "a".repeat(64);
      const result = parseReqCommand(["-e", hex]);
      expect(result.filter["#e"]).toEqual([hex]);
    });

    it("should parse comma-separated event IDs", () => {
      const hex1 = "a".repeat(64);
      const hex2 = "b".repeat(64);
      const result = parseReqCommand(["-e", `${hex1},${hex2}`]);
      expect(result.filter["#e"]).toEqual([hex1, hex2]);
    });

    it("should deduplicate event IDs", () => {
      const hex = "a".repeat(64);
      const result = parseReqCommand(["-e", `${hex},${hex}`]);
      expect(result.filter["#e"]).toEqual([hex]);
    });
  });

  describe("event ID flag (-e) with nevent/naddr support", () => {
    describe("nevent support", () => {
      it("should parse nevent and populate filter.ids", () => {
        const eventId =
          "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d";
        const nevent = nip19.neventEncode({
          id: eventId,
        });
        const result = parseReqCommand(["-e", nevent]);

        expect(result.filter.ids).toBeDefined();
        expect(result.filter.ids).toHaveLength(1);
        expect(result.filter.ids).toEqual([eventId]);
        expect(result.filter["#e"]).toBeUndefined();
      });

      it("should extract relay hints from nevent", () => {
        const eventId =
          "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d";
        const nevent = nip19.neventEncode({
          id: eventId,
          relays: ["wss://relay.damus.io"],
        });
        const result = parseReqCommand(["-e", nevent]);

        expect(result.relays).toBeDefined();
        expect(result.relays).toContain("wss://relay.damus.io/");
      });

      it("should normalize relay URLs from nevent", () => {
        const eventId =
          "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d";
        const nevent = nip19.neventEncode({
          id: eventId,
          relays: ["wss://relay.damus.io"],
        });
        const result = parseReqCommand(["-e", nevent]);

        result.relays?.forEach((url) => {
          expect(url).toMatch(/^wss?:\/\//);
          expect(url).toMatch(/\/$/); // trailing slash
        });
      });

      it("should handle nevent without relay hints", () => {
        const eventId =
          "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d";
        const nevent = nip19.neventEncode({
          id: eventId,
        });
        const result = parseReqCommand(["-e", nevent]);

        expect(result.filter.ids).toHaveLength(1);
        expect(result.relays).toBeUndefined();
      });
    });

    describe("naddr support", () => {
      it("should parse naddr and populate filter['#a']", () => {
        const pubkey =
          "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d";
        const naddr = nip19.naddrEncode({
          kind: 30023,
          pubkey: pubkey,
          identifier: "test-article",
        });
        const result = parseReqCommand(["-e", naddr]);

        expect(result.filter["#a"]).toBeDefined();
        expect(result.filter["#a"]).toHaveLength(1);
        expect(result.filter["#a"]?.[0]).toBe(`30023:${pubkey}:test-article`);
      });

      it("should extract relay hints from naddr", () => {
        const pubkey =
          "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d";
        const naddr = nip19.naddrEncode({
          kind: 30023,
          pubkey: pubkey,
          identifier: "test-article",
          relays: ["wss://relay.damus.io", "wss://nos.lol"],
        });
        const result = parseReqCommand(["-e", naddr]);

        expect(result.relays).toBeDefined();
        expect(result.relays!.length).toBe(2);
        expect(result.relays).toContain("wss://relay.damus.io/");
        expect(result.relays).toContain("wss://nos.lol/");
      });

      it("should format coordinate correctly (kind:pubkey:identifier)", () => {
        const pubkey =
          "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d";
        const naddr = nip19.naddrEncode({
          kind: 30023,
          pubkey: pubkey,
          identifier: "test-article",
        });
        const result = parseReqCommand(["-e", naddr]);

        const coordinate = result.filter["#a"]?.[0];
        expect(coordinate).toBe(`30023:${pubkey}:test-article`);
        // Validate format: kind:pubkey:identifier
        const parts = coordinate?.split(":");
        expect(parts).toHaveLength(3);
        expect(parseInt(parts![0])).toBe(30023);
        expect(parts![1]).toBe(pubkey);
        expect(parts![2]).toBe("test-article");
      });

      it("should handle naddr without relay hints", () => {
        const pubkey =
          "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d";
        const naddr = nip19.naddrEncode({
          kind: 30023,
          pubkey: pubkey,
          identifier: "test-article",
        });
        const result = parseReqCommand(["-e", naddr]);

        expect(result.filter["#a"]).toHaveLength(1);
        expect(result.relays).toBeUndefined();
      });
    });

    describe("note/hex support (existing behavior)", () => {
      it("should parse note and populate filter['#e']", () => {
        const eventId =
          "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d";
        const note = nip19.noteEncode(eventId);
        const result = parseReqCommand(["-e", note]);

        expect(result.filter["#e"]).toBeDefined();
        expect(result.filter["#e"]).toHaveLength(1);
        expect(result.filter["#e"]).toContain(eventId);
        expect(result.filter.ids).toBeUndefined();
        expect(result.filter["#a"]).toBeUndefined();
      });

      it("should parse hex and populate filter['#e']", () => {
        const hex = "a".repeat(64);
        const result = parseReqCommand(["-e", hex]);

        expect(result.filter["#e"]).toContain(hex);
        expect(result.filter.ids).toBeUndefined();
      });
    });

    describe("mixed format support", () => {
      it("should handle comma-separated mix of all formats", () => {
        const hex = "a".repeat(64);
        const eventId =
          "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d";
        const pubkey = "b".repeat(64);

        const note = nip19.noteEncode(eventId);
        const nevent = nip19.neventEncode({ id: eventId });
        const naddr = nip19.naddrEncode({
          kind: 30023,
          pubkey: pubkey,
          identifier: "test-article",
        });

        const result = parseReqCommand([
          "-e",
          `${hex},${note},${nevent},${naddr}`,
        ]);

        // hex and note should go to filter["#e"]
        expect(result.filter["#e"]).toHaveLength(2);
        expect(result.filter["#e"]).toContain(hex);
        expect(result.filter["#e"]).toContain(eventId);

        // nevent should go to filter.ids
        expect(result.filter.ids).toHaveLength(1);
        expect(result.filter.ids).toContain(eventId);

        // naddr should go to filter["#a"]
        expect(result.filter["#a"]).toHaveLength(1);
        expect(result.filter["#a"]?.[0]).toBe(`30023:${pubkey}:test-article`);
      });

      it("should deduplicate within each filter field", () => {
        const eventId =
          "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d";
        const nevent1 = nip19.neventEncode({ id: eventId });
        const nevent2 = nip19.neventEncode({
          id: eventId,
          relays: ["wss://relay.damus.io"],
        });

        const result = parseReqCommand(["-e", `${nevent1},${nevent2}`]);

        // Both nevent decode to same event ID, should deduplicate
        expect(result.filter.ids).toHaveLength(1);
      });

      it("should collect relay hints from mixed formats", () => {
        const eventId =
          "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d";
        const pubkey = "b".repeat(64);

        const nevent = nip19.neventEncode({
          id: eventId,
          relays: ["wss://relay.damus.io"],
        });
        const naddr = nip19.naddrEncode({
          kind: 30023,
          pubkey: pubkey,
          identifier: "test-article",
          relays: ["wss://nos.lol"],
        });

        const result = parseReqCommand(["-e", `${nevent},${naddr}`]);

        expect(result.relays).toBeDefined();
        expect(result.relays!.length).toBe(2);
        expect(result.relays).toContain("wss://relay.damus.io/");
        expect(result.relays).toContain("wss://nos.lol/");
      });

      it("should handle multiple nevents with different relay hints", () => {
        const eventId =
          "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d";
        const nevent1 = nip19.neventEncode({
          id: eventId,
          relays: ["wss://relay.damus.io"],
        });
        const hex = "b".repeat(64);

        const result = parseReqCommand(["-e", `${nevent1},${hex}`]);

        // nevent goes to filter.ids
        expect(result.filter.ids).toHaveLength(1);
        // hex goes to filter["#e"]
        expect(result.filter["#e"]).toContain(hex);
        // relays extracted from nevent
        expect(result.relays).toBeDefined();
        expect(result.relays).toContain("wss://relay.damus.io/");
      });
    });

    describe("error handling", () => {
      it("should ignore invalid bech32", () => {
        const result = parseReqCommand(["-e", "nevent1invalid"]);

        expect(result.filter.ids).toBeUndefined();
        expect(result.filter["#e"]).toBeUndefined();
        expect(result.filter["#a"]).toBeUndefined();
      });

      it("should ignore invalid naddr", () => {
        const result = parseReqCommand(["-e", "naddr1invalid"]);

        expect(result.filter["#a"]).toBeUndefined();
      });

      it("should skip empty values in comma-separated list", () => {
        const hex = "a".repeat(64);
        const result = parseReqCommand(["-e", `${hex},,`]);

        expect(result.filter["#e"]).toEqual([hex]);
      });

      it("should continue parsing after encountering invalid values", () => {
        const hex1 = "a".repeat(64);
        const hex2 = "b".repeat(64);
        const result = parseReqCommand([
          "-e",
          `${hex1},invalid_bech32,${hex2}`,
        ]);

        expect(result.filter["#e"]).toEqual([hex1, hex2]);
      });
    });

    describe("integration with other flags", () => {
      it("should work with kind filter", () => {
        const eventId =
          "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d";
        const nevent = nip19.neventEncode({ id: eventId });
        const result = parseReqCommand(["-k", "1", "-e", nevent]);

        expect(result.filter.kinds).toEqual([1]);
        expect(result.filter.ids).toHaveLength(1);
      });

      it("should work with explicit relays", () => {
        const pubkey = "b".repeat(64);
        const naddr = nip19.naddrEncode({
          kind: 30023,
          pubkey: pubkey,
          identifier: "test-article",
        });
        const result = parseReqCommand([
          "-e",
          naddr,
          "wss://relay.example.com",
        ]);

        expect(result.filter["#a"]).toHaveLength(1);
        expect(result.relays).toContain("wss://relay.example.com/");
      });

      it("should work with author and time filters", () => {
        const hex = "c".repeat(64);
        const eventId =
          "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d";
        const nevent = nip19.neventEncode({ id: eventId });
        const result = parseReqCommand([
          "-k",
          "1",
          "-a",
          hex,
          "-e",
          nevent,
          "--since",
          "24h",
          "-l",
          "50",
        ]);

        expect(result.filter.kinds).toEqual([1]);
        expect(result.filter.authors).toEqual([hex]);
        expect(result.filter.ids).toHaveLength(1);
        expect(result.filter.since).toBeDefined();
        expect(result.filter.limit).toBe(50);
      });
    });
  });

  describe("pubkey tag flag (-p)", () => {
    it("should parse hex pubkey for #p tag", () => {
      const hex = "a".repeat(64);
      const result = parseReqCommand(["-p", hex]);
      expect(result.filter["#p"]).toEqual([hex]);
    });

    it("should parse npub for #p tag", () => {
      const npub =
        "npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6";
      const result = parseReqCommand(["-p", npub]);
      expect(result.filter["#p"]).toEqual([
        "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d",
      ]);
    });

    it("should parse nprofile for #p tag", () => {
      const nprofile =
        "nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p";
      const result = parseReqCommand(["-p", nprofile]);
      expect(result.filter["#p"]).toEqual([
        "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d",
      ]);
    });

    it("should extract and normalize relay hints from nprofile in -p flag", () => {
      const nprofile =
        "nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p";
      const result = parseReqCommand(["-p", nprofile]);
      // Relay hints should be normalized (lowercase, trailing slash)
      expect(result.relays).toContain("wss://r.x.com/");
      expect(result.relays).toContain("wss://djbas.sadkb.com/");
    });

    it("should parse comma-separated pubkeys", () => {
      const hex1 = "a".repeat(64);
      const hex2 = "b".repeat(64);
      const result = parseReqCommand(["-p", `${hex1},${hex2}`]);
      expect(result.filter["#p"]).toEqual([hex1, hex2]);
    });

    it("should accumulate NIP-05 identifiers for #p tags", () => {
      const result = parseReqCommand([
        "-p",
        "user@domain.com,alice@example.com",
      ]);
      expect(result.nip05PTags).toEqual([
        "user@domain.com",
        "alice@example.com",
      ]);
      expect(result.filter["#p"]).toBeUndefined();
    });

    it("should handle mixed hex, npub, nprofile, and NIP-05 for #p tags", () => {
      const hex = "a".repeat(64);
      const npub =
        "npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6";
      const result = parseReqCommand(["-p", `${hex},${npub},user@domain.com`]);
      expect(result.filter["#p"]).toEqual([
        hex,
        "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d",
      ]);
      expect(result.nip05PTags).toEqual(["user@domain.com"]);
    });

    it("should deduplicate #p tags", () => {
      const hex = "a".repeat(64);
      const result = parseReqCommand(["-p", `${hex},${hex}`]);
      expect(result.filter["#p"]).toEqual([hex]);
    });

    it("should accumulate @domain syntax for #p tags", () => {
      const result = parseReqCommand(["-p", "@habla.news"]);
      expect(result.domainPTags).toEqual(["habla.news"]);
      expect(result.filter["#p"]).toBeUndefined();
    });

    it("should handle mixed hex, NIP-05, and @domain for #p tags", () => {
      const hex = "a".repeat(64);
      const result = parseReqCommand([
        "-p",
        `${hex},user@domain.com,@habla.news`,
      ]);
      expect(result.filter["#p"]).toEqual([hex]);
      expect(result.nip05PTags).toEqual(["user@domain.com"]);
      expect(result.domainPTags).toEqual(["habla.news"]);
    });
  });

  describe("uppercase P tag flag (-P)", () => {
    it("should parse hex pubkey for #P tag", () => {
      const hex = "a".repeat(64);
      const result = parseReqCommand(["-P", hex]);
      expect(result.filter["#P"]).toEqual([hex]);
    });

    it("should parse npub for #P tag", () => {
      const npub =
        "npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6";
      const result = parseReqCommand(["-P", npub]);
      expect(result.filter["#P"]).toEqual([
        "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d",
      ]);
    });

    it("should parse nprofile for #P tag", () => {
      const nprofile =
        "nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p";
      const result = parseReqCommand(["-P", nprofile]);
      expect(result.filter["#P"]).toEqual([
        "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d",
      ]);
    });

    it("should parse comma-separated pubkeys for #P", () => {
      const hex1 = "a".repeat(64);
      const hex2 = "b".repeat(64);
      const result = parseReqCommand(["-P", `${hex1},${hex2}`]);
      expect(result.filter["#P"]).toEqual([hex1, hex2]);
    });

    it("should accumulate NIP-05 identifiers for #P tags", () => {
      const result = parseReqCommand([
        "-P",
        "user@domain.com,alice@example.com",
      ]);
      expect(result.nip05PTagsUppercase).toEqual([
        "user@domain.com",
        "alice@example.com",
      ]);
      expect(result.filter["#P"]).toBeUndefined();
    });

    it("should handle mixed hex, npub, and NIP-05 for #P tags", () => {
      const hex = "a".repeat(64);
      const npub =
        "npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6";
      const result = parseReqCommand(["-P", `${hex},${npub},user@domain.com`]);
      expect(result.filter["#P"]).toEqual([
        hex,
        "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d",
      ]);
      expect(result.nip05PTagsUppercase).toEqual(["user@domain.com"]);
    });

    it("should deduplicate #P tags", () => {
      const hex = "a".repeat(64);
      const result = parseReqCommand(["-P", `${hex},${hex}`]);
      expect(result.filter["#P"]).toEqual([hex]);
    });

    it("should accumulate @domain syntax for #P tags", () => {
      const result = parseReqCommand(["-P", "@habla.news"]);
      expect(result.domainPTagsUppercase).toEqual(["habla.news"]);
      expect(result.filter["#P"]).toBeUndefined();
    });

    it("should handle mixed hex, NIP-05, and @domain for #P tags", () => {
      const hex = "a".repeat(64);
      const result = parseReqCommand([
        "-P",
        `${hex},user@domain.com,@habla.news`,
      ]);
      expect(result.filter["#P"]).toEqual([hex]);
      expect(result.nip05PTagsUppercase).toEqual(["user@domain.com"]);
      expect(result.domainPTagsUppercase).toEqual(["habla.news"]);
    });

    it("should handle $me alias in #P tags", () => {
      const result = parseReqCommand(["-P", "$me"]);
      expect(result.filter["#P"]).toContain("$me");
      expect(result.needsAccount).toBe(true);
    });

    it("should handle $contacts alias in #P tags", () => {
      const result = parseReqCommand(["-P", "$contacts"]);
      expect(result.filter["#P"]).toContain("$contacts");
      expect(result.needsAccount).toBe(true);
    });

    it("should handle mixed aliases and pubkeys in #P", () => {
      const hex = "a".repeat(64);
      const result = parseReqCommand(["-P", `$me,${hex},$contacts`]);
      expect(result.filter["#P"]).toContain("$me");
      expect(result.filter["#P"]).toContain(hex);
      expect(result.filter["#P"]).toContain("$contacts");
      expect(result.needsAccount).toBe(true);
    });

    it("should differentiate between -p and -P flags", () => {
      const hex1 = "a".repeat(64);
      const hex2 = "b".repeat(64);
      const result = parseReqCommand(["-p", hex1, "-P", hex2]);
      expect(result.filter["#p"]).toEqual([hex1]);
      expect(result.filter["#P"]).toEqual([hex2]);
    });
  });

  describe("hashtag flag (-t)", () => {
    it("should parse single hashtag", () => {
      const result = parseReqCommand(["-t", "nostr"]);
      expect(result.filter["#t"]).toEqual(["nostr"]);
    });

    it("should parse comma-separated hashtags", () => {
      const result = parseReqCommand(["-t", "nostr,bitcoin,lightning"]);
      expect(result.filter["#t"]).toEqual(["nostr", "bitcoin", "lightning"]);
    });

    it("should parse comma-separated hashtags with spaces", () => {
      const result = parseReqCommand(["-t", "nostr, bitcoin, lightning"]);
      expect(result.filter["#t"]).toEqual(["nostr", "bitcoin", "lightning"]);
    });

    it("should deduplicate hashtags", () => {
      const result = parseReqCommand(["-t", "nostr,bitcoin,nostr"]);
      expect(result.filter["#t"]).toEqual(["nostr", "bitcoin"]);
    });
  });

  describe("d-tag flag (-d)", () => {
    it("should parse single d-tag", () => {
      const result = parseReqCommand(["-d", "article1"]);
      expect(result.filter["#d"]).toEqual(["article1"]);
    });

    it("should parse comma-separated d-tags", () => {
      const result = parseReqCommand(["-d", "article1,article2,article3"]);
      expect(result.filter["#d"]).toEqual(["article1", "article2", "article3"]);
    });

    it("should deduplicate d-tags", () => {
      const result = parseReqCommand(["-d", "article1,article2,article1"]);
      expect(result.filter["#d"]).toEqual(["article1", "article2"]);
    });
  });

  describe("limit flag (-l, --limit)", () => {
    it("should parse limit", () => {
      const result = parseReqCommand(["-l", "100"]);
      expect(result.filter.limit).toBe(100);
    });

    it("should handle --limit long form", () => {
      const result = parseReqCommand(["--limit", "50"]);
      expect(result.filter.limit).toBe(50);
    });
  });

  describe("time flags (--since, --until)", () => {
    describe("unix timestamps", () => {
      it("should parse unix timestamp for --since", () => {
        const result = parseReqCommand(["--since", "1234567890"]);
        expect(result.filter.since).toBe(1234567890);
      });

      it("should parse unix timestamp for --until", () => {
        const result = parseReqCommand(["--until", "1234567890"]);
        expect(result.filter.until).toBe(1234567890);
      });
    });

    describe("relative time - seconds (s)", () => {
      it("should parse seconds for --since", () => {
        const now = Math.floor(Date.now() / 1000);
        const result = parseReqCommand(["--since", "30s"]);
        expect(result.filter.since).toBeDefined();
        expect(result.filter.since).toBeGreaterThan(now - 35);
        expect(result.filter.since).toBeLessThan(now - 25);
      });

      it("should parse 1 second for --since", () => {
        const now = Math.floor(Date.now() / 1000);
        const result = parseReqCommand(["--since", "1s"]);
        expect(result.filter.since).toBeDefined();
        expect(result.filter.since).toBeGreaterThan(now - 5);
        expect(result.filter.since).toBeLessThan(now + 1);
      });

      it("should parse seconds for --until", () => {
        const now = Math.floor(Date.now() / 1000);
        const result = parseReqCommand(["--until", "30s"]);
        expect(result.filter.until).toBeDefined();
        expect(result.filter.until).toBeGreaterThan(now - 35);
        expect(result.filter.until).toBeLessThan(now - 25);
      });
    });

    describe("relative time - minutes (m)", () => {
      it("should parse minutes for --since", () => {
        const now = Math.floor(Date.now() / 1000);
        const result = parseReqCommand(["--since", "30m"]);
        expect(result.filter.since).toBeDefined();
        const diff = now - result.filter.since!;
        expect(diff).toBeGreaterThan(1795); // 30m - 5s
        expect(diff).toBeLessThan(1805); // 30m + 5s
      });

      it("should parse 1 minute for --since", () => {
        const now = Math.floor(Date.now() / 1000);
        const result = parseReqCommand(["--since", "1m"]);
        expect(result.filter.since).toBeDefined();
        const diff = now - result.filter.since!;
        expect(diff).toBeGreaterThan(55); // 1m - 5s
        expect(diff).toBeLessThan(65); // 1m + 5s
      });
    });

    describe("relative time - hours (h)", () => {
      it("should parse hours for --since", () => {
        const now = Math.floor(Date.now() / 1000);
        const result = parseReqCommand(["--since", "2h"]);
        expect(result.filter.since).toBeDefined();
        const diff = now - result.filter.since!;
        expect(diff).toBeGreaterThan(7195); // 2h - 5s
        expect(diff).toBeLessThan(7205); // 2h + 5s
      });

      it("should parse 24 hours for --since", () => {
        const now = Math.floor(Date.now() / 1000);
        const result = parseReqCommand(["--since", "24h"]);
        expect(result.filter.since).toBeDefined();
        const diff = now - result.filter.since!;
        expect(diff).toBeGreaterThan(86395); // 24h - 5s
        expect(diff).toBeLessThan(86405); // 24h + 5s
      });
    });

    describe("relative time - days (d)", () => {
      it("should parse days for --since", () => {
        const now = Math.floor(Date.now() / 1000);
        const result = parseReqCommand(["--since", "7d"]);
        expect(result.filter.since).toBeDefined();
        const diff = now - result.filter.since!;
        expect(diff).toBeGreaterThan(604795); // 7d - 5s
        expect(diff).toBeLessThan(604805); // 7d + 5s
      });

      it("should parse 1 day for --since", () => {
        const now = Math.floor(Date.now() / 1000);
        const result = parseReqCommand(["--since", "1d"]);
        expect(result.filter.since).toBeDefined();
        const diff = now - result.filter.since!;
        expect(diff).toBeGreaterThan(86395); // 1d - 5s
        expect(diff).toBeLessThan(86405); // 1d + 5s
      });
    });

    describe("relative time - weeks (w)", () => {
      it("should parse weeks for --since", () => {
        const now = Math.floor(Date.now() / 1000);
        const result = parseReqCommand(["--since", "2w"]);
        expect(result.filter.since).toBeDefined();
        const diff = now - result.filter.since!;
        expect(diff).toBeGreaterThan(1209595); // 2w - 5s
        expect(diff).toBeLessThan(1209605); // 2w + 5s
      });

      it("should parse 1 week for --since", () => {
        const now = Math.floor(Date.now() / 1000);
        const result = parseReqCommand(["--since", "1w"]);
        expect(result.filter.since).toBeDefined();
        const diff = now - result.filter.since!;
        expect(diff).toBeGreaterThan(604795); // 1w - 5s
        expect(diff).toBeLessThan(604805); // 1w + 5s
      });
    });

    describe("relative time - months (mo)", () => {
      it("should parse months for --since", () => {
        const now = Math.floor(Date.now() / 1000);
        const result = parseReqCommand(["--since", "3mo"]);
        expect(result.filter.since).toBeDefined();
        const diff = now - result.filter.since!;
        // 3 months = 7776000 seconds (90 days)
        expect(diff).toBeGreaterThan(7775995); // 3mo - 5s
        expect(diff).toBeLessThan(7776005); // 3mo + 5s
      });

      it("should parse 1 month for --since", () => {
        const now = Math.floor(Date.now() / 1000);
        const result = parseReqCommand(["--since", "1mo"]);
        expect(result.filter.since).toBeDefined();
        const diff = now - result.filter.since!;
        // 1 month = 2592000 seconds (30 days)
        expect(diff).toBeGreaterThan(2591995); // 1mo - 5s
        expect(diff).toBeLessThan(2592005); // 1mo + 5s
      });
    });

    describe("relative time - years (y)", () => {
      it("should parse years for --since", () => {
        const now = Math.floor(Date.now() / 1000);
        const result = parseReqCommand(["--since", "4y"]);
        expect(result.filter.since).toBeDefined();
        const diff = now - result.filter.since!;
        // 4 years = 126144000 seconds (1460 days)
        expect(diff).toBeGreaterThan(126143995); // 4y - 5s
        expect(diff).toBeLessThan(126144005); // 4y + 5s
      });

      it("should parse 1 year for --since", () => {
        const now = Math.floor(Date.now() / 1000);
        const result = parseReqCommand(["--since", "1y"]);
        expect(result.filter.since).toBeDefined();
        const diff = now - result.filter.since!;
        // 1 year = 31536000 seconds (365 days)
        expect(diff).toBeGreaterThan(31535995); // 1y - 5s
        expect(diff).toBeLessThan(31536005); // 1y + 5s
      });
    });

    describe("special keyword - now", () => {
      it("should parse 'now' for --since", () => {
        const before = Math.floor(Date.now() / 1000);
        const result = parseReqCommand(["--since", "now"]);
        const after = Math.floor(Date.now() / 1000);

        expect(result.filter.since).toBeDefined();
        expect(result.filter.since).toBeGreaterThanOrEqual(before);
        expect(result.filter.since).toBeLessThanOrEqual(after);
      });

      it("should parse 'now' for --until", () => {
        const before = Math.floor(Date.now() / 1000);
        const result = parseReqCommand(["--until", "now"]);
        const after = Math.floor(Date.now() / 1000);

        expect(result.filter.until).toBeDefined();
        expect(result.filter.until).toBeGreaterThanOrEqual(before);
        expect(result.filter.until).toBeLessThanOrEqual(after);
      });

      it("should be case-insensitive for 'now'", () => {
        const result1 = parseReqCommand(["--since", "NOW"]);
        const result2 = parseReqCommand(["--since", "Now"]);
        const result3 = parseReqCommand(["--since", "now"]);

        expect(result1.filter.since).toBeDefined();
        expect(result2.filter.since).toBeDefined();
        expect(result3.filter.since).toBeDefined();
      });

      it("should work with other filters", () => {
        const now = Math.floor(Date.now() / 1000);
        const result = parseReqCommand([
          "-k",
          "1",
          "--since",
          "7d",
          "--until",
          "now",
        ]);

        expect(result.filter.kinds).toEqual([1]);
        expect(result.filter.since).toBeLessThan(now);
        expect(result.filter.until).toBeGreaterThanOrEqual(now - 1);
        expect(result.filter.until).toBeLessThanOrEqual(now + 1);
      });
    });

    describe("invalid time formats", () => {
      it("should return undefined for invalid time format", () => {
        const result = parseReqCommand(["--since", "invalid"]);
        expect(result.filter.since).toBeUndefined();
      });

      it("should return undefined for time unit without number", () => {
        const result = parseReqCommand(["--since", "h"]);
        expect(result.filter.since).toBeUndefined();
      });

      it("should return undefined for unsupported unit", () => {
        const result = parseReqCommand(["--since", "5x"]);
        expect(result.filter.since).toBeUndefined();
      });

      it("should return undefined for negative time", () => {
        const result = parseReqCommand(["--since", "-5h"]);
        expect(result.filter.since).toBeUndefined();
      });
    });

    describe("combined time flags", () => {
      it("should parse both --since and --until", () => {
        const result = parseReqCommand([
          "--since",
          "7d",
          "--until",
          "1d",
          "-k",
          "1",
        ]);
        expect(result.filter.since).toBeDefined();
        expect(result.filter.until).toBeDefined();
        expect(result.filter.since).toBeLessThan(result.filter.until!);
        expect(result.filter.kinds).toEqual([1]);
      });

      it("should work with unix timestamps for time range", () => {
        const result = parseReqCommand([
          "--since",
          "1600000000",
          "--until",
          "1700000000",
        ]);
        expect(result.filter.since).toBe(1600000000);
        expect(result.filter.until).toBe(1700000000);
      });

      it("should work with mixed relative and unix timestamps", () => {
        const now = Math.floor(Date.now() / 1000);
        const result = parseReqCommand([
          "--since",
          "7d",
          "--until",
          "1234567890",
        ]);
        expect(result.filter.since).toBeDefined();
        expect(result.filter.since).toBeLessThan(now);
        expect(result.filter.until).toBe(1234567890);
      });
    });
  });

  describe("search flag (--search)", () => {
    it("should parse search query", () => {
      const result = parseReqCommand(["--search", "bitcoin"]);
      expect(result.filter.search).toBe("bitcoin");
    });
  });

  describe("relay parsing", () => {
    it("should parse relay with wss:// protocol and normalize", () => {
      const result = parseReqCommand(["wss://relay.example.com"]);
      expect(result.relays).toEqual(["wss://relay.example.com/"]);
    });

    it("should parse relay domain and add wss:// with trailing slash", () => {
      const result = parseReqCommand(["relay.example.com"]);
      expect(result.relays).toEqual(["wss://relay.example.com/"]);
    });

    it("should parse multiple relays and normalize all", () => {
      const result = parseReqCommand([
        "wss://relay1.com",
        "relay2.com",
        "wss://relay3.com/",
      ]);
      expect(result.relays).toEqual([
        "wss://relay1.com/",
        "wss://relay2.com/",
        "wss://relay3.com/",
      ]);
    });

    it("should normalize relays with and without trailing slash to same value", () => {
      const result = parseReqCommand(["wss://relay.com", "wss://relay.com/"]);
      // Should deduplicate because they normalize to the same URL
      expect(result.relays).toEqual(["wss://relay.com/", "wss://relay.com/"]);
    });

    it("should lowercase relay URLs during normalization", () => {
      const result = parseReqCommand(["wss://Relay.Example.COM"]);
      expect(result.relays).toEqual(["wss://relay.example.com/"]);
    });
  });

  describe("close-on-eose flag", () => {
    it("should parse --close-on-eose", () => {
      const result = parseReqCommand(["--close-on-eose"]);
      expect(result.closeOnEose).toBe(true);
    });

    it("should default to false when not provided", () => {
      const result = parseReqCommand(["-k", "1"]);
      expect(result.closeOnEose).toBe(false);
    });
  });

  describe("complex scenarios", () => {
    it("should handle multiple flags together", () => {
      const hex = "a".repeat(64);
      const result = parseReqCommand([
        "-k",
        "1,3",
        "-a",
        hex,
        "-t",
        "nostr,bitcoin",
        "-l",
        "100",
        "--since",
        "1h",
        "relay.example.com",
      ]);

      expect(result.filter.kinds).toEqual([1, 3]);
      expect(result.filter.authors).toEqual([hex]);
      expect(result.filter["#t"]).toEqual(["nostr", "bitcoin"]);
      expect(result.filter.limit).toBe(100);
      expect(result.filter.since).toBeDefined();
      expect(result.relays).toEqual(["wss://relay.example.com/"]);
    });

    it("should handle deduplication across multiple flags and commas", () => {
      const result = parseReqCommand([
        "-k",
        "1,3",
        "-k",
        "3,7",
        "-k",
        "1",
        "-t",
        "nostr",
        "-t",
        "bitcoin,nostr",
      ]);

      expect(result.filter.kinds).toEqual([1, 3, 7]);
      expect(result.filter["#t"]).toEqual(["nostr", "bitcoin"]);
    });

    it("should handle empty comma-separated values", () => {
      const result = parseReqCommand(["-k", "1,,3,,"]);
      expect(result.filter.kinds).toEqual([1, 3]);
    });

    it("should handle whitespace in comma-separated values", () => {
      const result = parseReqCommand(["-t", " nostr , bitcoin , lightning "]);
      expect(result.filter["#t"]).toEqual(["nostr", "bitcoin", "lightning"]);
    });
  });

  describe("generic tag flag (--tag, -T)", () => {
    it("should parse single generic tag", () => {
      const result = parseReqCommand(["--tag", "a", "30023:abc:article"]);
      expect(result.filter["#a"]).toEqual(["30023:abc:article"]);
    });

    it("should parse short form -T", () => {
      const result = parseReqCommand(["-T", "a", "30023:abc:article"]);
      expect(result.filter["#a"]).toEqual(["30023:abc:article"]);
    });

    it("should parse comma-separated values", () => {
      const result = parseReqCommand([
        "--tag",
        "a",
        "30023:abc:article1,30023:abc:article2,30023:abc:article3",
      ]);
      expect(result.filter["#a"]).toEqual([
        "30023:abc:article1",
        "30023:abc:article2",
        "30023:abc:article3",
      ]);
    });

    it("should parse comma-separated values with spaces", () => {
      const result = parseReqCommand(["--tag", "a", "value1, value2, value3"]);
      expect(result.filter["#a"]).toEqual(["value1", "value2", "value3"]);
    });

    it("should deduplicate values within single tag", () => {
      const result = parseReqCommand([
        "--tag",
        "a",
        "value1,value2,value1,value2",
      ]);
      expect(result.filter["#a"]).toEqual(["value1", "value2"]);
    });

    it("should accumulate values across multiple --tag flags for same letter", () => {
      const result = parseReqCommand([
        "--tag",
        "a",
        "value1",
        "--tag",
        "a",
        "value2",
        "--tag",
        "a",
        "value3",
      ]);
      expect(result.filter["#a"]).toEqual(["value1", "value2", "value3"]);
    });

    it("should deduplicate across multiple --tag flags", () => {
      const result = parseReqCommand([
        "--tag",
        "a",
        "value1,value2",
        "--tag",
        "a",
        "value2,value3",
      ]);
      expect(result.filter["#a"]).toEqual(["value1", "value2", "value3"]);
    });

    it("should handle multiple different generic tags", () => {
      const result = parseReqCommand([
        "--tag",
        "a",
        "address1",
        "--tag",
        "r",
        "https://example.com",
        "--tag",
        "g",
        "geohash123",
      ]);
      expect(result.filter["#a"]).toEqual(["address1"]);
      expect(result.filter["#r"]).toEqual(["https://example.com"]);
      expect(result.filter["#g"]).toEqual(["geohash123"]);
    });

    it("should work alongside specific tag flags", () => {
      const result = parseReqCommand([
        "-t",
        "nostr",
        "--tag",
        "a",
        "30023:abc:article",
        "-d",
        "article1",
      ]);
      expect(result.filter["#t"]).toEqual(["nostr"]);
      expect(result.filter["#a"]).toEqual(["30023:abc:article"]);
      expect(result.filter["#d"]).toEqual(["article1"]);
    });

    it("should not conflict with -a author flag", () => {
      const hex = "a".repeat(64);
      const result = parseReqCommand([
        "-a",
        hex,
        "--tag",
        "a",
        "30023:abc:article",
      ]);
      expect(result.filter.authors).toEqual([hex]);
      expect(result.filter["#a"]).toEqual(["30023:abc:article"]);
    });

    it("should ignore --tag without letter argument", () => {
      const result = parseReqCommand(["--tag"]);
      expect(result.filter["#a"]).toBeUndefined();
    });

    it("should ignore --tag without value argument", () => {
      const result = parseReqCommand(["--tag", "a"]);
      expect(result.filter["#a"]).toBeUndefined();
    });

    it("should ignore --tag with multi-character letter", () => {
      const result = parseReqCommand(["--tag", "abc", "value"]);
      expect(result.filter["#abc"]).toBeUndefined();
    });

    it("should handle empty values in comma-separated list", () => {
      const result = parseReqCommand(["--tag", "a", "value1,,value2,,"]);
      expect(result.filter["#a"]).toEqual(["value1", "value2"]);
    });

    it("should handle whitespace in comma-separated values", () => {
      const result = parseReqCommand([
        "--tag",
        "a",
        " value1 , value2 , value3 ",
      ]);
      expect(result.filter["#a"]).toEqual(["value1", "value2", "value3"]);
    });

    it("should support any single-letter tag", () => {
      const result = parseReqCommand([
        "--tag",
        "x",
        "xval",
        "--tag",
        "y",
        "yval",
        "--tag",
        "z",
        "zval",
      ]);
      expect(result.filter["#x"]).toEqual(["xval"]);
      expect(result.filter["#y"]).toEqual(["yval"]);
      expect(result.filter["#z"]).toEqual(["zval"]);
    });
  });

  describe("$me and $contacts aliases", () => {
    describe("$me alias in authors (-a)", () => {
      it("should detect $me in authors", () => {
        const result = parseReqCommand(["-a", "$me"]);
        expect(result.filter.authors).toContain("$me");
        expect(result.needsAccount).toBe(true);
      });

      it("should handle $me with other pubkeys", () => {
        const hex = "a".repeat(64);
        const result = parseReqCommand(["-a", `$me,${hex}`]);
        expect(result.filter.authors).toContain("$me");
        expect(result.filter.authors).toContain(hex);
        expect(result.needsAccount).toBe(true);
      });

      it("should deduplicate $me", () => {
        const result = parseReqCommand(["-a", "$me,$me"]);
        expect(result.filter.authors).toEqual(["$me"]);
      });
    });

    describe("$contacts alias in authors (-a)", () => {
      it("should detect $contacts in authors", () => {
        const result = parseReqCommand(["-a", "$contacts"]);
        expect(result.filter.authors).toContain("$contacts");
        expect(result.needsAccount).toBe(true);
      });

      it("should handle $contacts with other pubkeys", () => {
        const hex = "a".repeat(64);
        const result = parseReqCommand(["-a", `$contacts,${hex}`]);
        expect(result.filter.authors).toContain("$contacts");
        expect(result.filter.authors).toContain(hex);
        expect(result.needsAccount).toBe(true);
      });

      it("should handle $me and $contacts together", () => {
        const result = parseReqCommand(["-a", "$me,$contacts"]);
        expect(result.filter.authors).toContain("$me");
        expect(result.filter.authors).toContain("$contacts");
        expect(result.needsAccount).toBe(true);
      });
    });

    describe("case-insensitive aliases", () => {
      it("should normalize $ME to $me in authors", () => {
        const result = parseReqCommand(["-a", "$ME"]);
        expect(result.filter.authors).toContain("$me");
        expect(result.needsAccount).toBe(true);
      });

      it("should normalize $CONTACTS to $contacts in authors", () => {
        const result = parseReqCommand(["-a", "$CONTACTS"]);
        expect(result.filter.authors).toContain("$contacts");
        expect(result.needsAccount).toBe(true);
      });

      it("should normalize mixed case $Me to $me in #p tags", () => {
        const result = parseReqCommand(["-p", "$Me"]);
        expect(result.filter["#p"]).toContain("$me");
        expect(result.needsAccount).toBe(true);
      });

      it("should normalize $CONTACTS to $contacts in #P tags", () => {
        const result = parseReqCommand(["-P", "$CONTACTS"]);
        expect(result.filter["#P"]).toContain("$contacts");
        expect(result.needsAccount).toBe(true);
      });

      it("should handle mixed case aliases with other values", () => {
        const hex = "a".repeat(64);
        const result = parseReqCommand(["-a", `$ME,${hex},$Contacts`]);
        expect(result.filter.authors).toContain("$me");
        expect(result.filter.authors).toContain("$contacts");
        expect(result.filter.authors).toContain(hex);
        expect(result.needsAccount).toBe(true);
      });
    });

    describe("$me alias in #p tags (-p)", () => {
      it("should detect $me in #p tags", () => {
        const result = parseReqCommand(["-p", "$me"]);
        expect(result.filter["#p"]).toContain("$me");
        expect(result.needsAccount).toBe(true);
      });

      it("should handle $me with other pubkeys in #p", () => {
        const hex = "a".repeat(64);
        const result = parseReqCommand(["-p", `$me,${hex}`]);
        expect(result.filter["#p"]).toContain("$me");
        expect(result.filter["#p"]).toContain(hex);
        expect(result.needsAccount).toBe(true);
      });
    });

    describe("$contacts alias in #p tags (-p)", () => {
      it("should detect $contacts in #p tags", () => {
        const result = parseReqCommand(["-p", "$contacts"]);
        expect(result.filter["#p"]).toContain("$contacts");
        expect(result.needsAccount).toBe(true);
      });

      it("should handle $contacts with other pubkeys in #p", () => {
        const hex = "a".repeat(64);
        const result = parseReqCommand(["-p", `$contacts,${hex}`]);
        expect(result.filter["#p"]).toContain("$contacts");
        expect(result.filter["#p"]).toContain(hex);
        expect(result.needsAccount).toBe(true);
      });

      it("should handle $me and $contacts together in #p", () => {
        const result = parseReqCommand(["-p", "$me,$contacts"]);
        expect(result.filter["#p"]).toContain("$me");
        expect(result.filter["#p"]).toContain("$contacts");
        expect(result.needsAccount).toBe(true);
      });
    });

    describe("mixed aliases across -a and -p", () => {
      it("should set needsAccount if alias in authors only", () => {
        const result = parseReqCommand(["-a", "$me", "-k", "1"]);
        expect(result.needsAccount).toBe(true);
      });

      it("should set needsAccount if alias in #p only", () => {
        const result = parseReqCommand(["-p", "$contacts", "-k", "1"]);
        expect(result.needsAccount).toBe(true);
      });

      it("should set needsAccount if aliases in both", () => {
        const result = parseReqCommand(["-a", "$me", "-p", "$contacts"]);
        expect(result.needsAccount).toBe(true);
      });

      it("should not set needsAccount without aliases", () => {
        const hex = "a".repeat(64);
        const result = parseReqCommand(["-a", hex, "-k", "1"]);
        expect(result.needsAccount).toBe(false);
      });
    });

    describe("complex scenarios with aliases", () => {
      it("should handle aliases with other filter types", () => {
        const result = parseReqCommand([
          "-k",
          "1",
          "-a",
          "$contacts",
          "--since",
          "24h",
          "-l",
          "50",
        ]);
        expect(result.filter.kinds).toEqual([1]);
        expect(result.filter.authors).toContain("$contacts");
        expect(result.filter.since).toBeDefined();
        expect(result.filter.limit).toBe(50);
        expect(result.needsAccount).toBe(true);
      });

      it("should handle mixed pubkeys, NIP-05, and aliases", () => {
        const hex = "a".repeat(64);
        const result = parseReqCommand([
          "-a",
          `${hex},$me,user@domain.com,$contacts`,
        ]);
        expect(result.filter.authors).toContain(hex);
        expect(result.filter.authors).toContain("$me");
        expect(result.filter.authors).toContain("$contacts");
        expect(result.nip05Authors).toEqual(["user@domain.com"]);
        expect(result.needsAccount).toBe(true);
      });
    });
  });

  describe("edge cases", () => {
    it("should handle empty args", () => {
      const result = parseReqCommand([]);
      expect(result.filter).toEqual({});
      expect(result.relays).toBeUndefined();
      expect(result.closeOnEose).toBe(false);
    });

    it("should handle flag without value", () => {
      const result = parseReqCommand(["-k"]);
      expect(result.filter.kinds).toBeUndefined();
    });

    it("should handle unknown flags gracefully", () => {
      const result = parseReqCommand(["-x", "value", "-k", "1"]);
      expect(result.filter.kinds).toEqual([1]);
    });
  });
});
