use anyhow::Result;
use async_trait::async_trait;
use uuid::Uuid;

use super::panel_adapter::{DiscoveredServer, FileEntry, PanelAdapter, ServerStatus};

/// Companion Agent adapter.
///
/// Unlike AMP and Pterodactyl which use REST APIs, the Companion Agent
/// runs alongside the game server and communicates via NATS JetStream.
/// Commands are published to the agent's subject namespace and responses
/// are received on reply subjects. This enables direct server management
/// without a panel intermediary.
pub struct CompanionAdapter {
    pub nats: async_nats::Client,
    pub license_id: Uuid,
}

impl CompanionAdapter {
    pub fn new(nats: async_nats::Client, license_id: Uuid) -> Self {
        Self { nats, license_id }
    }
}

#[async_trait]
impl PanelAdapter for CompanionAdapter {
    async fn test_connection(&self) -> Result<bool> {
        // TODO: Publish heartbeat request to corrosion.{license_id}.agent.ping,
        // await reply within timeout
        todo!()
    }

    async fn discover_servers(&self) -> Result<Vec<DiscoveredServer>> {
        // TODO: Request server info from agent via NATS request/reply.
        // Companion manages exactly one server, so this returns a single-element vec.
        todo!()
    }

    async fn get_server_status(&self, _server_id: &str) -> Result<ServerStatus> {
        // TODO: NATS request to corrosion.{license_id}.agent.status
        todo!()
    }

    async fn start_server(&self, _server_id: &str) -> Result<()> {
        // TODO: NATS request to corrosion.{license_id}.agent.start
        todo!()
    }

    async fn stop_server(&self, _server_id: &str) -> Result<()> {
        // TODO: NATS request to corrosion.{license_id}.agent.stop
        todo!()
    }

    async fn restart_server(&self, _server_id: &str) -> Result<()> {
        // TODO: NATS request to corrosion.{license_id}.agent.restart
        todo!()
    }

    async fn send_command(&self, _server_id: &str, _command: &str) -> Result<String> {
        // TODO: NATS request to corrosion.{license_id}.agent.command
        // with command payload, await RCON response
        todo!()
    }

    async fn get_file(&self, _server_id: &str, _path: &str) -> Result<Vec<u8>> {
        // TODO: NATS request to corrosion.{license_id}.agent.file.get
        // Agent reads local file and returns contents
        todo!()
    }

    async fn put_file(&self, _server_id: &str, _path: &str, _data: &[u8]) -> Result<()> {
        // TODO: NATS publish to corrosion.{license_id}.agent.file.put
        // May need chunking for large files
        todo!()
    }

    async fn delete_file(&self, _server_id: &str, _path: &str) -> Result<()> {
        // TODO: NATS request to corrosion.{license_id}.agent.file.delete
        todo!()
    }

    async fn list_files(&self, _server_id: &str, _path: &str) -> Result<Vec<FileEntry>> {
        // TODO: NATS request to corrosion.{license_id}.agent.file.list
        todo!()
    }

    async fn trigger_steam_update(&self, _server_id: &str) -> Result<()> {
        // TODO: NATS request to corrosion.{license_id}.agent.update
        // Agent runs SteamCMD locally
        todo!()
    }
}
