import json
import modal
import logging
import tempfile
import os
from suno_utils.worker.schema import QueueItem
import subprocess
import boto3
import requests


s3_client = boto3.client(
    "s3",
    aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
    aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"),
)


HOOT_BUCKET_NAME = "suno-data-uploads"
HOOT_FOLDER_NAME = "studio/uploads"
AUDIO_BUCKET_NAME = "suno-data-uploads"
AUDIO_FOLDER_NAME = "studio/uploads"


logger = logging.getLogger(__name__)
logging.basicConfig()
logger.setLevel(logging.INFO)

############## CHANGE THESE ##############
DEPLOYMENT_TYPE = "dev"

##########################################
aws_secret = modal.Secret.from_name("studio-aws")
SECRETS = [
    aws_secret,
    modal.Secret.from_name("openai-secret"),
    modal.Secret.from_name("api-callback-token"),
]

PYTHON_VERSION = "3.11"


def get_modal_base_image():
    return (
        modal.Image.from_registry("ubuntu:22.04", add_python="3.11")
        .apt_install(
            "curl",
            "git",
            "ffmpeg",
            "fonts-freefont-ttf",
            "build-essential",
            # 🧩 Critical Chrome dependencies:
            "ca-certificates",
            "fonts-liberation",
            "libappindicator3-1",
            "libasound2",
            "libatk-bridge2.0-0",
            "libatk1.0-0",
            "libc6",
            "libcairo2",
            "libcups2",
            "libdbus-1-3",
            "libexpat1",
            "libfontconfig1",
            "libgcc1",
            "libglib2.0-0",
            "libgtk-3-0",
            "libnspr4",
            "libnss3",
            "libpango-1.0-0",
            "libu2f-udev",
            "libv4l-0",
            "libx11-6",
            "libxcomposite1",
            "libxdamage1",
            "libxrandr2",
            "xdg-utils",
            "wget",
        )
        .run_commands(
            # Install Node.js
            "curl -fsSL https://deb.nodesource.com/setup_18.x | bash -",
            "apt-get install -y nodejs",
        )
        .pip_install(
            "openai",
            "modal",
            "boto3",
            "requests",
            # other Python deps
        )
    )


def clone_remotion_repo():
    git_token = os.environ["GITHUB_TOKEN"]
    clone_url = f"https://{git_token}@github.com/suno-ai/video-gen.git"
    subprocess.run(["git", "clone", "--depth=1", clone_url, "/remotion-project"], check=True)
    subprocess.run(["npm", "install"], cwd="/remotion-project", check=True)
    subprocess.run(["ls", "-l"], cwd="/remotion-project", check=True)


image = (
    get_modal_base_image()
    .add_local_python_source("suno_utils", copy=True)
    .run_function(clone_remotion_repo, secrets=[modal.Secret.from_name("victor-modal-github-token")])
)

app = modal.App(
    "remotion-video-render",
    image=image,
    secrets=[
        modal.Secret.from_name("openai-secret", required_keys=["OPENAI_API_KEY"]),
    ],
)


@app.cls(
    cpu=10,
    secrets=SECRETS,
    timeout=4000,
    scaledown_window=1200,
    retries=modal.Retries(
        max_retries=2,
        backoff_coefficient=2.0,
        initial_delay=5.0,
    ),
    memory=250000,
    min_containers=2,
)
@modal.concurrent(max_inputs=60)
class VideoRenderStub:
    def __init__(self):
        pass

    @modal.method()
    def generate_video_from_script(
        self,
        queue_item_json: str,
    ):
        queue_item = QueueItem.parse_raw(queue_item_json)
        video_id = queue_item.id
        with tempfile.TemporaryDirectory() as temp_dir:
            output_path = os.path.join(temp_dir, f"clip-{video_id}.mp4")
            props_path = os.path.join(temp_dir, f"scene_{video_id}.json")
            try:
                # Write props to a temporary JSON file to avoid escaping issues
                # download props json from s3
                # download video from cdn
                response = requests.get(f"https://cdn1.suno.ai/scene_{video_id}.json")
                props_data = json.loads(response.content.decode("utf-8"))
                # Write the downloaded content to props_path
                with open(props_path, "w", encoding="utf-8") as f:
                    json.dump(props_data, f, ensure_ascii=False)

                result = subprocess.run(
                    [
                        "npx",
                        "remotion",
                        "render",
                        "test",
                        output_path,
                        "--props",
                        props_path,
                        "--bundle-cache",
                        "false",
                        "--concurrency",
                        "6",
                        "--ffg-output-args",
                        "-movflags +faststart",
                    ],
                    cwd="/remotion-project",
                    capture_output=True,
                    text=True,
                )

                # 🧩 Add this for full visibility!
                print("========== REMOTION STDOUT ==========")
                print(result.stdout)

                print("========== REMOTION STDERR ==========")
                print(result.stderr)

                if result.returncode != 0:
                    raise RuntimeError(f"Remotion render failed with exit code {result.returncode}")
                s3_client.upload_file(
                    output_path,
                    "suno-data-uploads",
                    props_data["video_s3_url"],
                    ExtraArgs={
                        "ContentType": "video/mp4",
                        "ContentDisposition": "inline",
                    },
                )
                # Remove the props JSON file after successful processing
                if os.path.exists(props_path):
                    os.remove(props_path)
                if os.path.exists(output_path):
                    os.remove(output_path)

                queue_item.notify_progress(
                    {
                        "id": video_id,
                        "video_id": props_data["video_id"],
                        "video_url": props_data["video_output_url"],
                        "status": "success",
                        "message": "Video generation completed",
                    }
                )
            except subprocess.CalledProcessError as e:
                logger.error(f"Error rendering scene {video_id}:\n{e.stderr}")
                queue_item.notify_progress(
                    {
                        "id": video_id,
                        "video_id": props_data["video_id"],
                        "video_url": props_data["video_output_url"],
                        "status": "failed",
                        "message": f"Video generation completed: {e.stderr}",
                    }
                )
                raise

            return output_path


@app.local_entrypoint()
def main() -> None:
    app = VideoRenderStub()
