from fastapi import APIRouter, Depends, HTTPException
from api.common import api_response, api_abort
from api.command_helpers import enqueue_tx_command
from message_system_db_messages import DatabaseManagerMessages
from message_system_db_attachments import DatabaseManagerAttachments
from message_system_db_beacon import DatabaseManagerBeacon
from message_system_db_station import DatabaseManagerStations
import command_message_send
import adif_udp_logger
import wavelog_api_logger
from context import AppContext, get_ctx

router = APIRouter()


def _mgr_msgs(ctx: AppContext):
    return DatabaseManagerMessages(ctx)

def _mgr_attach(ctx: AppContext):
    return DatabaseManagerAttachments(ctx)

def _mgr_beacon(ctx: AppContext):
    return DatabaseManagerBeacon(ctx)

def _mgr_stations(ctx: AppContext):
    return DatabaseManagerStations(ctx)



@router.get("/messages/{message_id}", summary="Get Message by ID", tags=["FreeDATA"], responses={
    200: {"description": "Message found and returned."},
    404: {"description": "Message not found."}
})
async def get_freedata_message(
    message_id: str,
    ctx: AppContext = Depends(get_ctx)
):
    message = _mgr_msgs(ctx).get_message_by_id_json(message_id)
    if message is None:
        api_abort("Message not found", 404)
    return api_response(message)

@router.post("/messages", summary="Transmit Message", tags=["FreeDATA"], responses={
    200: {
        "description": "Message transmitted successfully.",
        "content": {
            "application/json": {
                "example": {
                    "destination": "XX1XXX-6",
                    "body": "Hello FreeDATA"
                }
            }
        }
    },
    404: {
        "description": "The requested resource was not found.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Resource not found."
                }
            }
        }
    }
})
async def post_freedata_message(
    payload: dict,
    ctx: AppContext = Depends(get_ctx)
):
    # Transmit FreeDATA message
    await enqueue_tx_command(ctx, command_message_send.SendMessageCommand, payload)
    return api_response(payload)

@router.post("/messages/{message_id}/adif", summary="Send Message ADIF Log", tags=["FreeDATA"], responses={
    200: {
        "description": "ADIF log sent successfully.",
        "content": {
            "application/json": {
                "example": {
                    "adif_output": "ADIF data..."
                }
            }
        }
    },
    400: {
        "description": "Bad Request: The request was malformed or missing required parameters.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Invalid message ID."
                }
            }
        }
    },
    404: {
        "description": "The requested resource was not found.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Message not found."
                }
            }
        }
    },
    503: {
        "description": "Modem not running.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Modem not running."
                }
            }
        }
    }
})
async def post_freedata_message_adif_log(
    message_id: str,
    ctx: AppContext = Depends(get_ctx)
):
    adif = _mgr_msgs(ctx).get_message_by_id_adif(message_id)
    if not adif:
        api_abort("Message not found or ADIF unavailable", 404)
    # send logs
    adif_udp_logger.send_adif_qso_data(ctx, adif)
    wavelog_api_logger.send_wavelog_qso_data(ctx, adif)
    return api_response({"adif_output": adif})

@router.patch("/messages/{message_id}", summary="Update Message by ID", tags=["FreeDATA"], responses={
    200: {
        "description": "Message updated successfully.",
        "content": {
            "application/json": {
                "example": {
                    "is_read": True
                }
            }
        }
    },
    400: {
        "description": "Bad Request: The request was malformed or missing required parameters.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Invalid parameters."
                }
            }
        }
    },
    404: {
        "description": "Message not found.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Message not found."
                }
            }
        }
    }
})
async def patch_freedata_message(
    message_id: str,
    payload: dict,
    ctx: AppContext = Depends(get_ctx)
):
    if payload.get("action") == "retransmit":
        _mgr_msgs(ctx).update_message(message_id, {'status':'queued'})
        _mgr_msgs(ctx).increment_message_attempts(message_id)
        result = {"message_id": message_id, "status": "queued"}
    else:
        result = _mgr_msgs(ctx).update_message(message_id, update_data=payload)
    if result is None:
        api_abort("Message not found", 404)
    return api_response(result)


@router.get("/messages", summary="Get All Messages", tags=["FreeDATA"], responses={
    200: {
        "description": "List of all messages.",
        "content": {
            "application/json": {
                "example": {
                    "total_messages": 1,
                    "messages": [
                        {
                            "id": "DXCALL-6_MYCALL-0_2024-04-12T20:39:05.302479",
                            "timestamp": "2024-04-12T20:39:05.302479",
                            "origin": "DXCALL-6",
                            "via": None,
                            "destination": "MYCALL-0",
                            "direction": "receive",
                            "body": "Hello !",
                            "attachments": [],
                            "status": "received",
                            "priority": 10,
                            "is_read": False,
                            "statistics": {
                                "total_bytes": 120,
                                "duration": 29.76698660850525,
                                "bytes_per_minute": 241,
                                "time_histogram": {
                                    "0": "2024-04-12T20:39:23.423169",
                                    "1": "2024-04-12T20:39:30.504638",
                                    "2": "2024-04-12T20:39:37.745075"
                                },
                                "snr_histogram": {
                                    "0": -6,
                                    "1": -6,
                                    "2": -6
                                },
                                "bpm_histogram": {
                                    "0": 198,
                                    "1": 265,
                                    "2": 252
                                }
                            }
                        }
                    ]
                }
            }
        }
    },
    404: {
        "description": "The requested resource was not found.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Resource not found."
                }
            }
        }
    }
})
async def get_freedata_messages(
    ctx: AppContext = Depends(get_ctx)
):
    filters = {k: v for k, v in ctx.config_manager.read().get('FILTERS', {}).items()}
    # use query params if needed
    # filters = dict(ctx.request.query_params)
    result = _mgr_msgs(ctx).get_all_messages_json(filters=filters)
    return api_response(result)




