use crate::context::BridgeContext;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ConvexMutationRequest {
    pub function_name: String,
    pub deployment_id: Option<String>,
    pub project_id: Option<String>,
    pub workspace_id: Option<String>,
    pub request_id: String,
    pub trace_id: String,
    pub idempotency_key: Option<String>,
    pub actor_id: String,
    pub payload_json: String,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ConvexQueryRequest {
    pub function_name: String,
    pub deployment_id: Option<String>,
    pub project_id: Option<String>,
    pub workspace_id: Option<String>,
    pub request_id: String,
    pub trace_id: String,
    pub actor_id: String,
    pub payload_json: String,
}

pub fn map_command_name_to_convex(command_name: &str) -> &'static str {
    match command_name {
        "create_workspace" => "workspaces:create",
        "create_page" => "pages:create",
        "kernel.node.create" => "kernel:createNode",
        "kernel.node.update" => "kernel:updateNode",
        "kernel.subtree.move" => "kernel:moveSubtree",
        "kernel.edge.attach" => "kernel:attachEdge",
        "kernel.edge.detach" => "kernel:detachEdge",
        "tree.node.create" => "documents:createWithParentReference",
        "tree.node.rename" => "documents:updateTitle",
        "tree.node.archive" => "documents:softDelete",
        "tree.node.restore" => "documents:restore",
        "tree.node.purge" => "documents:purge",
        "tree.subtree.move" => "documents:move",
        "tree.subtree.copy" => "documents:copyTree",
        "tree.node.embed" => "documents:updateContent",
        "documents.create" => "documents:createWithParentReference",
        "documents.move" => "documents:move",
        "documents.delete" => "documents:softDelete",
        "documents.restore" => "documents:restore",
        "documents.duplicate" => "documents:duplicateWithMindmaps",
        "documents.copy_tree" => "documents:copyTree",
        "documents.template" => "documents:setTemplate",
        "documents.emptyTrashByWorkspace" => "documents:emptyTrashByWorkspace",
        "documents.purge" => "documents:purge",
        "documents.embed" => "documents:updateContent",
        "blocks.patch" => "documents:updateContent",
        "documents.save" => "documents:updateContent",
        "page.body.save" => "documents:updateContent",
        "documents.title.update" => "documents:updateTitle",
        "page.head.updateTitle" => "documents:updateTitle",
        "documents.stats.update" => "documents:updateStats",
        "documents.options.update" => "documents:updateOptions",
        "page.layout.updateOptions" => "documents:updateOptions",
        "mindmaps.put" => "mindmaps:put",
        "mindmaps.delete" => "mindmaps:softDelete",
        "mindmaps.restore" => "mindmaps:restore",
        "mindmaps.purge" => "mindmaps:purge",
        "mindmaps.emptyTrashByWorkspace" => "mindmaps:emptyTrashByWorkspace",
        "insert_block" => "blocks:insert",
        "update_block" => "blocks:update",
        "move_block" => "blocks:move",
        "delete_block" => "blocks:delete",
        "blocks.move" => "blocks:move",
        "blocks.embed" => "blocks:insert",
        "media.assets.replace_storage" => "mediaAssets:replaceStorageFromUpload",
        _ => "commands:unknown",
    }
}

pub fn map_query_name_to_convex(query_name: &str) -> &'static str {
    match query_name {
        "kernel.node.get" => "kernel:getNode",
        "kernel.subtree.get" => "kernel:getSubtree",
        "kernel.children.list" => "kernel:listChildren",
        "kernel.edges.list" => "kernel:listEdges",
        "kernel.graph.traverse" => "kernel:traverseGraph",
        "kernel.project_view" => "kernel:projectView",
        "bridge.request.get" => "bridgeLogs:listByRequest",
        "bridge.trace.get" => "bridgeLogs:listByTrace",
        "bridge.command.get" => "bridgeLogs:listByCommand",
        "bridge.workspace.overview" => "bridgeLogs:listWorkspaceOverview",
        "documents.meta.get" => "documents:getMeta",
        "documents.content.get" => "documents:getContent",
        "mindmaps.get" => "mindmaps:get",
        "blocks.get" => "blocks:getById",
        "sidebar.dataset.list" => "sidebar:datasetList",
        "search.documents" => "search:documents",
        "search.recent" => "search:recent",
        "get_page" => "pages:get",
        "list_page_blocks" => "blocks:list_by_page",
        "search_pages" => "search:pages",
        "search_blocks" => "search:blocks",
        _ => "queries:unknown",
    }
}

fn json_opt(value: &Option<String>) -> String {
    match value {
        Some(v) => format!("\"{}\"", v),
        None => "null".into(),
    }
}

pub fn payload_json_for_command(context: &BridgeContext, command_name: &str) -> String {
    format!(
        "{{\"kind\":\"command\",\"name\":\"{}\",\"request_id\":\"{}\",\"trace_id\":\"{}\",\"deployment_id\":{},\"project_id\":{},\"workspace_id\":{},\"tenant_id\":{},\"idempotency_key\":{},\"actor\":{{\"type\":\"{}\",\"id\":\"{}\",\"session_id\":{}}},\"source\":{{\"channel\":\"{}\",\"client\":\"{}\"}}}}",
        command_name,
        context.request_id,
        context.trace_id,
        json_opt(&context.deployment_id),
        json_opt(&context.project_id),
        json_opt(&context.workspace_id),
        json_opt(&context.tenant_id),
        json_opt(&context.idempotency_key),
        context.actor_type,
        context.actor_id,
        json_opt(&context.session_id),
        context.source_channel,
        context.source_client,
    )
}

pub fn payload_json_for_query(context: &BridgeContext, query_name: &str) -> String {
    format!(
        "{{\"kind\":\"query\",\"name\":\"{}\",\"request_id\":\"{}\",\"trace_id\":\"{}\",\"deployment_id\":{},\"project_id\":{},\"workspace_id\":{},\"tenant_id\":{},\"actor_id\":\"{}\",\"source\":{{\"channel\":\"{}\",\"client\":\"{}\"}}}}",
        query_name,
        context.request_id,
        context.trace_id,
        json_opt(&context.deployment_id),
        json_opt(&context.project_id),
        json_opt(&context.workspace_id),
        json_opt(&context.tenant_id),
        context.actor_id,
        context.source_channel,
        context.source_client,
    )
}
