
use crate::rule::{Fix, LintError, LintResult, LintWarning, Rule};
use regex::Regex;

#[derive(Debug)]
pub struct MD029OLPrefix {
    pub style: String,
}

impl Default for MD029OLPrefix {
    fn default() -> Self {
        Self {
            style: "ordered".to_string(),
        }
    }
}

impl MD029OLPrefix {
    pub fn new(style: &str) -> Self {
        Self {
            style: style.to_string(),
        }
    }

    fn get_list_number(line: &str) -> Option<usize> {
        let re = Regex::new(r"^\s*(\d+)\.\s").unwrap();
        re.captures(line)
            .and_then(|cap| cap[1].parse().ok())
    }

    fn should_be_ordered(&self, current: usize, index: usize) -> bool {
        match self.style.as_str() {
            "ordered" => current != index + 1,
            "one" => current != 1,
            "zero" => current != 0,
            _ => false,
        }
    }

    fn get_expected_number(&self, index: usize) -> usize {
        match self.style.as_str() {
            "ordered" => index + 1,
            "one" => 1,
            "zero" => 0,
            _ => index + 1,
        }
    }
}

impl Rule for MD029OLPrefix {
    fn name(&self) -> &'static str {
        "MD029"
    }

    fn description(&self) -> &'static str {
        "Ordered list item prefix should be consistent"
    }

    fn check(&self, content: &str) -> LintResult {
        let mut warnings = Vec::new();
        let mut list_index = 0;

        for (line_num, line) in content.lines().enumerate() {
            if let Some(number) = Self::get_list_number(line) {
                if self.should_be_ordered(number, list_index) {
                    let indentation = line.len() - line.trim_start().len();
                    let expected = self.get_expected_number(list_index);
                    warnings.push(LintWarning {
                        line: line_num + 1,
                        column: indentation + 1,
                        message: format!("List item prefix should be {} for style '{}'", expected, self.style),
                        fix: Some(Fix {
                            line: line_num + 1,
                            column: indentation + 1,
                            replacement: format!("{}{}.{}", 
                                " ".repeat(indentation),
                                expected,
                                line.trim_start().split('.').skip(1).collect::<String>()
                            ),
                        }),
                    });
                }
                list_index += 1;
            } else if line.trim().is_empty() {
                list_index = 0;
            }
        }

        Ok(warnings)
    }

    fn fix(&self, content: &str) -> Result<String, LintError> {
        let mut result = String::new();
        let mut list_index = 0;

        for line in content.lines() {
            if let Some(_) = Self::get_list_number(line) {
                let indentation = line.len() - line.trim_start().len();
                let expected = self.get_expected_number(list_index);
                let fixed_line = format!("{}{}.{}", 
                    " ".repeat(indentation),
                    expected,
                    line.trim_start().split('.').skip(1).collect::<String>()
                );
                result.push_str(&fixed_line);
                list_index += 1;
            } else {
                result.push_str(line);
                if line.trim().is_empty() {
                    list_index = 0;
                }
            }
            result.push('\n');
        }

        if !content.ends_with('\n') {
            result.pop();
        }

        Ok(result)
    }
} 