@router.delete("/messages/{message_id}", summary="Delete Message by ID", tags=["FreeDATA"], responses={
    200: {
        "description": "Message deleted successfully.",
        "content": {
            "application/json": {
                "example": {
                    "message": "DXCALL-0_MYCALL-5_2024-04-04T17:22:14.002502 deleted",
                    "status": "success"
                }
            }
        }
    },
    404: {
        "description": "Message not found.",
        "content": {
            "application/json": {
                "example": {
                    "message": "Message not found",
                    "status": "failure"
                }
            }
        }
    }
})
async def delete_freedata_message(
    message_id: str,
    ctx: AppContext = Depends(get_ctx)
):
    ok = _mgr_msgs(ctx).delete_message(message_id)
    if not ok:
        api_abort("Message not found", 404)
    return api_response({"message": f"{message_id} deleted", "status": "success"})

@router.get("/messages/{message_id}/attachments", summary="Get Attachments by Message ID", tags=["FreeDATA"], responses={
    200: {
        "description": "List of attachments for the specified message.",
        "content": {
            "application/json": {
                "example": {
                    "attachments": [
                        {
                            "id": "attachment1",
                            "filename": "file1.txt",
                            "file_size": 1024,
                            "file_type": "text/plain",
                            "data_sha512": "abcdef1234567890..."
                        },
                        {
                            "id": "attachment2",
                            "filename": "image.png",
                            "file_size": 2048,
                            "file_type": "image/png",
                            "data_sha512": "123456abcdef7890..."
                        }
                    ]
                }
            }
        }
    },
    404: {
        "description": "The requested resource was not found.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Resource not found."
                }
            }
        }
    },
    503: {
        "description": "Modem not running.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Modem not running."
                }
            }
        }
    }
})
async def get_message_attachments(
    message_id: str,
    ctx: AppContext = Depends(get_ctx)
):
    attachments = _mgr_attach(ctx).get_attachments_by_message_id_json(message_id)
    return api_response({"attachments": attachments})

@router.get("/messages/attachment/{data_sha512}", summary="Get Attachment by SHA512", tags=["FreeDATA"], responses={
    200: {
        "description": "Retrieve a specific attachment by its SHA512 hash.",
        "content": {
            "application/json": {
                "example": {
                    "id": "attachment1",
                    "filename": "file1.txt",
                    "file_size": 1024,
                    "file_type": "text/plain",
                    "data_sha512": "abcdef1234567890..."
                }
            }
        }
    },
    404: {
        "description": "The requested attachment was not found.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Attachment not found."
                }
            }
        }
    },
    503: {
        "description": "Modem not running.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Modem not running."
                }
            }
        }
    }
})
async def get_message_attachment(
    data_sha512: str,
    ctx: AppContext = Depends(get_ctx)
):
    attachment = _mgr_attach(ctx).get_attachment_by_sha512(data_sha512)
    if attachment is None:
        api_abort("Attachment not found", 404)
    return api_response(attachment)


@router.get("/beacons", summary="Get Received Beacons", tags=["FreeDATA"], responses={
    200: {
        "description": "List of received beacons.",
        "content": {
            "application/json": {
                "example": {
                    "total_beacons": 2,
                    "beacons": [
                        {
                            "id": "DXCALL-0_MYCALL-5_2024-04-04T17:22:14.002502",
                            "timestamp": "2024-04-04T17:22:14.002502",
                            "origin": "DXCALL-0",
                            "via": None,
                            "destination": "MYCALL-5",
                            "direction": "receive",
                            "body": "Hello FreeDATA",
                            "attachments": [],
                            "status": "received",
                            "priority": 10,
                            "is_read": False,
                            "statistics": {
                                "total_bytes": 120,
                                "duration": 29.77,
                                "bytes_per_minute": 241,
                                "time_histogram": {
                                    "0": "2024-04-04T17:22:23.423169",
                                    "1": "2024-04-04T17:22:30.504638",
                                    "2": "2024-04-04T17:22:37.745075"
                                },
                                "snr_histogram": {
                                    "0": -6,
                                    "1": -6,
                                    "2": -6
                                },
                                "bpm_histogram": {
                                    "0": 198,
                                    "1": 265,
                                    "2": 252
                                }
                            }
                        }
                    ]
                }
            }
        }
    },
    400: {
        "description": "Bad Request: The request was malformed or missing required parameters.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Invalid request."
                }
            }
        }
    },
    404: {
        "description": "The requested resource was not found.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Resource not found."
                }
            }
        }
    },
    500: {
        "description": "Internal Server Error: An unexpected error occurred on the server.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Internal server error."
                }
            }
        }
    },
    503: {
        "description": "Modem not running.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Modem not running."
                }
            }
        }
    }
})
async def get_all_beacons(
    ctx: AppContext = Depends(get_ctx)
):
    beacons = _mgr_beacon(ctx).get_all_beacons()
    return api_response(beacons)


