use crate::model::{Experience, Project, Resume, SkillGroup};
use std::fs;

// &str= borrowed string slice
pub fn parse_file(path: &str) -> Result<Resume, Box<dyn std::error::Error>> {
    let content = fs::read_to_string(path)?;
    parse_content(&content)
}

pub fn parse_content(content: &str) -> Result<Resume, Box<dyn std::error::Error>> {
    let mut resume = Resume::new();

    #[derive(PartialEq)]
    enum Section {
        None,
        PersonalInfo,
        Education,
        Skills,
        Projects,
        Experience,
    }

    let mut section = Section::None;

    let mut current_project:    Option<Project>    = None;
    let mut current_experience: Option<Experience> = None;

    for line in content.lines() {
        let line = line.trim();
        if line.is_empty() {
            continue;
        }

        //section headers
        // lines like "# SKILLS" or "# PROJECTS"
        if line.starts_with("# ") {

            // .take() removes the value from option
            //option<project> && <exp> become none after .take() 
            if let Some(p) = current_project.take() {
                resume.projects.push(p);
            }
            if let Some(e)=current_experience.take() {
                resume.experience.push(e);
            }
            section = match line {
                "# PERSONAL INFORMATION" => Section::PersonalInfo,
                "# EDUCATION"            => Section::Education,
                "# SKILLS"               => Section::Skills,
                "# PROJECTS"             => Section::Projects,
                "# EXPERIENCE"           => Section::Experience,
                _                        => Section::None,
            };

            continue;
        }

        match section {

            //handles both section same way
            Section::PersonalInfo | Section::Education => {
                // if let Some runs only if it returned Some(...)
                if let Some((key, value)) = split_key_value(line) {//split "name:something" into (name,something)
                    match key {
                        "name"       => resume.name       = value.to_string(),
                        "email"      => resume.email      = value.to_string(),
                        "phone"      => resume.phone      = value.to_string(),
                        "github"     => resume.github     = value.to_string(),
                        "degree"     => resume.degree     = value.to_string(),
                        "university" => resume.university = value.to_string(),
                        "year"       => resume.year       = value.to_string(),
                        _            => {}
                    }
                }
            }

            Section::Skills => {
                if let Some((category, items_str)) = split_key_value(line) {
                    let items = items_str
                        .split(',')
                        .map(|s| s.trim().to_string())
                        .collect();// .collect()   → gather into Vec<String>

                    resume.skills.push(SkillGroup {
                        category: category.to_string(),
                        items,
                    });
                }
            }

            Section::Projects => {
                if line == "project:" {
                    if let Some(p) = current_project.take() {
                        resume.projects.push(p);
                    }
                    current_project = Some(Project::default());

                } else if let Some(p) = current_project.as_mut() {
                    // .as_mut() gives mutable reference
                    // without removing it from Option (unlike .take())
                    if let Some((key, value)) = split_key_value(line) {
                        match key {
                            "title"       => p.title       = value.to_string(),
                            "description" => p.description = value.to_string(),
                            "tech"        => {
                                p.tech = value
                                    .split(',')
                                    .map(|s| s.trim().to_string())
                                    .collect();
                            }
                            _ => {}
                        }
                    }
                }
            }

            Section::Experience => {
                if line == "experience:" {
                    if let Some(e) = current_experience.take() {
                        resume.experience.push(e);
                    }
                    current_experience = Some(Experience::default());

                } else if let Some(e) = current_experience.as_mut() {
                    if let Some((key, value)) = split_key_value(line) {
                        match key {
                            "company"  => e.company  = value.to_string(),
                            "role"     => e.role     = value.to_string(),
                            "duration" => e.duration = value.to_string(),
                            _          => {}
                        }
                    } else if line.starts_with("- ") {
                        e.details.push(line[2..].to_string());
                    }
                }
            }

            Section::None => {}
        }
    }
    if let Some(p) = current_project    { resume.projects.push(p); }
    if let Some(e) = current_experience { resume.experience.push(e); }

    // wrap in Ok() to signal success
    Ok(resume)
}

fn split_key_value(line: &str) -> Option<(&str, &str)> {
    // .find(':') returns Option<usize> — the index of the first ':'
    // ? means: if None (no colon), return None from this whole function
    let pos   = line.find(':')?;
    let key   = line[..pos].trim(); // take everything before  colon
    let value = line[pos + 1..].trim();  // take everything after  colon
    Some((key, value))
}
