use convert_case::Casing;
use proc_macro2::Span;
use syn::{Ident, Path, PathSegment};

#[derive(Default, Clone)]
pub struct QueryNodePath {
    pub segments: Vec<Ident>,
}

impl QueryNodePath {
    pub fn new() -> Self {
        Self { segments: vec![] }
    }

    pub fn append(&mut self, segment: Ident) {
        self.segments.push(segment);
    }

    pub fn appended(mut self, segment: Ident) -> Self {
        self.append(segment);
        self
    }

    pub fn to_struct_name(&self, prefix: &str) -> Ident {
        let mut struct_name = prefix.to_string();
        for segment in &self.segments {
            struct_name += &segment.to_string().to_case(convert_case::Case::Pascal);
        }
        Ident::new(&struct_name, Span::call_site())
    }

    pub fn to_module_name(&self, prefix: &str) -> Ident {
        let mut module_name = prefix.to_string();
        for segment in &self.segments {
            module_name += "_";
            module_name += &segment.to_string();
        }
        Ident::new(&module_name, Span::call_site())
    }

    pub fn resolve(&self, root_table: &Path) -> Path {
        let mut path = root_table.clone();
        for segment in &self.segments {
            path.segments
                .push(Ident::new("relations", Span::call_site()).into());
            path.segments.push(PathSegment::from(segment.clone()));
            path.segments
                .push(Ident::new("target_table", Span::call_site()).into());
        }
        path
    }
}
