import { expect } from "chai";
import {
  detectOutputScriptType,
  getScriptTypeFromAddress,
} from "../src/common";
import { ScriptType } from "../src/types";

describe("getScriptTypeFromAddress", () => {
  describe("Mainnet addresses", () => {
    it("should detect P2PKH addresses (starting with 1)", () => {
      expect(
        getScriptTypeFromAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"),
      ).to.equal(ScriptType.P2PKH);
      expect(
        getScriptTypeFromAddress("12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX"),
      ).to.equal(ScriptType.P2PKH);
    });

    it("should detect P2SH addresses (starting with 3)", () => {
      expect(
        getScriptTypeFromAddress("3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy"),
      ).to.equal(ScriptType.P2SH);
      expect(
        getScriptTypeFromAddress("3FZbgi29cpjq2GjdwV8eyHuJJnkLtktZc5"),
      ).to.equal(ScriptType.P2SH);
    });

    it("should detect P2WPKH addresses (starting with bc1q)", () => {
      expect(
        getScriptTypeFromAddress("bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"),
      ).to.equal(ScriptType.P2WPKH);
    });

    it("should detect P2WSH addresses (starting with bc1q)", () => {
      expect(
        getScriptTypeFromAddress(
          "bc1qp3eqzeuz97rh3nnhapy5lxjguueazurqdezd8rjakcwjscp6dwcsqckypc",
        ),
      ).to.equal(ScriptType.P2WSH);
    });

    it("should detect P2TR addresses (starting with bc1p)", () => {
      expect(
        getScriptTypeFromAddress(
          "bc1pp4djkw70g7s27hhj7j3hddfca3hgzsay66xhpw2mt26znqpdds8sw7lxz2",
        ),
      ).to.equal(ScriptType.P2TR);
    });
  });

  describe("Testnet addresses", () => {
    it("should detect testnet P2PKH addresses (starting with m or n)", () => {
      expect(
        getScriptTypeFromAddress("mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn"),
      ).to.equal(ScriptType.P2PKH);
      expect(
        getScriptTypeFromAddress("n4f7rXQcbpoYFUbTenRZCaqJ1fhgoJxik3"),
      ).to.equal(ScriptType.P2PKH);
    });

    it("should detect testnet P2SH addresses (starting with 2)", () => {
      expect(
        getScriptTypeFromAddress("2NByHN6A8QYkBATzxf4pRGbCSHD5CEN2TRu"),
      ).to.equal(ScriptType.P2SH);
    });

    it("should detect testnet P2WPKH addresses (starting with tb1q)", () => {
      expect(
        getScriptTypeFromAddress("tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx"),
      ).to.equal(ScriptType.P2WPKH);
    });

    it("should detect testnet P2WSH addresses (starting with tb1q)", () => {
      expect(
        getScriptTypeFromAddress(
          "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
        ),
      ).to.equal(ScriptType.P2WSH);
    });

    it("should detect testnet P2TR addresses (starting with tb1p)", () => {
      expect(
        getScriptTypeFromAddress(
          "tb1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vq47zagq",
        ),
      ).to.equal(ScriptType.P2TR);
    });
  });

  describe("Invalid addresses", () => {
    it("should return UNKNOWN for invalid addresses", () => {
      expect(getScriptTypeFromAddress("")).to.equal(ScriptType.UNKNOWN);
      expect(getScriptTypeFromAddress("not an address")).to.equal(
        ScriptType.UNKNOWN,
      );
      expect(getScriptTypeFromAddress("bc1invalid")).to.equal(
        ScriptType.UNKNOWN,
      );
      expect(getScriptTypeFromAddress("1111111111111111111114")).to.equal(
        ScriptType.UNKNOWN,
      ); // Invalid checksum
    });

    it("should return UNKNOWN for non-string inputs", () => {
      expect(getScriptTypeFromAddress(null as never)).to.equal(
        ScriptType.UNKNOWN,
      );
      expect(getScriptTypeFromAddress(undefined as never)).to.equal(
        ScriptType.UNKNOWN,
      );
      expect(getScriptTypeFromAddress(123 as never)).to.equal(
        ScriptType.UNKNOWN,
      );
    });
  });

  describe("Edge cases", () => {
    it("should return UNKNOWN for P2PK addresses (no standard address format)", () => {
      // P2PK doesn't have a standard address format
      expect(getScriptTypeFromAddress("04somepublickey")).to.equal(
        ScriptType.UNKNOWN,
      );
    });

    it("should return UNKNOWN for OP_RETURN (no address format)", () => {
      // OP_RETURN doesn't have an address format
      expect(getScriptTypeFromAddress("OP_RETURN")).to.equal(
        ScriptType.UNKNOWN,
      );
    });
  });
});
describe("Real Signet Transactions", () => {
  it("should return correct script type", () => {
    const P2PK =
      "41049464205950188c29d377eebca6535e0f3699ce4069ecd77ffebfbd0bcf95e3c134cb7d2742d800a12df41413a09ef87a80516353a2f0a280547bb5512dc03da8ac";
    expect(detectOutputScriptType(Buffer.from(P2PK, "hex"))).eq(
      ScriptType.P2PK,
    );

    const P2TR =
      "51200f0c8db753acbd17343a39c2f3f4e35e4be6da749f9e35137ab220e7b238a667";
    expect(detectOutputScriptType(Buffer.from(P2TR, "hex"))).eq(
      ScriptType.P2TR,
    );

    const P2PKH = "76a91455ae51684c43435da751ac8d2173b2652eb6410588ac";
    expect(detectOutputScriptType(Buffer.from(P2PKH, "hex"))).eq(
      ScriptType.P2PKH,
    );

    const P2SH = "a914748284390f9e263a4b766a75d0633c50426eb87587";
    expect(detectOutputScriptType(Buffer.from(P2SH, "hex"))).eq(
      ScriptType.P2SH,
    );

    const P2WPKH = "0014841b80d2cc75f5345c482af96294d04fdd66b2b7";
    expect(detectOutputScriptType(Buffer.from(P2WPKH, "hex"))).eq(
      ScriptType.P2WPKH,
    );

    const P2WSH =
      "002065f91a53cb7120057db3d378bd0f7d944167d43a7dcbff15d6afc4823f1d3ed3";
    expect(detectOutputScriptType(Buffer.from(P2WSH, "hex"))).eq(
      ScriptType.P2WSH,
    );

    const OP_RETURN = "6a0b68656c6c6f20776f726c64";
    expect(detectOutputScriptType(Buffer.from(OP_RETURN, "hex"))).eq(
      ScriptType.OP_RETURN,
    );

    const P2SH_P2WPKH_SCRIPT = "a9144733f37cf4db86fbc2efed2500b4f4e49f31202387";
    const P2SH_P2WPKH_REDEEM = "0014841b80d2cc75f5345c482af96294d04fdd66b2b7";
    expect(
      detectOutputScriptType(
        Buffer.from(P2SH_P2WPKH_SCRIPT, "hex"),
        Buffer.from(P2SH_P2WPKH_REDEEM, "hex"),
      ),
    ).eq(ScriptType.P2SH_P2WPKH);

    const P2SH_P2WSH_SCRIPT = "a9141d0f172a0ecb48aee1be1f2687d2963ae33f71a187";
    const P2SH_P2WSH_REDEEM =
      "002065f91a53cb7120057db3d378bd0f7d944167d43a7dcbff15d6afc4823f1d3ed3";
    expect(
      detectOutputScriptType(
        Buffer.from(P2SH_P2WSH_SCRIPT, "hex"),
        Buffer.from(P2SH_P2WSH_REDEEM, "hex"),
      ),
    ).eq(ScriptType.P2SH_P2WSH);
  });
});
