use autolib::find_version_in_str;

use crate::{Actions, GitHub};
use std::fmt::{Display, Formatter};

pub struct Release {
    sha: String,
    label: String,
}

pub enum Outputs {
    ReleaseDetected,
    TagName,
}

impl Display for Outputs {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match &self {
            Self::ReleaseDetected => write!(f, "release-detected"),
            Self::TagName => write!(f, "tag-name"),
        }
    }
}

impl Release {
    pub fn new(sha: String, label: String) -> Self {
        Self { sha, label }
    }

    pub fn detect(&self) -> anyhow::Result<()> {
        let sha = &self.sha;
        let label = &self.label;

        // Try and find the pull-request that the commit was part of to examine it.
        // A release can only ever be triggered by a pull-request being merged.
        if GitHub::find_pull_request_by(sha, label)?.is_none() {
            log::info!(
                "Could not find a pull request with hash {sha} and label \
                {label}",
            );
            return Self::miss();
        }

        let commit: String = cmd_lib::run_fun!(git log -n 1 "${sha}")?;

        // A release commits need to contain a semver version number.
        let version = find_version_in_str(&commit)?;

        match version {
            Some(v) => Self::hit(&v.to_string()),
            None => {
                log::info!(
                    "Commit message is missing version number:\n\
                    {commit}",
                );
                Self::miss()
            }
        }
    }

    fn hit(tag: &str) -> anyhow::Result<()> {
        let tag = format!("v{tag}");
        log::info!("detected release of {tag}");

        Actions::set_output([
            (Outputs::ReleaseDetected, "true"),
            (Outputs::TagName, &tag),
        ])?;

        Ok(())
    }

    fn miss() -> anyhow::Result<()> {
        log::info!("no release detected");
        Actions::set_output([(Outputs::ReleaseDetected, "false")])?;
        Ok(())
    }
}
