use std::io::{self, Read};

use anyhow::bail;

use crate::proto::{CliResponse, DockerCredential};
use super::{
    CliCredential,
    CliRequest,
    GlobalArgs
};


pub fn docker_store(global_args: GlobalArgs) -> anyhow::Result<()> {
    let input: DockerCredential = serde_json::from_reader(io::stdin())?;

    let req = CliRequest::StoreDockerCredential(input);

    match super::make_request(global_args.server_addr, &req)?? {
        CliResponse::Empty => Ok(()),
        r => bail!("Unexpected response from server: {r}"),
    }
}


pub fn docker_get(global_args: GlobalArgs) -> anyhow::Result<()> {
    let mut server_url = String::new();
    io::stdin().read_to_string(&mut server_url)?;
    let req = CliRequest::GetDockerCredential {
       server_url: server_url.trim().to_owned()
    };

    let server_resp = super::make_request(global_args.server_addr, &req)?;
    match server_resp {
        Ok(CliResponse::Credential(CliCredential::Docker(d))) => {
            println!("{}", serde_json::to_string(&d)?);
        },
        Err(e) if e.code == "NoCredentials" => {
            // To indicate credentials are not found, a credential helper *must* print
            // this message to stdout, then exit 1. Any other message/status will cause
            // some builds to fail. This is, of course, not documented anywhere.
            println!("credentials not found in native keychain");
            std::process::exit(1);
        },
        Err(e) => Err(e)?,
        Ok(r) => bail!("Unexpected response from server: {r}"),
    }
    Ok(())
}


pub fn docker_erase(global_args: GlobalArgs) -> anyhow::Result<()> {
    let mut server_url = String::new();
    io::stdin().read_to_string(&mut server_url)?;
    let req = CliRequest::EraseDockerCredential {
        server_url: server_url.trim().to_owned()
    };

    match super::make_request(global_args.server_addr, &req)?? {
        CliResponse::Empty => Ok(()),
        r => bail!("Unexpected response from server: {r}"),
    }
}