from flask import Flask, render_template, request, jsonify
from flask_socketio import SocketIO, emit
from flask_cors import CORS
import requests
import uuid
import time

app = Flask(__name__)

app.config["SECRET_KEY"] = "sdf5asdwer6df3asdf3565asdf"

socketio = SocketIO(cors_allowed_origins="*")
socketio.init_app(app)
CORS(app)

JANUS_URL = "https://bindaslive.com:8089/janus"
JANUS_API_SECRET = "your-secret-key"
roomId = 1234
sessions = {}
publishers = {}

def janus_event(endpoint, data):
    headers = {"Content-Type": "application/json"}
    response = requests.post(f"{JANUS_URL}/{endpoint}", json=data, headers=headers)
    return response.json()

@app.route('/')
def index():
    return render_template('index.html')

# 1️⃣ Create Janus Session
@app.route('/create_session', methods=['POST'])
def create_session():
    data = {
        "janus": "create", 
        "transaction": str(uuid.uuid4())
    }
    session_data = janus_event("", data)
    if "data" in session_data:
        session_id = session_data['data']['id']
        sessions[session_id] = {}
        return jsonify(session_data)
    return jsonify({"error": "Failed to create session"}), 500

# 2️⃣ Attach VideoRoom Plugin
@app.route('/attach_plugin', methods=['POST'])
def attach_plugin():
    session_id = request.json['session_id']
    data = {
        "janus": "attach", 
        "plugin": "janus.plugin.videoroom", 
        "transaction": str(uuid.uuid4())
    }
    response = janus_event(f'{session_id}', data)
    return jsonify(response)

# 3️⃣ Join Video Room
@app.route('/join_room', methods=['POST'])
def join_room():
    
    session_id = request.json['session_id']
    handle_id = request.json['handle_id']
    user_id = request.json['user_id']
    
    data = {
        "janus": "message",
        "body": {
            "request": "join",
            "ptype": "publisher",
            "room": roomId,
            "display": user_id
        },
        "transaction": str(uuid.uuid4())
    }

   
    response = janus_event(f"{session_id}/{handle_id}", data)
    
    if response["janus"] == "ack":
        # poll event after ack
        event_response = requests.get(f'{JANUS_URL}/{session_id}/events')
        print(event_response, 'event-join')
            
        return jsonify(event_response.json())
    
    return jsonify({"error": "Join room config error!!"})




# 4️⃣ Publish Local Stream
@app.route('/publish_stream', methods=['POST'])
def publish_stream():
    session_id = request.json['session_id']
    handle_id = request.json['handle_id']
    jsep = request.json['jsep']

    request_body = {
        "janus": "message",
        "transaction": str(uuid.uuid4()),
        "body": {
            "request": "publish",
            "audio": True,
            "video": True
        },
        "jsep": jsep
    }

    response = janus_event(f"{session_id}/{handle_id}", request_body)
    return jsonify(response)

# 5️⃣ Subscribe to a Publisher
@app.route('/subscribe', methods=['POST'])
def subscribe():
    session_id = request.json['session_id']
    feed_id = request.json['feed_id']

    # Create a new handle for subscription
    data = {
        "janus": "attach", 
        "plugin": "janus.plugin.videoroom", 
        "transaction": str(uuid.uuid4())
    }
    handle_response = janus_event(f'{session_id}', data)

    if handle_response.get("janus") != "success":
        return jsonify({"error": "Failed to create subscriber handle"}), 500

    subscriber_handle_id = handle_response["data"]["id"]

    # Join as a subscriber
    request_body = {
        "janus": "message",
        "transaction": str(uuid.uuid4()),
        "body": {
            "request": "join",
            "ptype": "subscriber",
            "room": roomId,
            "feed": feed_id
        }
    }
    response = janus_event(f"{session_id}/{subscriber_handle_id}", request_body)

    if response.get("janus") == "success":
        jsep = response.get("jsep", {})
        return jsonify({"handle_id": subscriber_handle_id, "jsep": jsep})

    return jsonify({"error": "Failed to subscribe"}), 500

# 6️⃣ Handle ICE Candidates
@app.route('/send_ice_candidate', methods=['POST'])
def send_ice_candidate():
    data = request.json
    session_id = data['session_id']
    handle_id = data['handle_id']
    candidate = data['candidate']

    payload = {
        "janus": "trickle",
        "transaction": str(uuid.uuid4()),
        "candidate": candidate
    }

    response = janus_event(f"{session_id}/{handle_id}", payload)
    return jsonify(response)

@app.route('/get_ice_candidates', methods=['POST'])
def get_ice_candidates():
    data = request.json
    session_id = data.get('session_id')
    handle_id = data.get('handle_id')

    if not session_id or not handle_id:
        return jsonify({"error": "Missing session_id or handle_id"}), 400

    request_body = {
        "janus": "message",
        "transaction": str(uuid.uuid4()),
        "body": {
            "request": "trickle",
            "candidate": "completed"
        }
    }

    response = janus_event(f"{session_id}/{handle_id}", request_body)
    return jsonify(response)

# 7️⃣ Handle Answer (for subscribers)
@app.route('/send_answer', methods=['POST'])
def send_answer():
    data = request.json
    session_id = data['session_id']
    handle_id = data['handle_id']
    jsep = data['jsep']

    request_data = {
        "janus": "message",
        "transaction": str(uuid.uuid4()),
        "body": {
            "request": "start",
            "room": roomId
        },
        "jsep": jsep
    }

    response = janus_event(f"{session_id}/{handle_id}", request_data)
    return jsonify(response)

# 🔴 Socket.IO Handlers
@socketio.on("offer")
def on_offer(data):
    emit("offer", data, broadcast=True, include_self=False)

@socketio.on("answer")
def on_answer(data):
    emit("answer", data, broadcast=True, include_self=False)

@socketio.on("ice-candidate")
def on_ice_candidate(data):
    emit("ice-candidate", data, broadcast=True, include_self=False)

if __name__ == '__main__':
    socketio.run(app, debug=True, host="0.0.0.0", port=5656)
