use crate::prelude::*;
use crate::types::{Address, Transaction, U64};
use serde::{Deserialize, Serialize};
use alloc::collections::BTreeMap;

/// Transaction Pool Content Info
///
/// The content inspection property can be queried to list the exact details of all
/// the transactions currently pending for inclusion in the next block(s), as well
/// as the ones that are being scheduled for future execution only.
///
/// See [here](https://geth.ethereum.org/docs/rpc/ns-txpool#txpool_content) for more details
///
#[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize)]
pub struct TxpoolContentInfo {
    /// pending tx
    pub pending: BTreeMap<Address, BTreeMap<String, Transaction>>,
    /// queued tx
    pub queued: BTreeMap<Address, BTreeMap<String, Transaction>>,
}

/// Transaction Pool Inspect Info
///
/// The inspect inspection property can be queried to list a textual summary
/// of all the transactions currently pending for inclusion in the next block(s),
/// as well as the ones that are being scheduled for future execution only.
/// This is a method specifically tailored to developers to quickly see the
/// transactions in the pool and find any potential issues.
///
/// See [here](https://geth.ethereum.org/docs/rpc/ns-txpool#txpool_inspect) for more details
///
#[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize)]
pub struct TxpoolInspectInfo {
    /// pending tx
    pub pending: BTreeMap<Address, BTreeMap<String, String>>,
    /// queued tx
    pub queued: BTreeMap<Address, BTreeMap<String, String>>,
}

/// Transaction Pool Status
///
/// The status inspection property can be queried for the number of transactions
/// currently pending for inclusion in the next block(s), as well as the ones that
/// are being scheduled for future execution only.
///
/// See [here](https://geth.ethereum.org/docs/rpc/ns-txpool#txpool_status) for more details
///
#[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize)]
pub struct TxpoolStatus {
    /// number of pending tx
    pub pending: U64,
    /// number of queued tx
    pub queued: U64,
}

#[cfg(test)]
mod tests {
    use super::{TxpoolContentInfo, TxpoolInspectInfo, TxpoolStatus};

    #[test]
    fn should_deserialize_txpool_content() {
        let txpool_content_str = r#"
{
  "pending": {
    "0x0513dc7403e074f5c77368ee2819fa3a65b5cf80": {
      "6712": {
        "hash": "0xc463c2dcab885136f76d093357f62b0541d1bfa4e96f27f413a7191cc625e105",
        "nonce": "0x1a38",
        "blockHash": null,
        "blockNumber": null,
        "transactionIndex": null,
        "from": "0x0513dc7403e074f5c77368ee2819fa3a65b5cf80",
        "to": "0x0b9ab0cce5238c24ea25ee3d921865da818ccf5e",
        "value": "0x1",
        "gasPrice": "0x2cb417800",
        "gas": "0x186a0",
        "input": "0x"
      }
    },
    "0x07e80128c7a35d0d43ddcc67fa8b1495871e08bf": {
      "41588": {
        "hash": "0x73057ec83d040f5d3be8afae35b447d7996472b5dedf2e727c8f4a2e1bedca14",
        "nonce": "0xa274",
        "blockHash": null,
        "blockNumber": null,
        "transactionIndex": null,
        "from": "0x07e80128c7a35d0d43ddcc67fa8b1495871e08bf",
        "to": null,
        "value": "0x0",
        "gasPrice": "0xee6b2800",
        "gas": "0xc074c",
        "input": "[encoded data, 6890 characters]"
      },
      "41589": {
        "hash": "0xc67949dfcf2e5cbb054f0711d5dbf1789801303773c85b7d0b3a8108832b99b0",
        "nonce": "0xa275",
        "blockHash": null,
        "blockNumber": null,
        "transactionIndex": null,
        "from": "0x07e80128c7a35d0d43ddcc67fa8b1495871e08bf",
        "to": null,
        "value": "0x0",
        "gasPrice": "0xee6b2800",
        "gas": "0xc074c",
        "input": "[encoded data, 6890 characters]"
      },
      "41590": {
        "hash": "0x87f1eca993dd77d4fcf34aaa078f555dde68d478c7fcc75afefbc06553bde807",
        "nonce": "0xa276",
        "blockHash": null,
        "blockNumber": null,
        "transactionIndex": null,
        "from": "0x07e80128c7a35d0d43ddcc67fa8b1495871e08bf",
        "to": null,
        "value": "0x0",
        "gasPrice": "0xee6b2800",
        "gas": "0xc074c",
        "input": "[encoded data, 6890 characters]"
      }
    }
  },
  "queued": {
    "0x0f87ffcd71859233eb259f42b236c8e9873444e3": {
      "7": {
        "hash": "0x5c2cc0e17ea6c48489fddd2a64975791e0d4a7cc0ae4a81613682fd134be1baa",
        "nonce": "0x7",
        "blockHash": null,
        "blockNumber": null,
        "transactionIndex": null,
        "from": "0x0f87ffcd71859233eb259f42b236c8e9873444e3",
        "to": "0x3479be69e07e838d9738a301bb0c89e8ea2bef4a",
        "value": "0x38d7ea4c68000",
        "gasPrice": "0x2540be400",
        "gas": "0x5208",
        "input": "0x"
      },
      "8": {
        "hash": "0x8755fadda87e9fd2e66c0bfa542baa9f552cddda334f673e272f3aa686efb5e4",
        "nonce": "0x8",
        "blockHash": null,
        "blockNumber": null,
        "transactionIndex": null,
        "from": "0x0f87ffcd71859233eb259f42b236c8e9873444e3",
        "to": "0x73aaf691bc33fe38f86260338ef88f9897ecaa4f",
        "value": "0x38d7ea4c68000",
        "gasPrice": "0x2540be400",
        "gas": "0x5208",
        "input": "0x"
      }
    },
    "0x307e8f249bcccfa5b245449256c5d7e6e079943e": {
      "3": {
        "hash": "0x54ea4d4905bf74b687ccc73e8a1fb9615357e5e82d3f716e7ab10cd8460a3221",
        "nonce": "0x3",
        "blockHash": null,
        "blockNumber": null,
        "transactionIndex": null,
        "from": "0x307e8f249bcccfa5b245449256c5d7e6e079943e",
        "to": "0x73aaf691bc33fe38f86260338ef88f9897ecaa4f",
        "value": "0x2386f26fc10000",
        "gasPrice": "0x2540be400",
        "gas": "0x5208",
        "input": "0x"
      }
    }
  }
}"#;
        let deserialized: TxpoolContentInfo = serde_json::from_str(txpool_content_str).unwrap();
        let serialized: String = serde_json::to_string_pretty(&deserialized).unwrap();
        // println!("{}", serialized);
        assert_eq!(txpool_content_str.trim(), serialized);
    }

