use chainhook_types::OrdinalInscriptionRevealData;
use regex::Regex;

lazy_static! {
    pub static ref RECURSIVE_INSCRIPTION_REGEX: Regex =
        Regex::new(r"/content/([a-fA-F0-9]{64}i\d+)").expect("failed to compile recursion regex");
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DbInscriptionRecursion {
    pub inscription_id: String,
    pub ref_inscription_id: String,
}

impl DbInscriptionRecursion {
    pub fn from_reveal(reveal: &OrdinalInscriptionRevealData) -> Result<Vec<Self>, String> {
        let bytes = hex::decode(&reveal.content_bytes[2..])
            .map_err(|e| format!("unable to decode inscription content for recursion: {e}"))?;
        let Ok(utf8_str) = String::from_utf8(bytes) else {
            // Not a string, we should fail silently.
            return Ok(vec![]);
        };
        let mut results = vec![];
        for capture in RECURSIVE_INSCRIPTION_REGEX.captures_iter(&utf8_str) {
            results.push(DbInscriptionRecursion {
                inscription_id: reveal.inscription_id.clone(),
                ref_inscription_id: capture.get(1).unwrap().as_str().to_string(),
            });
        }
        Ok(results)
    }
}

#[cfg(test)]
mod test {
    use chainhook_types::{OrdinalInscriptionNumber, OrdinalInscriptionRevealData};

    use super::DbInscriptionRecursion;

    #[test]
    fn test_inscription_recursion_parsing() {
        let reveal = OrdinalInscriptionRevealData {
            content_bytes: "[encoded data, 7776 characters]".to_string(),
            content_type: "text/javascript".to_string(),
            content_length: 3887,
            inscription_number: OrdinalInscriptionNumber { jubilee: 79027291, classic: 79027291 },
            inscription_fee: 100,
            inscription_output_value: 546,
            inscription_id: "e47a70a218dfa746ba410b1c057403bb481523d830562fd8dec61ec4d2915e5fi0".to_string(),
            inscription_input_index: 0 as usize,
            inscription_pointer: Some(0),
            inscriber_address: Some("bc1petvmwa7qe55jfnmqvqel6k8096s62d59c9qm2j4ypgdjwqthxt4q99stkz".to_string()),
            delegate: None,
            metaprotocol: None,
            metadata: None,
            parents: vec![],
            ordinal_number: 959876891264081,
            ordinal_block_height: 191975,
            ordinal_offset: 0,
            tx_index: 0,
            transfers_pre_inscription: 0,
            satpoint_post_inscription: "e47a70a218dfa746ba410b1c057403bb481523d830562fd8dec61ec4d2915e5f:0:0".to_string(),
            curse_type: None,
            charms: 0,
        };
        let recursions = DbInscriptionRecursion::from_reveal(&reveal).unwrap();
        assert_eq!(2, recursions.len());
        assert_eq!(
            Some(&DbInscriptionRecursion {
                inscription_id:
                    "e47a70a218dfa746ba410b1c057403bb481523d830562fd8dec61ec4d2915e5fi0".to_string(),
                ref_inscription_id:
                    "a1f0878d02a3f872b0542faf605c996306826f8ac96434c6213bd4988b769bb6i0".to_string()
            }),
            recursions.get(0)
        );
        assert_eq!(
            Some(&DbInscriptionRecursion {
                inscription_id:
                    "e47a70a218dfa746ba410b1c057403bb481523d830562fd8dec61ec4d2915e5fi0".to_string(),
                ref_inscription_id:
                    "389d4636224429262873e3d167eda4b5aba4b1e9dfe585519217b2596ba53c1ci0".to_string()
            }),
            recursions.get(1)
        );
    }
}
