/* bin/askpass.rs
 *
 * Copyright 2026 Christian Kruse
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */

use std::io::{BufRead, BufReader, Write};
use std::net::Shutdown;
use std::os::unix::net::UnixStream;
use std::process::ExitCode;

use gitte::askpass::ipc::{AskpassReply, AskpassRequest, SOCKET_ENV, TOKEN_ENV};

fn main() -> ExitCode {
    let prompt = std::env::args().nth(1).unwrap_or_default();
    eprintln!("gitte-askpass: invoked with prompt {prompt:?}");

    let Ok(socket) = std::env::var(SOCKET_ENV) else {
        eprintln!("gitte-askpass: {SOCKET_ENV} not set");
        return ExitCode::FAILURE;
    };

    let Ok(token) = std::env::var(TOKEN_ENV) else {
        eprintln!("gitte-askpass: {TOKEN_ENV} not set");
        return ExitCode::FAILURE;
    };

    eprintln!("gitte-askpass: connecting to {socket}");

    let mut stream = match UnixStream::connect(&socket) {
        Ok(s) => s,

        Err(e) => {
            eprintln!("gitte-askpass: connect {socket}: {e}");
            return ExitCode::FAILURE;
        }
    };

    let req = AskpassRequest { token, prompt };

    let mut buf = match serde_json::to_vec(&req) {
        Ok(b) => b,
        Err(_) => return ExitCode::FAILURE,
    };

    buf.push(b'\n');

    if stream.write_all(&buf).is_err() {
        return ExitCode::FAILURE;
    }

    let _ = stream.shutdown(Shutdown::Write);

    let mut reader = BufReader::new(stream);
    let mut line = String::new();

    if reader.read_line(&mut line).is_err() {
        return ExitCode::FAILURE;
    }

    match serde_json::from_str::<AskpassReply>(line.trim_end()) {
        Ok(AskpassReply::Ok { value }) => {
            let stdout = std::io::stdout();
            let mut out = stdout.lock();

            if out.write_all(value.as_bytes()).is_err() {
                return ExitCode::FAILURE;
            }

            let _ = out.write_all(b"\n");

            ExitCode::SUCCESS
        }

        _ => ExitCode::FAILURE,
    }
}
