use anyhow::Result;
use serde::Serialize;

use crate::app::App;
use crate::output::{Format, print_success_or};

#[derive(Serialize)]
struct UpdateResult {
    current_version: String,
    latest_version: String,
    status: String,
}

impl App {
    pub fn update(&self, check: bool) -> Result<()> {
        let current = env!("CARGO_PKG_VERSION");

        let updater = self_update::backends::github::Update::configure()
            .repo_owner("199-biotechnologies")
            .repo_name("email-cli")
            .bin_name("email-cli")
            .current_version(current)
            .build()?;

        if check {
            let latest = updater.get_latest_release()?;
            let v = latest.version.trim_start_matches('v').to_string();
            let up_to_date = v == current;
            let result = UpdateResult {
                current_version: current.into(),
                latest_version: v.clone(),
                status: if up_to_date {
                    "up_to_date".into()
                } else {
                    "update_available".into()
                },
            };
            print_success_or(self.format, &result, |r| {
                if up_to_date {
                    println!("Up to date (v{})", r.current_version);
                } else {
                    println!("Update available: v{} -> v{}", r.current_version, r.latest_version);
                    println!("Run `email-cli update` to install");
                }
            });
        } else {
            match updater.update() {
                Ok(release) => {
                    let v = release.version().trim_start_matches('v').to_string();
                    let up_to_date = v == current;
                    let result = UpdateResult {
                        current_version: current.into(),
                        latest_version: v.clone(),
                        status: if up_to_date {
                            "up_to_date".into()
                        } else {
                            "updated".into()
                        },
                    };
                    print_success_or(self.format, &result, |r| {
                        if up_to_date {
                            println!("Already up to date (v{})", r.current_version);
                        } else {
                            println!("Updated: v{} -> v{}", r.current_version, r.latest_version);
                            println!("Run `email-cli skill install` to update agent skills");
                        }
                    });
                }
                Err(e) => {
                    anyhow::bail!("update failed: {}", e);
                }
            }
        }

        Ok(())
    }
}
