use super::{paths as claude, slot};
use crate::context::Context;
use crate::host::{OS, Os};
use crate::service::Permit;
use crate::store::{Backend, Error, Live, RawStore, Unbuilt};
use std::path::{Path, PathBuf};
pub(crate) fn credential_file(ctx: &Context) -> PathBuf {
PathBuf::from(claude::storage_dir(ctx)).join(slot::CRED_FILE)
}
fn not_on_windows_yet() -> Unbuilt {
Unbuilt::new(
Backend::Unknown,
"Pitboard does not switch Claude Code on Windows yet",
)
}
pub(crate) fn chain(ctx: &Context) -> Live {
match OS {
Os::MacOs | Os::Linux => {
let host = ctx.host();
let mut backends: Vec<Box<dyn RawStore>> = Vec::new();
if let Some(keychain) = host.foreign_secrets(ctx, &slot::account_name(ctx)) {
backends.push(keychain);
}
backends.push(host.file(credential_file(ctx)));
Live::of(backends)
}
Os::Windows => Live::of(vec![Box::new(not_on_windows_yet())]),
}
}
pub(crate) fn read_signin(ctx: &Context, dir: &Path) -> Result<Option<String>, Error> {
match OS {
Os::MacOs | Os::Linux => {}
Os::Windows => return not_on_windows_yet().read(""),
}
match ctx.host().foreign_secrets(ctx, &slot::account_name(ctx)) {
Some(keychain) => keychain.read(&slot::service_for_dir(&dir.to_string_lossy())),
None => ctx.host().file(dir.join(slot::CRED_FILE)).read(""),
}
}
pub(crate) fn discard_signin(ctx: &Context, permit: Permit, dir: &Path) -> Result<(), Error> {
match OS {
Os::MacOs | Os::Linux => {}
Os::Windows => return not_on_windows_yet().delete(permit, ""),
}
let service = slot::service_for_dir(&dir.to_string_lossy());
if service == slot::LIVE_SERVICE || service == claude::live_service(ctx) {
return Err(Error::Write(format!("refusing to delete {service}")));
}
match ctx.host().foreign_secrets(ctx, &slot::account_name(ctx)) {
Some(keychain) => keychain.delete(permit, &service),
None => ctx
.host()
.file(dir.join(slot::CRED_FILE))
.delete(permit, ""),
}
}