    #[test]
    fn should_deserialize_txpool_inspect() {
        let txpool_inspect_str = r#"
{
  "pending": {
    "0x0512261a7486b1e29704ac49a5eb355b6fd86872": {
      "124930": "0x000000000000000000000000000000000000007E: 0 wei + 100187 gas × 20000000000 wei"
    },
    "0x201354729f8d0f8b64e9a0c353c672c6a66b3857": {
      "252350": "0xd10e3Be2bc8f959Bc8C41CF65F60dE721cF89ADF: 0 wei + 65792 gas × 2000000000 wei",
      "252351": "0xd10e3Be2bc8f959Bc8C41CF65F60dE721cF89ADF: 0 wei + 65792 gas × 2000000000 wei",
      "252352": "0xd10e3Be2bc8f959Bc8C41CF65F60dE721cF89ADF: 0 wei + 65780 gas × 2000000000 wei",
      "252353": "0xd10e3Be2bc8f959Bc8C41CF65F60dE721cF89ADF: 0 wei + 65780 gas × 2000000000 wei"
    }
  },
  "queued": {
    "0x0f87ffcd71859233eb259f42b236c8e9873444e3": {
      "7": "0x3479BE69e07E838D9738a301Bb0c89e8EA2Bef4a: 1000000000000000 wei + 21000 gas × 10000000000 wei",
      "8": "0x73Aaf691bc33fe38f86260338EF88f9897eCaa4F: 1000000000000000 wei + 21000 gas × 10000000000 wei"
    },
    "0x307e8f249bcccfa5b245449256c5d7e6e079943e": {
      "3": "0x73Aaf691bc33fe38f86260338EF88f9897eCaa4F: 10000000000000000 wei + 21000 gas × 10000000000 wei"
    }
  }
}"#;
        let deserialized: TxpoolInspectInfo = serde_json::from_str(txpool_inspect_str).unwrap();
        let serialized: String = serde_json::to_string_pretty(&deserialized).unwrap();
        assert_eq!(txpool_inspect_str.trim(), serialized);
    }

    #[test]
    fn should_deserialize_txpool_status() {
        let txpool_status_str = r#"
{
  "pending": "0x23",
  "queued": "0x20"
}"#;
        let deserialized: TxpoolStatus = serde_json::from_str(txpool_status_str).unwrap();
        let serialized: String = serde_json::to_string_pretty(&deserialized).unwrap();
        assert_eq!(txpool_status_str.trim(), serialized);
    }
}
