// src/config/storage/storage.rs
use serde::{Deserialize, Serialize};
use std::fs::{self, File};
use std::io::Write;
use std::path::PathBuf;
use anyhow::{Context, Result};
use tracing::{error, info};

#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;

pub const APP_NAME: &str = "komp_ac_client";
pub const TOKEN_FILE_NAME: &str = "auth.token";

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct StoredAuthData {
    pub access_token: String,
    pub user_id: String,
    pub role: String,
    pub username: String,
}

pub fn get_token_storage_path() -> Result<PathBuf> {
    let state_dir = dirs::state_dir()
        .or_else(|| dirs::home_dir().map(|home| home.join(".local").join("state")))
        .ok_or_else(|| anyhow::anyhow!("Could not determine state directory"))?;

    let app_state_dir = state_dir.join(APP_NAME);
    fs::create_dir_all(&app_state_dir)
        .with_context(|| format!("Failed to create app state directory at {:?}", app_state_dir))?;
    
    Ok(app_state_dir.join(TOKEN_FILE_NAME))
}

pub fn save_auth_data(data: &StoredAuthData) -> Result<()> {
    let path = get_token_storage_path()?;
    
    let json_data = serde_json::to_string(data)
        .context("Failed to serialize auth data")?;
    
    let mut file = File::create(&path)
        .with_context(|| format!("Failed to create token file at {:?}", path))?;
    
    file.write_all(json_data.as_bytes())
        .context("Failed to write token data to file")?;
    
    // Set file permissions to 600 (owner read/write only) on Unix
    #[cfg(unix)]
    {
        file.set_permissions(std::fs::Permissions::from_mode(0o600))
            .context("Failed to set token file permissions")?;
    }
    
    info!("Auth data saved to {:?}", path);
    Ok(())
}

pub fn load_auth_data() -> Result<Option<StoredAuthData>> {
    let path = get_token_storage_path()?;
    
    if !path.exists() {
        info!("Token file not found at {:?}", path);
        return Ok(None);
    }
    
    let json_data = fs::read_to_string(&path)
        .with_context(|| format!("Failed to read token file at {:?}", path))?;
    
    if json_data.trim().is_empty() {
        info!("Token file is empty at {:?}", path);
        return Ok(None);
    }
    
    match serde_json::from_str::<StoredAuthData>(&json_data) {
        Ok(data) => {
            info!("Auth data loaded from {:?}", path);
            Ok(Some(data))
        }
        Err(e) => {
            error!("Failed to deserialize token data from {:?}: {}. Deleting corrupt file.", path, e);
            if let Err(del_e) = fs::remove_file(&path) {
                error!("Failed to delete corrupt token file: {}", del_e);
            }
            Ok(None)
        }
    }
}

pub fn delete_auth_data() -> Result<()> {
    let path = get_token_storage_path()?;
    
    if path.exists() {
        fs::remove_file(&path)
            .with_context(|| format!("Failed to delete token file at {:?}", path))?;
        info!("Token file deleted from {:?}", path);
    } else {
        info!("Token file not found for deletion at {:?}", path);
    }
    
    Ok(())
}
