from pyramid.view import view_config
from pyramid.httpexceptions import HTTPFound, HTTPNotFound, HTTPForbidden, HTTPBadRequest
import random

from . import get_referer_or_home

from ..models.product import get_media_type, get_products_from_a_shop, Product


@view_config(route_name="player", renderer="player.j2")
def player(request):
    """Pop-out media player for video, audio, and images."""

    # Check if feature is enabled
    if not request.popout_player_enabled:
        return HTTPNotFound()

    product = request.product

    if not product:
        return HTTPNotFound()

    # Only allow public products (visibility == 1)
    if product.visibility != 1:
        return HTTPForbidden("This content is not publicly available")

    # Determine which file to use
    if product.is_sellable:
        # For products (sellable), use preview file
        file_key = "preview"
        if file_key not in product.extensions:
            return HTTPForbidden("No preview available for this product")
    else:
        # For content (not sellable), use product file
        file_key = "product"
        if file_key not in product.extensions:
            return HTTPNotFound("No media file available")

    # Get extension and detect media type
    extension = product.extensions.get(file_key)
    media_type = get_media_type(extension)

    if not media_type:
        return HTTPBadRequest("Not a supported media file")

    # Generate presigned URL
    bucket_name = request.shop_bucket_name
    s3_key = f"{product.s3_path}/{file_key}"

    params = {
        "Bucket": bucket_name,
        "Key": s3_key,
    }

    # Set content disposition for inline display
    content_disposition = f'inline; filename="{product.title}.{extension}"'
    content_type = product.get_content_type(file_key)

    if content_disposition:
        params["ResponseContentDisposition"] = content_disposition

    if content_type:
        params["ResponseContentType"] = content_type

    presigned_url = request.shop_uploads_client.generate_presigned_url(
        ClientMethod="get_object",
        Params=params,
        ExpiresIn=900,  # 15 minutes
    )

    # Query shop products for navigation
    # Get all public products from the same shop
    shop_products = get_products_from_a_shop(product.shop, visibility=1)

    # Filter to only media items with valid file for this file_key
    media_products = []
    for p in shop_products:
        # Check if product has the appropriate file
        if product.is_sellable:
            # For sellable products, check for preview file
            if "preview" in p.extensions:
                ext = p.extensions.get("preview")
                if get_media_type(ext):
                    media_products.append(p)
        else:
            # For content, check for product file
            if "product" in p.extensions:
                ext = p.extensions.get("product")
                if get_media_type(ext):
                    media_products.append(p)

    # Find current product index
    current_index = None
    for i, p in enumerate(media_products):
        if p.id == product.id:
            current_index = i
            break

    # Get next/prev product IDs
    prev_product_id = None
    next_product_id = None

    if current_index is not None:
        if current_index > 0:
            prev_product_id = str(media_products[current_index - 1].id)
        if current_index < len(media_products) - 1:
            next_product_id = str(media_products[current_index + 1].id)

    # Get product URLs for navigation
    product_url = product.absolute_url(request)
    prev_product_url = None
    next_product_url = None

    if prev_product_id and current_index is not None and current_index > 0:
        prev_product_url = media_products[current_index - 1].absolute_url(request)

    if next_product_id and current_index is not None and current_index < len(media_products) - 1:
        next_product_url = media_products[current_index + 1].absolute_url(request)

    # Generate presigned URLs for isolated tracks if available
    instrumentals_url = None
    vocals_url = None
    if media_type in ("video", "audio"):
        for track_name, attr in (("instrumentals", "instrumentals_url"), ("vocals", "vocals_url")):
            if track_name in product.extensions:
                track_ext = product.extensions.get(track_name)
                track_ct = product.get_content_type(track_name) or (
                    "video/mp4" if media_type == "video" else "audio/wav"
                )
                url = request.shop_uploads_client.generate_presigned_url(
                    ClientMethod="get_object",
                    Params={
                        "Bucket": bucket_name,
                        "Key": f"{product.s3_path}/{track_name}",
                        "ResponseContentDisposition": f'inline; filename="{product.title} ({track_name.title()}).{track_ext}"',
                        "ResponseContentType": track_ct,
                    },
                    ExpiresIn=900,
                )
                if track_name == "instrumentals":
                    instrumentals_url = url
                else:
                    vocals_url = url

    return {
        "product": product,
        "presigned_url": presigned_url,
        "media_type": media_type,
        "extension": extension,
        "prev_product_id": prev_product_id,
        "next_product_id": next_product_id,
        "product_url": product_url,
        "prev_product_url": prev_product_url,
        "next_product_url": next_product_url,
        "instrumentals_url": instrumentals_url,
        "vocals_url": vocals_url,
    }


