use anyhow::{bail, Result};
use std::process::Command;

use crate::git::cli::GitCli;

impl GitCli {
    pub fn branches(&self, repo_path: &str) -> Result<Vec<crate::app::state::BranchEntry>> {
        let output = Command::new("git")
            .args([
                "-C", repo_path,
                "branch", "-a", "--sort=-committerdate",
                "--format=%(refname:short)|%(objectname:short)|%(upstream:short)|%(authorname)|%(committerdate:relative)|%(HEAD)",
            ])
            .output()?;

        if !output.status.success() {
            bail!(
                "git branch failed (exit {}): {}",
                output.status,
                String::from_utf8_lossy(&output.stderr)
            );
        }

        let text = String::from_utf8_lossy(&output.stdout);
        let mut branches = Vec::new();
        for line in text.lines() {
            let parts: Vec<&str> = line.split('|').collect();
            if parts.len() >= 5 {
                let name = parts[0].trim().to_string();
                branches.push(crate::app::state::BranchEntry {
                    name: name.trim_start_matches("* ").to_string(),
                    is_remote: name.starts_with("remotes/"),
                    ahead: None,
                    behind: None,
                });
            }
        }
        Ok(branches)
    }

    pub fn checkout_branch(&self, repo_path: &str, branch: &str) -> Result<()> {
        let output = Command::new("git")
            .args(["-C", repo_path, "checkout", branch])
            .output()?;
        if !output.status.success() {
            bail!(
                "git checkout failed (exit {}): {}",
                output.status,
                String::from_utf8_lossy(&output.stderr)
            );
        }
        Ok(())
    }

    pub fn merge(&self, repo_path: &str, branch: &str) -> Result<()> {
        let output = Command::new("git")
            .args(["-C", repo_path, "merge", branch])
            .output()?;
        if !output.status.success() {
            bail!(
                "git merge failed: {}",
                String::from_utf8_lossy(&output.stderr)
            );
        }
        Ok(())
    }

    pub fn rebase(&self, repo_path: &str, onto_branch: &str) -> Result<()> {
        let output = Command::new("git")
            .args(["-C", repo_path, "rebase", onto_branch])
            .output()?;
        if !output.status.success() {
            bail!(
                "git rebase failed: {}",
                String::from_utf8_lossy(&output.stderr)
            );
        }
        Ok(())
    }

    pub fn create_branch(&self, repo_path: &str, branch: &str) -> Result<()> {
        let output = Command::new("git")
            .args(["-C", repo_path, "branch", branch])
            .output()?;
        if !output.status.success() {
            bail!(
                "git branch {} failed (exit {}): {}",
                branch,
                output.status,
                String::from_utf8_lossy(&output.stderr)
            );
        }
        Ok(())
    }

}