@router.get("/beacons/{callsign}", summary="Get Beacon by Callsign", tags=["FreeDATA"], responses={
    200: {
        "description": "List of beacons from the specified callsign.",
        "content": {
            "application/json": {
                "example": {
                    "beacons": [
                        {
                            "id": "DXCALL-0_MYCALL-5_2024-04-04T17:22:14.002502",
                            "timestamp": "2024-04-04T17:22:14.002502",
                            "origin": "DXCALL-0",
                            "via": None,
                            "destination": "MYCALL-5",
                            "direction": "receive",
                            "body": "Hello FreeDATA",
                            "attachments": [],
                            "status": "received",
                            "priority": 10,
                            "is_read": False,
                            "statistics": {
                                "total_bytes": 120,
                                "duration": 29.77,
                                "bytes_per_minute": 241,
                                "time_histogram": {
                                    "0": "2024-04-04T17:22:23.423169",
                                    "1": "2024-04-04T17:22:30.504638",
                                    "2": "2024-04-04T17:22:37.745075"
                                },
                                "snr_histogram": {
                                    "0": -6,
                                    "1": -6,
                                    "2": -6
                                },
                                "bpm_histogram": {
                                    "0": 198,
                                    "1": 265,
                                    "2": 252
                                }
                            }
                        }
                    ]
                }
            }
        }
    },
    400: {
        "description": "Bad Request: The request was malformed or missing required parameters.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Invalid request."
                }
            }
        }
    },
    404: {
        "description": "The requested resource was not found.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Resource not found."
                }
            }
        }
    },
    500: {
        "description": "Internal Server Error: An unexpected error occurred on the server.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Internal server error."
                }
            }
        }
    },
    503: {
        "description": "Modem not running.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Modem not running."
                }
            }
        }
    }
})
async def get_beacons_by_callsign(
    callsign: str,
    ctx: AppContext = Depends(get_ctx)
):
    beacons = _mgr_beacon(ctx).get_beacons_by_callsign(callsign)
    return api_response(beacons)



@router.get("/station/{callsign}", summary="Get Station Info", tags=["FreeDATA"], responses={
    200: {
        "description": "Retrieve station information by callsign.",
        "content": {
            "application/json": {
                "example": {
                    "callsign": "MYCALL-0",
                    "location": "Springfield",
                    "frequency": "14093000",
                    "mode": "PKTUSB",
                    "status": "active",
                    "additional_info": "Station details here."
                }
            }
        }
    },
    400: {
        "description": "Bad Request: The request was malformed or missing required parameters.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Invalid callsign parameter."
                }
            }
        }
    },
    404: {
        "description": "The requested station was not found.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Station not found."
                }
            }
        }
    },
    500: {
        "description": "Internal Server Error: An unexpected error occurred on the server.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Internal server error."
                }
            }
        }
    },
    503: {
        "description": "Modem not running.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Modem not running."
                }
            }
        }
    }
})
async def get_station_info(
    callsign: str,
    ctx: AppContext = Depends(get_ctx)
):
    station = _mgr_stations(ctx).get_station(callsign)
    if station is None:
        api_abort("Station not found", 404)
    return api_response(station)

@router.post("/station/{callsign}", summary="Set Station Info", tags=["FreeDATA"], responses={
    200: {
        "description": "Station information updated successfully.",
        "content": {
            "application/json": {
                "example": {
                    "callsign": "MYCALL-0",
                    "location": "Springfield",
                    "frequency": "14093000",
                    "mode": "PKTUSB",
                    "status": "active",
                    "additional_info": "Updated station details."
                }
            }
        }
    },
    400: {
        "description": "Bad Request: The request was malformed or missing required parameters.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Invalid input data."
                }
            }
        }
    },
    404: {
        "description": "The requested station was not found.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Station not found."
                }
            }
        }
    },
    500: {
        "description": "Internal Server Error: An unexpected error occurred on the server.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Internal server error."
                }
            }
        }
    },
    503: {
        "description": "Modem not running.",
        "content": {
            "application/json": {
                "example": {
                    "error": "Modem not running."
                }
            }
        }
    }
})
async def set_station_info(
    callsign: str,
    payload: dict,
    ctx: AppContext = Depends(get_ctx)
):
    info = payload.get("info")
    if not isinstance(info, dict):
        api_abort("Invalid input data", 400)
    result = _mgr_stations(ctx).update_station_info(callsign, new_info=info)
    if result is None:
        api_abort("Station not found", 404)
    return api_response(result)
