import base64
import logging
import json
import boto3
from datetime import datetime, timezone

HOOKS_PLAY_DURATION_NAME = "HooksPlayDuration"

# Android events are currently lowerCamelCase and iOS events are UpperCamelCase.
# TODO - Shorten list once we standardize the action names.
HOOK_EVENT_ACTION_NAME_ALLOWLIST = [
    "PlayNewHook",
    "playNewHook",
    "PlayHook",
    "playHook",
    "PauseHook",
    "pauseHook",
    "AutoRepeatPlaySameHook",
    "autoRepeatPlaySameHook",
    "ScrollUpPauseHook",
    "scrollUpPauseHook",
    "ScrollDownPauseHook",
    "scrollDownPauseHook",
    "ScrollUpPlayNewHook",
    "scrollUpPlayNewHook",
    "ScrollDownPlayNewHook",
    "scrollDownPlayNewHook",
    "OpenOmniPlayerPauseHook",
    "openOmniPlayerPauseHook",
    "CloseOmniPlayerPlayHook",
    "closeOmniPlayerPlayHook",
    "OpenDeeplinkPlayNewHook",
    "OpenDeeplinkPauseHook",
    "OpenNotificationPlayNewHook",
    "OpenNotificationPauseHook",
    "TapSongPillPauseHook",
    "TapSongPillPlayNewSong",
    "CloseOmniPlayerPauseSong",
    "TapCreateHookPauseHook",
    "CloseCreateHookPlayHook",
    "TapTabPlayHook",
    "TapTabPauseHook",
    "TapCreateSongPauseHook",
    "CloseCreateSongPlayHook",
    "TapBackPlayHook",
    "TapBackPauseHook",
    "TapProfilePauseHook",
    "ForegroundAppPlayHook",
    "BackgroundAppPauseHook",
    "CloseCoverPlayHook",
    "TapExtendPauseHook",
    "CloseExtendPlayHook",
    "TapCoverPauseHook",
]

RECS_EVENTS_KINESIS_CLIENT = boto3.client(
    "kinesis",
    region_name="us-east-2",
)

logger = logging.getLogger(__name__)


def lambda_handler(event, context):
    """
    Lambda handler to check if an event name is in hook_events list and log to RECS_EVENTS_KINESIS stream
    """
    try:
        if "Records" not in event:
            return
        for record in event["Records"]:
            process_record(record)

        return {"statusCode": 200, "body": json.dumps("Success")}
    except Exception as e:
        print(f"Error in lambda_handler: {str(e)}")
        return {"statusCode": 500, "body": json.dumps(f"Error: {str(e)}")}


def process_record(record):
    """
    Process a single record and check if it should be logged to RECS_EVENTS_KINESIS
    Unlike the web hook events, all mobile events have the event name 'App-Event', so we can't filter out there.
    We can just filter out events if they have a hook ID.
    """

    if "kinesis" not in record:
        return
    kinesis = record["kinesis"]
    if "data" not in kinesis:
        return

    payload = base64.b64decode(record["kinesis"]["data"])
    payload_as_json = json.loads(payload)

    request_body = payload_as_json.get("request_body", "")
    if not request_body:
        return

    decoded_request_body = json.loads(base64.b64decode(request_body))

    properties = decoded_request_body.get("properties", {})
    if not properties:
        return

    action_name = properties.get("actionName", "")
    if action_name not in HOOK_EVENT_ACTION_NAME_ALLOWLIST:
        return

    event_context = properties.get("context", {})

    if not event_context:
        return

    # Whether event_context is a string or a dict depends
    # on how the client serialized the payload, so we need to
    # handle both cases.
    if isinstance(event_context, str):
        event_context_json = json.loads(event_context)
    else:
        event_context_json = event_context

    hook_id = properties.get("elementId", "")
    if not hook_id:
        return
    user_id = properties.get("userId", "")
    if not user_id:
        return

    recs_event = {}
    recs_event["name"] = HOOKS_PLAY_DURATION_NAME
    recs_event["source"] = "mobile"
    recs_event["user_id"] = user_id
    recs_event["timestamp"] = str(datetime.now(timezone.utc).isoformat())
    play_duration = event_context_json.get("playDuration", 0)
    if play_duration == 0:
        return

    recs_event["properties"] = {
        "hook_id": hook_id,
        "hook_play_duration": play_duration,
    }

    logger.info(f"Logging hook play duration event: {recs_event}")
    print(f"Logging hook play duration event: {recs_event}")

    RECS_EVENTS_KINESIS_CLIENT.put_record(
        StreamName="rec-events-stream",
        Data=json.dumps(recs_event),
        PartitionKey=str(datetime.now(timezone.utc).isoformat()),
    )
