import json
import os
import re

import boto3
import requests

MEDIACONVERT_DEST_BUCKET = "suno-media-dest"

def get_s3_bucket_and_key(output_path):
    # Parse S3 URI to get bucket and key
    parts = output_path.replace("s3://", "").split("/", 1)
    bucket = parts[0]
    key = parts[1]

    return bucket, key


def get_callback_auth_token(environment):
    secret_arn = os.environ[f"{environment.upper()}_SECRET_ARN"]
    secrets_client = boto3.client("secretsmanager")
    response = secrets_client.get_secret_value(SecretId=secret_arn)
    print(f"got response {response}")
    return response["SecretString"]


def handler(event, context):
    print(f"event is {event}")

    callback_payload = {
        "status": "finished_media_convert",
        "request_id": event["id"],
        "id": event["id"],
        "type": "upload_video",
        "ok": 1,
    }
    # Handle Error Events
    if event["detail"]["status"] != "COMPLETE":
        print(f"MediaConvert job failed with status {event['detail']}")
        callback_payload["ok"] = 0
        callback_payload["error"] = event["detail"]["errorMessage"]

    # Handle empty outputs
    output_group = event["detail"]["outputGroupDetails"]
    output_group_item_count = len(output_group)
    if not output_group_item_count:
        print(
            f"Unexpectedly got 0 items in MediaConvert output group, id {event['id']}"
        )
        callback_payload["ok"] = 0
        callback_payload["error"] = (
            "Unexpectedly got 0 items in MediaConvert output group"
        )

    clip_id = event["detail"]["userMetadata"].get("clip-id", None)
    environment = event["detail"]["userMetadata"].get("environment", "staging")
    callback_url = event["detail"]["userMetadata"].get("callback-url", None)
    skip_callback = (
        event["detail"]["userMetadata"].get("skip-callback", "false").lower() == "true"
    )
    print(f"got clip id {clip_id} and skip_callback {skip_callback}")

    request_id = None
    output_sizes = []
    for output_details in output_group[0]["outputDetails"]:
        output_path = output_details["outputFilePaths"][0]
        match = re.search(
            r"/([^/]+)_(\d+)p\.m3u8$", output_path
        )  # e.g. 856479-uhd_4096_2160_25fps and 1080 from s3://suno-media-dest/85/64/856479-uhd_4096_2160_25fps_1080p.m3u8
        if not match:
            print(f"Unexpected output path format: {output_path}")
            callback_payload["ok"] = 0
            callback_payload["error"] = f"Unexpected output path format: {output_path}"
            break
        request_id = match.group(1)
        output_sizes.append(int(match.group(2)))

    if callback_payload["ok"]:
        callback_payload = {
            "status": "finished_media_convert",
            "request_id": request_id,
            "id": request_id,
            "type": "upload_video",
            "ok": 1,
            "video_cover_clip_id": clip_id,
            "video_streaming_sizes": output_sizes,
        }

    # Send callback to studio_api
    # callback_url = (
    #     f"https://studio-api.{environment}.suno.com/api/uploads/webhook/finish"
    # )
    if skip_callback:
        print(f"Skipping callback for hook {request_id} because skip_callback is True")
        return
    if not callback_url:
        raise ValueError("callback_url is required, or specify skip_callback")

    callback_auth_token = get_callback_auth_token(environment)
    try:
        response = requests.post(
            callback_url,
            json=callback_payload,
            headers={
                "Content-Type": "application/json",
                "Authentication": f"Bearer {callback_auth_token}",
            },
        )
        response.raise_for_status()
        print(f"Callback sent successfully: {response.status_code}")
        print(f"Callback payload: {json.dumps(callback_payload)}")
    except Exception as e:
        print(f"Error sending callback: {str(e)}")
        print(f"Callback payload was: {json.dumps(callback_payload)}")
        # Raise an exception here to fail the Lambda execution
        raise e

    return
