use crate::model::Resume;

pub fn render(resume: &Resume) -> Result<String, Box<dyn std::error::Error>> {
    let mut out = String::new();
    out.push_str(r#"\documentclass[letterpaper,11pt]{article}

\usepackage{latexsym}
\usepackage[empty]{fullpage}
\usepackage{titlesec}
\usepackage{marvosym}
\usepackage[usenames,dvipsnames]{color}
\usepackage{verbatim}
\usepackage{enumitem}
\usepackage[hidelinks]{hyperref}
\usepackage{fancyhdr}
\usepackage[english]{babel}
\usepackage{tabularx}

\pagestyle{fancy}
\fancyhf{}
\fancyfoot{}
\renewcommand{\headrulewidth}{0pt}
\renewcommand{\footrulewidth}{0pt}

\addtolength{\oddsidemargin}{-0.5in}
\addtolength{\evensidemargin}{-0.5in}
\addtolength{\textwidth}{1in}
\addtolength{\topmargin}{-.5in}
\addtolength{\textheight}{1.0in}

\urlstyle{same}
\raggedbottom
\raggedright
\setlength{\tabcolsep}{0in}

\titleformat{\section}{
  \vspace{-4pt}\scshape\raggedright\large
}{}{0em}{}[\color{black}\titlerule \vspace{-5pt}]

\newcommand{\resumeItem}[1]{
  \item\small{{#1 \vspace{-2pt}}}
}

\newcommand{\resumeSubheading}[4]{
  \vspace{-2pt}\item
    \begin{tabular*}{0.97\textwidth}[t]{l@{\extracolsep{\fill}}r}
      \textbf{#1} & #2 \\
      \textit{\small#3} & \textit{\small #4} \\
    \end{tabular*}\vspace{-7pt}
}

\newcommand{\resumeProjectHeading}[2]{
    \item
    \begin{tabular*}{0.97\textwidth}{l@{\extracolsep{\fill}}r}
      \small#1 & #2 \\
    \end{tabular*}\vspace{-7pt}
}

\renewcommand\labelitemii{$\vcenter{\hbox{\tiny$\bullet$}}$}

\newcommand{\resumeSubHeadingListStart}{\begin{itemize}[leftmargin=0.15in, label={}]}
\newcommand{\resumeSubHeadingListEnd}{\end{itemize}}
\newcommand{\resumeItemListStart}{\begin{itemize}}
\newcommand{\resumeItemListEnd}{\end{itemize}\vspace{-5pt}}

\begin{document}
"#);

    // ── heading ───────────────────────────────────────────────
    out.push_str("\n\\begin{center}\n");

    // big bold name at the top
    out.push_str(&format!(
        "    \\textbf{{\\Huge \\scshape {}}} \\\\ \\vspace{{1pt}}\n",
        esc(&resume.name)
    ));

    // contact line: phone | email | github
    // we build each part into a Vec then join them with $|$
    // this is cleaner than lots of if/else push_str calls
    let mut contact: Vec<String> = Vec::new();

    if !resume.phone.is_empty() {
        contact.push(esc(&resume.phone));
    }
    if !resume.email.is_empty() {
        // \href{mailto:x@y.com}{x@y.com} makes a clickable email link
        contact.push(format!(
            "\\href{{mailto:{email}}}{{{email}}}",
            email = esc(&resume.email)
        ));
    }
    if !resume.github.is_empty() {
        // \href{https://github.com/...}{github.com/...} clickable link
        contact.push(format!(
            "\\href{{https://{gh}}}{{{gh}}}",
            gh = esc(&resume.github)
        ));
    }

    // join with LaTeX's math pipe symbol $|$ which renders as a vertical bar
    out.push_str("    \\small ");
    out.push_str(&contact.join(" $|$ "));
    out.push_str("\n\\end{center}\n\n");

    // ── education ─────────────────────────────────────────────
    if !resume.degree.is_empty() {
        out.push_str("\\section{Education}\n");
        out.push_str("  \\resumeSubHeadingListStart\n");
        out.push_str(&format!(
            // resumeSubheading takes 4 args: {name}{right}{subtitle}{right}
            // we leave the right column empty (no city in our format)
            "    \\resumeSubheading\n      {{{}}}{{}}\n      {{{}}}{{{}}}\n",
            esc(&resume.university),
            esc(&resume.degree),
            esc(&resume.year)
        ));
        out.push_str("  \\resumeSubHeadingListEnd\n\n");
    }

    // ── experience ────────────────────────────────────────────
    if !resume.experience.is_empty() {
        out.push_str("\\section{Experience}\n");
        out.push_str("  \\resumeSubHeadingListStart\n");

        // & before resume.experience means we iterate over references
        // so we don't move/consume the Vec, we just borrow each element
        for exp in &resume.experience {
            out.push_str(&format!(
                "    \\resumeSubheading\n      {{{}}}{{}}\n      {{{}}}{{{}}}\n",
                esc(&exp.company),
                esc(&exp.role),
                esc(&exp.duration)
            ));

            if !exp.details.is_empty() {
                out.push_str("      \\resumeItemListStart\n");
                for detail in &exp.details {
                    out.push_str(&format!(
                        "        \\resumeItem{{{}}}\n",
                        esc(detail)
                    ));
                }
                out.push_str("      \\resumeItemListEnd\n");
            }
            out.push('\n');
        }

        out.push_str("  \\resumeSubHeadingListEnd\n\n");
    }

    // ── projects ──────────────────────────────────────────────
    if !resume.projects.is_empty() {
        out.push_str("\\section{Projects}\n");
        out.push_str("    \\resumeSubHeadingListStart\n");

        for proj in &resume.projects {
            // join tech vec into "Rust, Node.js, PostgreSQL"
            let tech = proj.tech.join(", ");

            // project heading: Title | tech stack
            out.push_str(&format!(
                "      \\resumeProjectHeading\n          {{\\textbf{{{}}} $|$ \\emph{{{}}}}}{{}}\n",
                esc(&proj.title),
                esc(&tech)
            ));

            if !proj.description.is_empty() {
                out.push_str("          \\resumeItemListStart\n");

                // split description on "." so each sentence becomes a bullet
                // this lets users write natural sentences in the .txt file
                for sentence in proj.description.split('.') {
                    let sentence = sentence.trim();
                    if !sentence.is_empty() {
                        out.push_str(&format!(
                            "            \\resumeItem{{{}}}\n",
                            esc(sentence)
                        ));
                    }
                }

                out.push_str("          \\resumeItemListEnd\n");
            }
            out.push('\n');
        }

        out.push_str("    \\resumeSubHeadingListEnd\n\n");
    }

    // ── technical skills ──────────────────────────────────────
    if !resume.skills.is_empty() {
        out.push_str("\\section{Technical Skills}\n");
        out.push_str(" \\begin{itemize}[leftmargin=0.15in, label={}]\n");
        out.push_str("    \\small{\\item{\n");

        // each SkillGroup becomes one line: Languages: Rust, C++, Python
        for group in &resume.skills {
            let items = group.items.join(", ");
            out.push_str(&format!(
                "     \\textbf{{{}}}{{: {}}} \\\\\n",
                esc(&group.category),
                esc(&items)
            ));
        }

        out.push_str("    }}\n \\end{itemize}\n\n");
    }

    out.push_str("\\end{document}\n");

    Ok(out)
}

fn esc(input: &str) -> String {
    input
        .replace('&', r"\&")
        .replace('%', r"\%")
        .replace('$', r"\$")
        .replace('#', r"\#")
}
