import json
import re
import os

DATA_DIR = os.path.join(os.path.dirname(__file__), "../data")

with open(os.path.join(DATA_DIR, "ats_keywords.json")) as f:
    ATS_KEYWORDS = json.load(f)

ACTION_VERBS = [
    "built", "developed", "designed", "led", "managed", "created", "implemented",
    "improved", "optimized", "deployed", "delivered", "collaborated", "increased",
    "reduced", "automated", "launched", "architected", "integrated", "mentored",
]

def score_structure(parsed: dict) -> tuple[int, list]:
    score = 0
    suggestions = []
    sections = ["skills", "projects", "experience", "education"]
    filled = [s for s in sections if parsed.get(s)]
    score += min(len(filled), 4) * 3  # up to 12 pts

    if parsed.get("name") and parsed.get("email"):
        score += 4
    else:
        suggestions.append("Add your name and email clearly at the top of your resume.")

    word_count = len(parsed.get("rawText", "").split())
    if 200 <= word_count <= 700:
        score += 4
    elif word_count < 200:
        suggestions.append("Your resume is too short. Add more details about your projects and experience.")
    else:
        suggestions.append("Your resume may be too long. Keep it under 2 pages.")

    return min(score, 20), suggestions

def score_skills_section(parsed: dict) -> tuple[int, list]:
    skills = parsed.get("skills", [])
    score = 0
    suggestions = []

    if skills:
        score += 5
    else:
        suggestions.append("Add a dedicated Skills section to your resume.")
        return 0, suggestions

    score += min(len(skills), 8) // 2  # up to 4 more pts for 8+ skills
    if len(skills) >= 8:
        score += 5
    elif len(skills) < 5:
        suggestions.append("Add more skills. Aim for at least 8 relevant technical skills.")

    score += 6  # assume standard names since our extractor uses a canonical list
    return min(score, 20), suggestions

def score_projects_section(parsed: dict) -> tuple[int, list]:
    projects = parsed.get("projects", [])
    score = 0
    suggestions = []

    if projects:
        score += 5
    else:
        suggestions.append("Add a Projects section. Projects are the #1 differentiator for students.")
        return 0, suggestions

    if len(projects) >= 3:
        score += 5
    else:
        suggestions.append("Add at least 3 projects to your resume.")

    has_stack = sum(1 for p in projects if p.get("techStack"))
    if has_stack >= 2:
        score += 5
    else:
        suggestions.append("Mention the tech stack (tools/languages used) for each project.")

    has_desc = sum(1 for p in projects if len(p.get("description", "").split()) > 10)
    if has_desc >= 2:
        score += 5
    else:
        suggestions.append("Write a 1–2 sentence description for each project explaining what it does.")

    return min(score, 20), suggestions

def score_experience_section(parsed: dict) -> tuple[int, list]:
    experience = parsed.get("experience", [])
    score = 0
    suggestions = []

    if not experience:
        suggestions.append("No experience found. Add internships, part-time work, or volunteer work.")
        return 5, suggestions  # partial credit for students

    score += 5
    raw = parsed.get("rawText", "").lower()
    verb_count = sum(1 for v in ACTION_VERBS if v in raw)
    if verb_count >= 5:
        score += 5
    else:
        suggestions.append("Start bullet points with action verbs like 'Built', 'Developed', 'Improved'.")

    has_numbers = bool(re.search(r"\d+%|\d+ users|\d+x", raw))
    if has_numbers:
        score += 5
    else:
        suggestions.append("Quantify your achievements (e.g., 'improved load time by 30%', 'handled 1000 users').")

    score += 5  # company + role present since our parser captured them
    return min(score, 20), suggestions

def score_keyword_optimization(parsed: dict, target_role: str = "Software Engineer") -> tuple[int, list]:
    role_keywords = ATS_KEYWORDS.get(target_role, ATS_KEYWORDS.get("Software Engineer", []))
    skills_text = " ".join(parsed.get("skills", [])).lower()
    raw_text = parsed.get("rawText", "").lower()

    matched = sum(1 for kw in role_keywords if kw.lower() in skills_text or kw.lower() in raw_text)
    ratio = matched / len(role_keywords) if role_keywords else 0
    score = int(ratio * 20)

    suggestions = []
    if ratio < 0.5:
        missing = [kw for kw in role_keywords if kw.lower() not in raw_text][:5]
        suggestions.append(f"Add these keywords to match ATS filters: {', '.join(missing)}")

    return min(score, 20), suggestions

def compute_ats_score(parsed: dict, target_role: str = "Software Engineer") -> dict:
    s1, sg1 = score_structure(parsed)
    s2, sg2 = score_skills_section(parsed)
    s3, sg3 = score_projects_section(parsed)
    s4, sg4 = score_experience_section(parsed)
    s5, sg5 = score_keyword_optimization(parsed, target_role)

    return {
        "total": s1 + s2 + s3 + s4 + s5,
        "breakdown": {
            "structure": s1,
            "skillsSection": s2,
            "projectsSection": s3,
            "experienceSection": s4,
            "keywordOptimization": s5,
        },
        "suggestions": sg1 + sg2 + sg3 + sg4 + sg5,
    }
