import os
import subprocess
import sys
import time
import uuid

from fastapi import APIRouter, Depends, HTTPException, UploadFile, File
from loguru import logger

from pipecat.transports.services.helpers.daily_rest import (
    DailyRoomParams,
    DailyRoomProperties,
)

from app.auth import get_current_user
from app.config import LOG_DIR, LOG_FILE, ROOM_EXPIRY_SECONDS, BASE_DIR
from app.schemas.auth import CurrentUser
from app.schemas.bot import ConnectRequest, ConnectResponse, UploadImageResponse
from app.services.r2 import upload_bytes
from app.usage import get_usage_state

router = APIRouter()

# Bot sub-process dict for concurrency control
bot_procs = {}

# Daily REST helper (set during app startup)
daily_helpers = {}


@router.get("/health")
async def health_check():
    return {"status": "healthy"}


@router.post("/connect", response_model=ConnectResponse)
async def rtvi_connect(body: ConnectRequest, current_user: CurrentUser = Depends(get_current_user)):
    """RTVI connect endpoint that creates a room and returns connection credentials."""
    try:
        user_id = current_user.sub
        is_premium = current_user.premium
        plan = current_user.plan
        logger.info(f"=== Starting new connection request for user={user_id} ===")

        # Check usage limits based on persona before creating room
        persona_id = body.persona_id
        usage = get_usage_state(user_id)
        total_images = usage["plan_images_remaining"] + usage["topup_images_remaining"]
        total_videos = usage["plan_videos_remaining"] + usage["topup_videos_remaining"]
        total_ppts = usage["plan_ppts_remaining"]

        # Each persona checks only its relevant credits
        persona_limit_map = {
            "image_gen": total_images,
            "video_gen": total_videos,
            "video_ads": total_videos,
            "ppt_gen": total_ppts,
        }
        relevant_credits = persona_limit_map.get(persona_id, total_images)

        if relevant_credits <= 0:
            reason = "topup" if usage["is_premium"] else "subscribe"
            logger.info(f"LIMIT_BLOCKED: user={user_id} persona={persona_id} reason={reason} credits={relevant_credits}")
            raise HTTPException(
                status_code=403,
                detail={"limit_reached": True, "reason": reason},
            )

        daily_api_key = os.getenv("DAILY_API_KEY")
        if not daily_api_key:
            raise HTTPException(status_code=500, detail="DAILY_API_KEY environment variable is not set")

        # Create room
        try:
            room_properties = DailyRoomProperties(
                exp=time.time() + ROOM_EXPIRY_SECONDS,
                start_audio_off=False,
                start_video_off=True,
                eject_at_room_exp=True,
                enable_prejoin_ui=False,
            )
            room_params = DailyRoomParams(privacy="public", properties=room_properties)
            room = await daily_helpers["rest"].create_room(room_params)
            daily_room_url = room.url
            logger.info(f"Created room: {daily_room_url} with expiry in {ROOM_EXPIRY_SECONDS / 60} minutes")
        except Exception as e:
            logger.error(f"Failed to create room: {e}")
            raise HTTPException(status_code=500, detail=f"Failed to create room: {e}")

        # Get token
        try:
            token = await daily_helpers["rest"].get_token(daily_room_url)
        except Exception as e:
            logger.error(f"Failed to get room token: {e}")
            raise HTTPException(status_code=500, detail=f"Failed to generate room token: {e}")

        if not token:
            raise HTTPException(status_code=500, detail="Failed to generate room token - no token returned")

        # Start bot process
        session_id = str(uuid.uuid4())[:8]
        env = os.environ.copy()
        env["DAILY_ROOM_URL"] = daily_room_url
        env["DAILY_API_KEY"] = daily_api_key
        env["DAILY_ROOM_TOKEN"] = token
        env["SESSION_ID"] = session_id
        env["USER_ID"] = user_id
        env["IS_PREMIUM"] = str(is_premium)
        env["PLAN"] = plan
        env["PERSONA_ID"] = body.persona_id

        try:
            proc = subprocess.Popen(
                [sys.executable, "-m", "bot.core.main"],
                env=env,
                cwd=BASE_DIR,
                stdout=open(LOG_FILE, "a"),  # append so bot logs merge with server logs
                stderr=subprocess.DEVNULL,
            )
            bot_procs[proc.pid] = (proc, daily_room_url)
            logger.info(f"Bot process started with PID: {proc.pid}, session_id: {session_id}")
        except Exception as e:
            logger.error(f"Failed to start bot process: {e}")
            raise HTTPException(status_code=500, detail=f"Failed to start bot: {e}")

        return ConnectResponse(room_url=daily_room_url, token=token)

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Unexpected error in rtvi_connect: {e}")
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/upload_image", response_model=UploadImageResponse)
async def upload_image(file: UploadFile = File(...)):
    """Upload image to R2. Frontend calls this, then sends the URL to bot via sendClientMessage."""
    try:
        contents = await file.read()
        mime_type = file.content_type or "image/jpeg"
        ext = "jpg" if "jpeg" in mime_type else "png"
        timestamp = int(time.time())
        image_id = f"upload_{timestamp}_{uuid.uuid4().hex[:6]}"
        r2_key = f"uploads/{image_id}.{ext}"

        r2_url = upload_bytes(contents, r2_key, mime_type)
        logger.info(f"IMAGE_UPLOADED_VIA_HTTP: image_id={image_id} size={len(contents)} url={r2_url}")

        return UploadImageResponse(
            image_url=r2_url,
            image_id=image_id,
            mime_type=mime_type,
            size_bytes=len(contents),
        )
    except Exception as e:
        logger.error(f"Failed to upload image: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Upload failed: {e}")
