"""
MongoDB Command Mappings
Contains all command mappings and method translations for MongoDB operations
"""

DB_METHOD_MAPPING = {
    'stats': {'dbStats': 1},
    'hostInfo': {'hostInfo': 1},
    'serverStatus': {'serverStatus': 1},
    'currentOp': {'currentOp': 1},
    'dropDatabase': {'dropDatabase': 1},
    'getCollectionInfos': {'listCollections': 1},
    'listCollections': {'listCollections': 1},
    'adminCommand': None,
    'runCommand': None,
    'killOp': None,
    'createCollection': None,
    'getCollection': None
}

SHOW_MAPPING = {
    'dbs': {'listDatabases': 1},
    'databases': {'listDatabases': 1},
    'collections': {'listCollections': 1},
    'tables': {'listCollections': 1},
    'users': {'usersInfo': 1},
    'roles': {'rolesInfo': 1},
    'profile': {'profile': -1},
    'logs': {'getLog': 'global'}
}

RS_METHOD_MAPPING = {
    'conf': {'replSetGetConfig': 1},
    'config': {'replSetGetConfig': 1},
    'status': {'replSetGetStatus': 1},
    'initiate': {'replSetInitiate': {}},
    'add': None,
    'remove': None,
    'stepDown': {'replSetStepDown': 60},
    'freeze': None,
    'slaveOk': {'setSlaveOk': 1}
}

SH_METHOD_MAPPING = {
    'status': {'shardingState': 1},
    'help': {'help': 'sharding'},
    'enableSharding': None,
    'shardCollection': None,
    'getShardMap': {'getShardMap': 1},
    'isBalancerRunning': {'balancerStatus': 1},
    'disableBalancing': None,
    'enableBalancing': None,
    'startBalancer': {'balancerStart': 1},
    'stopBalancer': {'balancerStop': 1}
}

COLLECTION_METHOD_MAPPING = {
    'find': lambda collection_name, params: {
        "find": collection_name,
        "filter": params[0] if params else {}
    },
    'findOne': lambda collection_name, params: {
        "find": collection_name,
        "filter": params[0] if params else {},
        "limit": 1
    },
    'insertOne': lambda collection_name, params: {
        "insert": collection_name,
        "documents": params
    },
    'insertMany': lambda collection_name, params: {
        "insert": collection_name,
        "documents": params[0] if params and isinstance(params[0], list) else params
    },
    'insert': lambda collection_name, params: {
        "insert": collection_name,
        "documents": params[0] if params and isinstance(params[0], list) else params
    },
    'updateOne': lambda collection_name, params: {
        "update": collection_name,
        "updates": [{"q": params[0], "u": params[1], "multi": False}]
    },
    'updateMany': lambda collection_name, params: {
        "update": collection_name,
        "updates": [{"q": params[0], "u": params[1], "multi": True}]
    },
    'update': lambda collection_name, params: {
        "update": collection_name,
        "updates": [{"q": params[0], "u": params[1], "multi": True}]
    },
    'deleteOne': lambda collection_name, params: {
        "delete": collection_name,
        "deletes": [{"q": params[0] if params else {}, "limit": 1}]
    },
    'deleteMany': lambda collection_name, params: {
        "delete": collection_name,
        "deletes": [{"q": params[0] if params else {}, "limit": 0}]
    },
    'remove': lambda collection_name, params: {
        "delete": collection_name,
        "deletes": [{"q": params[0] if params else {}, "limit": 0}]
    },
    'count': lambda collection_name, params: {
        "count": collection_name,
        "query": params[0] if params else {}
    },
    'countDocuments': lambda collection_name, params: {
        "count": collection_name,
        "query": params[0] if params else {}
    },
    'createIndex': lambda collection_name, params: {
        "createIndexes": collection_name,
        "indexes": [{
            "key": params[0],
            "name": f"idx_{collection_name}_{hash(str(params[0]))}",
            **(params[1] if len(params) > 1 else {})
        }]
    },
    'ensureIndex': lambda collection_name, params: {
        "createIndexes": collection_name,
        "indexes": [{
            "key": params[0],
            "name": f"idx_{collection_name}_{hash(str(params[0]))}",
            **(params[1] if len(params) > 1 else {})
        }]
    },
    'dropIndex': lambda collection_name, params: {
        "dropIndexes": collection_name,
        "index": params[0] if params else {}
    },
    'getIndexes': lambda collection_name, params: {
        "listIndexes": collection_name
    },
    'listIndexes': lambda collection_name, params: {
        "listIndexes": collection_name
    },
    'watch': lambda collection_name, params: {
        "aggregate": collection_name,
        "pipeline": [{"$changeStream": {}}],
        "cursor": {}
    },
    'aggregate': lambda collection_name, params: {
        "aggregate": collection_name,
        "pipeline": params[0] if params and isinstance(params[0], list) else [],
        "cursor": params[1] if len(params) > 1 and isinstance(params[1], dict) else {}
    }
}

COMMAND_PROCESSORS = {
    'buildInfo': {
        'result_keys': ['version', 'gitVersion', 'buildEnvironment'],
        'processor': lambda result: [[
            result.get('version', ''),
            result.get('gitVersion', ''),
            str(result.get('buildEnvironment', {}))
        ]]
    },
    'serverStatus': {
        'result_keys': ['uptime', 'current_connections', 'available_connections'],
        'processor': lambda result: [[
            result.get('uptime', 0),
            result.get('connections', {}).get('current', 0),
            result.get('connections', {}).get('available', 0)
        ]]
    },
    'currentOp': {
        'result_keys': ['opid', 'active', 'operation', 'namespace'],
        'processor': lambda result: [
            [str(op.get('opid', '')), str(op.get('active', False)), op.get('op', ''), op.get('ns', '')]
            for op in [op for op in result.get('inprog', []) if op.get('active', False)][:10]
        ]
    },
    'connectionStatus': {
        'result_keys': ['user', 'database', 'roles'],
        'processor': lambda result: [
            [user.get('user', ''), user.get('db', ''), str(result.get('authInfo', {}).get('authenticatedUserRoles', []))]
            for user in result.get('authInfo', {}).get('authenticatedUsers', [])
        ] or [["No authenticated user information available", "", ""]]
    }
}