use std::{cmp::Ordering, collections::HashMap};

use bstr::BStr;

use crate::{
    file::{self, SectionBodyIdsLut, SectionId},
    lookup,
    parse::section,
    File,
};

/// Private helper functions
impl<'event> File<'event> {
    /// Adds a new section to the config file, returning the section id of the newly added section.
    pub(crate) fn push_section_internal(&mut self, mut section: file::Section<'event>) -> SectionId {
        let new_section_id = SectionId(self.section_id_counter);
        section.id = new_section_id;
        self.sections.insert(new_section_id, section);
        let header = &self.sections[&new_section_id].header;
        let lookup = self.section_lookup_tree.entry(header.name.clone()).or_default();

        let mut found_node = false;
        if let Some(subsection_name) = header.subsection_name.clone() {
            for node in lookup.iter_mut() {
                if let SectionBodyIdsLut::NonTerminal(subsections) = node {
                    found_node = true;
                    subsections
                        .entry(subsection_name.clone())
                        .or_default()
                        .push(new_section_id);
                    break;
                }
            }
            if !found_node {
                let mut map = HashMap::new();
                map.insert(subsection_name, vec![new_section_id]);
                lookup.push(SectionBodyIdsLut::NonTerminal(map));
            }
        } else {
            for node in lookup.iter_mut() {
                if let SectionBodyIdsLut::Terminal(vec) = node {
                    found_node = true;
                    vec.push(new_section_id);
                    break;
                }
            }
            if !found_node {
                lookup.push(SectionBodyIdsLut::Terminal(vec![new_section_id]));
            }
        }
        self.section_order.push_back(new_section_id);
        self.section_id_counter += 1;
        new_section_id
    }

    /// Inserts `section` after the section that comes `before` it, and maintains correct ordering in all of our lookup structures.
    pub(crate) fn insert_section_after(&mut self, mut section: file::Section<'event>, before: SectionId) -> SectionId {
        let lookup_section_order = {
            let section_order = &self.section_order;
            move |section_id| {
                section_order
                    .iter()
                    .enumerate()
                    .find_map(|(idx, id)| (*id == section_id).then_some(idx))
                    .expect("before-section exists")
            }
        };

        let before_order = lookup_section_order(before);
        let new_section_id = SectionId(self.section_id_counter);
        section.id = new_section_id;
        self.sections.insert(new_section_id, section);
        let header = &self.sections[&new_section_id].header;
        let lookup = self.section_lookup_tree.entry(header.name.clone()).or_default();

        let mut found_node = false;
        if let Some(subsection_name) = header.subsection_name.clone() {
            for node in lookup.iter_mut() {
                if let SectionBodyIdsLut::NonTerminal(subsections) = node {
                    found_node = true;
                    let sections_with_name_and_subsection_name =
                        subsections.entry(subsection_name.clone()).or_default();
                    let insert_pos = find_insert_pos_by_order(
                        sections_with_name_and_subsection_name,
                        before_order,
                        lookup_section_order,
                    );
                    sections_with_name_and_subsection_name.insert(insert_pos, new_section_id);
                    break;
                }
            }
            if !found_node {
                let mut map = HashMap::new();
                map.insert(subsection_name, vec![new_section_id]);
                lookup.push(SectionBodyIdsLut::NonTerminal(map));
            }
        } else {
            for node in lookup.iter_mut() {
                if let SectionBodyIdsLut::Terminal(sections_with_name) = node {
                    found_node = true;
                    let insert_pos = find_insert_pos_by_order(sections_with_name, before_order, lookup_section_order);
                    sections_with_name.insert(insert_pos, new_section_id);
                    break;
                }
            }
            if !found_node {
                lookup.push(SectionBodyIdsLut::Terminal(vec![new_section_id]));
            }
        }

        self.section_order.insert(before_order + 1, new_section_id);
        self.section_id_counter += 1;
        new_section_id
    }

    /// Returns the mapping between section and subsection name to section ids.
    pub(crate) fn section_ids_by_name_and_subname<'a>(
        &'a self,
        section_name: &'a str,
        subsection_name: Option<&BStr>,
    ) -> Result<impl ExactSizeIterator<Item = SectionId> + DoubleEndedIterator + '_, lookup::existing::Error> {
        let section_name = section::Name::from_str_unchecked(section_name);
        let section_ids = self
            .section_lookup_tree
            .get(&section_name)
            .ok_or(lookup::existing::Error::SectionMissing)?;
        let mut maybe_ids = None;
        if let Some(subsection_name) = subsection_name {
            for node in section_ids {
                if let SectionBodyIdsLut::NonTerminal(subsection_lookup) = node {
                    maybe_ids = subsection_lookup.get(subsection_name).map(|v| v.iter().copied());
                    break;
                }
            }
        } else {
            for node in section_ids {
                if let SectionBodyIdsLut::Terminal(subsection_lookup) = node {
                    maybe_ids = Some(subsection_lookup.iter().copied());
                    break;
                }
            }
        }
        maybe_ids.ok_or(lookup::existing::Error::SubSectionMissing)
    }

    pub(crate) fn section_ids_by_name<'a>(
        &'a self,
        section_name: &'a str,
    ) -> Result<impl Iterator<Item = SectionId> + '_, lookup::existing::Error> {
        let section_name = section::Name::from_str_unchecked(section_name);
        match self.section_lookup_tree.get(&section_name) {
            Some(lookup) => {
                let mut lut = Vec::with_capacity(self.section_order.len());
                for node in lookup {
                    match node {
                        SectionBodyIdsLut::Terminal(v) => lut.extend(v.iter().copied()),
                        SectionBodyIdsLut::NonTerminal(v) => lut.extend(v.values().flatten().copied()),
                    }
                }

                Ok(self.section_order.iter().filter(move |a| lut.contains(a)).copied())
            }
            None => Err(lookup::existing::Error::SectionMissing),
        }
    }
}

fn find_insert_pos_by_order(
    sections_with_name: &[SectionId],
    before_order: usize,
    lookup_section_order: impl Fn(SectionId) -> usize,
) -> usize {
    let mut insert_pos = sections_with_name.len(); // push back by default
    for (idx, candidate_id) in sections_with_name.iter().enumerate() {
        let candidate_order = lookup_section_order(*candidate_id);
        match candidate_order.cmp(&before_order) {
            Ordering::Less => {}
            Ordering::Equal => {
                insert_pos = idx + 1; // insert right after this one
                break;
            }
            Ordering::Greater => {
                insert_pos = idx; // insert before this one
                break;
            }
        }
    }
    insert_pos
}
