import { ethers, type BytesLike } from "ethers";
import type { AsyncRes } from "./types.js";
import * as ed from "@noble/ed25519";

const KIMAP_ABI = [
  "function get(bytes32 namehash) external view returns (address tba, address owner, bytes memory data)",
  "function leaf(bytes32 parenthash, bytes calldata label) external pure returns (bytes32 namehash)",
  "function tbaOf(bytes32 entry) external view returns (address tba)",
];

const KIMAP_ADDRESS = "0x000000000044C6B8Cb4d8f0F889a3E47664EAeda";
// const KIMAP_ADDRESS = "0x969cAbCE3625224BA3d340ea4dC2f929301188Ad";
const RPC_URL =
  "https://base-mainnet.g.alchemy.com/v2/jWsKWKv217Jz-9Nnnu7uJpW6gqmBcNog";
class KimapClient {
  apiKey;
  contract;
  constructor(apiKey: string) {
    this.apiKey = apiKey;
    const provider = ethers.getDefaultProvider(RPC_URL);
    const contract = new ethers.Contract(KIMAP_ADDRESS, KIMAP_ABI, provider);
    this.contract = contract;
  }
  async fetchAbi() {
    const url = `https://api.basescan.org/api?module=contract&action=getabi&address=${KIMAP_ADDRESS}&apikey=${this.apiKey}`;
    try {
      const response = await fetch(url);
      const data = await response.json();
      if (data.status === "1") {
        return data.result; // ABI as a JSON string
      } else {
        throw new Error("Failed to fetch ABI: " + data.message);
      }
    } catch (error) {
      console.error("Error fetching ABI:", error);
      throw error;
    }
  }
  async getPublicKey(name: string): AsyncRes<string> {
    const hash = await this.namehash(name);
    console.log({ name, hash, contract: KIMAP_ADDRESS });
    // const res = await this.contract!.get(hash);
    // console.log({ res });
    const netKeyNoteNamehash = await this.contract.leaf(
      hash,
      ethers.toUtf8Bytes("~net-key"),
    );
    const stoof = await this.contract.get(hash);
    console.log({ stoof });
    const [tba, owner, data] = await this.contract.get(netKeyNoteNamehash);
    if (!data || data === "0x") {
      return { error: "no data" };
    }
    return { ok: data };
  }
  async namehash(name: string) {
    let hash = ethers.ZeroHash;
    const labels = name.split(".").reverse();
    for (const part of labels) {
      const newhash = await this.contract!.leaf(hash, ethers.toUtf8Bytes(part));
      hash = newhash;
    }
    return hash;
  }

  async verifySignature(
    node: string,
    messageArray: number[],
    signatureArray: number[],
  ): AsyncRes<boolean> {
    // This is not a Browser transaction signature, this doesn't work
    try {
      const publicKey = await this.getPublicKey(node);
      console.log({ publicKey });
      if ("error" in publicKey)
        return { error: "no public key found for " + node };
      const publicKeyBytes = ethers.getBytes(publicKey.ok);
      let messageBytes = new Uint8Array(messageArray);
      let signatureBytes = new Uint8Array(signatureArray);
      const isValid = await ed.verifyAsync(
        signatureBytes,
        messageBytes,
        publicKeyBytes,
      );
      return { ok: isValid };
    } catch (e) {
      return { error: `${e}` };
    }
  }
}

export default KimapClient;

// export function getClient() {
//   const client = new KimapClient(KIMAP_ADDRESS, Bun.env.BASESCAN_API_KEY!);
//   return client;
// }
// async setContract() {
//   const abi = await this.fetchAbi();
//   // console.log(JSON.parse(abi));
//   const provider = ethers.getDefaultProvider(RPC_URL);
//   const contract = new ethers.Contract(
//     this.contractAddress,
//     abi,
//     provider,
//   );
//   this.contract = contract;
// }
//   async verifySignature(
//     node: string,
//     messageBytes: BytesLike,
//     signatureBytes: BytesLike,
//   ): Promise<boolean> {
//     // This is not a Browser transaction signature, this doesn't work
//     const publicKey = await this.getPublicKey(node);
//     console.log({ publicKey });
//     if ("error" in publicKey) return false;
//     // const messageBytes = ethers.toUtf8Bytes(message);
//     const r = ethers.hexlify(signatureBytes.slice(0, 32));
//     const s = ethers.hexlify(signatureBytes.slice(32, 64));
//     const v = Number(ethers.hexlify(signatureBytes.slice(64, 65)));
//     const signature = { r, s, v };
//     const messageHash = ethers.hashMessage(messageBytes);
//     const recovered = ethers.recoverAddress(messageHash, signature);
//     // const lol: ethers.SignatureLike = "";
//     console.log({ messageHash, recovered, publicKey });

//     return false;
//   }
// }
// const toCheck = {
//   data: {
//     body: {
//       site: "f",
//       time: 1741297185312,
//       nonce: "ff",
//     },
//     message: [
//       115, 111, 114, 116, 117, 103, 100, 101, 118, 111, 46, 111, 115, 64, 108,
//       111, 103, 105, 110, 58, 108, 111, 103, 105, 110, 58, 115, 121, 115, 123,
//       34, 83, 105, 103, 110, 34, 58, 123, 34, 115, 105, 116, 101, 34, 58, 34,
//       102, 34, 44, 34, 116, 105, 109, 101, 34, 58, 49, 55, 52, 49, 50, 57, 55,
//       49, 56, 53, 51, 49, 50, 44, 34, 110, 111, 110, 99, 101, 34, 58, 34, 102,
//       102, 34, 125, 125,
//     ],
//     signature: [
//       41, 45, 105, 167, 143, 76, 68, 129, 157, 100, 71, 117, 117, 151, 89, 80,
//       40, 118, 14, 21, 235, 190, 98, 239, 156, 131, 225, 216, 167, 160, 96, 43,
//       132, 148, 254, 29, 49, 164, 131, 181, 205, 197, 136, 63, 175, 223, 57,
//       231, 253, 87, 130, 12, 118, 153, 72, 201, 246, 125, 200, 70, 4, 176, 98,
//       9,
//     ],
//   },
// };
// async function run() {
//   const client = new KimapClient(KIMAP_ADDRESS, BASESCAN_API_KEY);
//   // await client.setContract();
//   // client.getPublicKey("sortugdevo.os");
//   const messageBytes = new Uint8Array(toCheck.data.message);
//   const signatureBytes = new Uint8Array(toCheck.data.signature);
//   client.verifySignature("sortugdevo.os", messageBytes, signatureBytes);
// }
// run();
