use serde::{Deserialize, Serialize};

use crate::agent::SubmitTaskRequest;
use crate::pipe::ConversationMessage;

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ConfigUpdatePayload {
    #[serde(rename = "apiKey", default)]
    pub api_key: Option<String>,
    #[serde(rename = "baseUrl", default)]
    pub base_url: Option<String>,
    #[serde(default)]
    pub model: Option<String>,
    #[serde(rename = "skillsDir", default)]
    pub skills_dir: Option<String>,
    #[serde(rename = "directSubmitSkill", default)]
    pub direct_submit_skill: Option<String>,
    #[serde(rename = "runtimeProfile", default)]
    pub runtime_profile: Option<String>,
    #[serde(rename = "browserBackend", default)]
    pub browser_backend: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ClientMessage {
    Connect,
    Start,
    Stop,
    SubmitTask {
        instruction: String,
        #[serde(default)]
        conversation_id: String,
        #[serde(default)]
        messages: Vec<ConversationMessage>,
        #[serde(default)]
        page_url: String,
        #[serde(default)]
        page_title: String,
    },
    Ping,
    UpdateConfig {
        config: ConfigUpdatePayload,
    },
}

impl ClientMessage {
    pub fn into_submit_task_request(self) -> Option<SubmitTaskRequest> {
        match self {
            ClientMessage::SubmitTask {
                instruction,
                conversation_id,
                messages,
                page_url,
                page_title,
            } => Some(SubmitTaskRequest {
                instruction,
                conversation_id: normalize_optional_field(conversation_id),
                messages,
                page_url: normalize_optional_field(page_url),
                page_title: normalize_optional_field(page_title),
            }),
            ClientMessage::Connect
            | ClientMessage::Start
            | ClientMessage::Stop
            | ClientMessage::Ping
            | ClientMessage::UpdateConfig { .. } => None,
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ServiceMessage {
    StatusChanged { state: String },
    LogEntry { level: String, message: String },
    TaskComplete { success: bool, summary: String },
    Busy { message: String },
    Pong,
    ConfigUpdated {
        success: bool,
        message: String,
    },
}

fn normalize_optional_field(value: String) -> Option<String> {
    let trimmed = value.trim();
    (!trimmed.is_empty()).then(|| trimmed.to_string())
}