@view_config(route_name="player_json", renderer="json")
def player_json(request):
    """JSON API endpoint for video data - used by Document PiP."""

    # Check if feature is enabled
    if not request.popout_player_enabled:
        return {"error": "Feature not enabled"}

    product = request.product

    if not product:
        return {"error": "Product not found"}

    # Only allow public products (visibility == 1)
    if product.visibility != 1:
        return {"error": "Not publicly available"}

    # Determine which file to use
    if product.is_sellable:
        file_key = "preview"
        if file_key not in product.extensions:
            return {"error": "No preview available"}
    else:
        file_key = "product"
        if file_key not in product.extensions:
            return {"error": "No media file available"}

    # Get extension and detect media type
    extension = product.extensions.get(file_key)
    media_type = get_media_type(extension)

    if not media_type:
        return {"error": "Not a supported media file"}

    # Generate presigned URL
    bucket_name = request.shop_bucket_name
    s3_key = f"{product.s3_path}/{file_key}"

    params = {
        "Bucket": bucket_name,
        "Key": s3_key,
    }

    content_disposition = f'inline; filename="{product.title}.{extension}"'
    content_type = product.get_content_type(file_key)

    if content_disposition:
        params["ResponseContentDisposition"] = content_disposition

    if content_type:
        params["ResponseContentType"] = content_type

    presigned_url = request.shop_uploads_client.generate_presigned_url(
        ClientMethod="get_object",
        Params=params,
        ExpiresIn=900,
    )

    # Query shop products for navigation
    shop_products = get_products_from_a_shop(product.shop, visibility=1)

    # Filter to only media items
    media_products = []
    for p in shop_products:
        if product.is_sellable:
            if "preview" in p.extensions:
                ext = p.extensions.get("preview")
                if get_media_type(ext):
                    media_products.append(p)
        else:
            if "product" in p.extensions:
                ext = p.extensions.get("product")
                if get_media_type(ext):
                    media_products.append(p)

    # Find current product index
    current_index = None
    for i, p in enumerate(media_products):
        if p.id == product.id:
            current_index = i
            break

    # Get next/prev product IDs
    prev_product_id = None
    next_product_id = None

    if current_index is not None:
        if current_index > 0:
            prev_product_id = str(media_products[current_index - 1].id)
        if current_index < len(media_products) - 1:
            next_product_id = str(media_products[current_index + 1].id)

    # Generate presigned URLs for isolated tracks if available
    instrumentals_url = None
    vocals_url = None
    if media_type in ("video", "audio"):
        for track_name in ("instrumentals", "vocals"):
            if track_name in product.extensions:
                track_ext = product.extensions.get(track_name)
                track_ct = product.get_content_type(track_name) or (
                    "video/mp4" if media_type == "video" else "audio/wav"
                )
                url = request.shop_uploads_client.generate_presigned_url(
                    ClientMethod="get_object",
                    Params={
                        "Bucket": bucket_name,
                        "Key": f"{product.s3_path}/{track_name}",
                        "ResponseContentDisposition": f'inline; filename="{product.title} ({track_name.title()}).{track_ext}"',
                        "ResponseContentType": track_ct,
                    },
                    ExpiresIn=900,
                )
                if track_name == "instrumentals":
                    instrumentals_url = url
                else:
                    vocals_url = url

    return {
        "success": True,
        "videoUrl": presigned_url,
        "mediaType": media_type,
        "title": product.title,
        "productId": str(product.id),
        "prevProductId": prev_product_id,
        "nextProductId": next_product_id,
        "instrumentalsUrl": instrumentals_url,
        "vocalsUrl": vocals_url,
    }


@view_config(route_name="random")
def random_product(request):
    """Redirect to a random public product or content page."""
    shop = request.shop
    if not shop:
        return HTTPNotFound()

    products = list(get_products_from_a_shop(shop, visibility=1))
    if not products:
        return HTTPNotFound("No public items available")

    chosen = random.choice(products)
    p_or_c = "p" if chosen.is_sellable else "c"
    return HTTPFound(location=f"/{p_or_c}/{chosen.id}/{chosen.slug}")


@view_config(route_name="tv", renderer="tv.j2")
def tv_mode(request):
    """Full-screen TV mode that autoplays media in sequence."""

    # Check if feature is enabled
    if not request.popout_player_enabled:
        return HTTPNotFound()

    # Get current shop
    shop = request.shop
    if not shop:
        return HTTPNotFound()

    # Query all public products from the shop
    shop_products = get_products_from_a_shop(shop, visibility=1)

    # Filter to only media items with preview or product files
    media_products = []
    for p in shop_products:
        # Check for preview or product file with media type
        has_media = False
        if "preview" in p.extensions:
            ext = p.extensions.get("preview")
            if get_media_type(ext):
                has_media = True
        elif "product" in p.extensions:
            ext = p.extensions.get("product")
            if get_media_type(ext):
                has_media = True

        if has_media:
            media_products.append(p)

    if not media_products:
        return HTTPNotFound("No media available for TV mode")

    # Pick a random starting product
    random_product = random.choice(media_products)

    return {
        "shop": shop,
        "start_product_id": str(random_product.id),
    }
