from flask import Flask, render_template, send_from_directory, request, render_template_string, jsonify, Response, jsonify
import os
import subprocess
import threading
import time
from werkzeug.middleware.proxy_fix import ProxyFix
import codecs
from flask import Response, request, send_file
import mimetypes

app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_port=1)
VIDEO_FOLDER = 'videos'
THUMBNAIL_FOLDER = 'thumbnails'
STATIC_FOLDER = 'static'

converting_files = set()

# Funkcja generująca miniaturki dla wideo
def generate_thumbnail(video_filename):
    thumbnail_path = os.path.join(THUMBNAIL_FOLDER, f"{video_filename}.jpg")
    if not os.path.exists(thumbnail_path):
        video_path = os.path.join(VIDEO_FOLDER, video_filename)
        subprocess.run([
            'ffmpeg', '-i', video_path,
            '-vf', 'thumbnail,scale=200:150',
            '-vframes', '1', thumbnail_path
        ])
    return thumbnail_path

@app.route('/')
def index():
    try:
        videos = sorted(
            [f for f in os.listdir(VIDEO_FOLDER) if f.lower().endswith(('.mp4', '.avi', '.mov', '.mkv'))],
            key=lambda x: os.path.getmtime(os.path.join(VIDEO_FOLDER, x)),
            reverse=True
        )
        thumbnails = {video: generate_thumbnail(video) for video in videos}
        return render_template('index.html', videos=videos, thumbnails=thumbnails)
    except Exception as e:
        return f"Wystąpił błąd: {str(e)}", 500

@app.route('/video')
def video_page():
    filename = request.args.get('id')
    timestamp = request.args.get('timestamp', 0)

    if not filename or not os.path.exists(os.path.join(VIDEO_FOLDER, filename)):
        return "Plik nie istnieje", 404

    with codecs.open(os.path.join("templates", "video.html"), "r", "utf-8") as f:
        return render_template_string(f.read(), filename=filename, timestamp=timestamp)



CHUNK_SIZE = 10 * 1024 * 1024  # 10 MB na fragment

def generate_video_stream(file_path, start_byte, end_byte):
    """Generator strumieniujący wideo w kawałkach"""
    with open(file_path, "rb") as f:
        f.seek(start_byte)
        remaining = end_byte - start_byte + 1
        while remaining > 0:
            chunk_size = min(CHUNK_SIZE, remaining)
            chunk = f.read(chunk_size)
            if not chunk:
                break
            yield chunk
            remaining -= chunk_size

@app.route('/videos/<filename>')
def serve_video(filename):
    file_path = os.path.join(VIDEO_FOLDER, filename)

    if not os.path.exists(file_path):
        return "Plik nie istnieje", 404

    file_size = os.path.getsize(file_path)
    mime_type, _ = mimetypes.guess_type(file_path)

    range_header = request.headers.get("Range")
    
    if range_header:
        try:
            byte1, byte2 = range_header.replace("bytes=", "").split("-")
            byte1 = int(byte1) if byte1 else 0
            byte2 = int(byte2) if byte2 else file_size - 1
            byte2 = min(byte2, file_size - 1)

            response = Response(generate_video_stream(file_path, byte1, byte2), 206,
                                mimetype=mime_type,
                                content_type=mime_type,
                                direct_passthrough=True)
            response.headers.add("Content-Range", f"bytes {byte1}-{byte2}/{file_size}")
            response.headers.add("Accept-Ranges", "bytes")
            response.headers.add("Content-Length", str(byte2 - byte1 + 1))
            return response

        except ValueError:
            return "Błędny zakres żądania", 400

    return Response(generate_video_stream(file_path, 0, file_size - 1),
                    mimetype=mime_type,
                    content_type=mime_type,
                    direct_passthrough=True)

@app.route('/thumbnails/<filename>')
def thumbnail(filename):
    return send_from_directory(THUMBNAIL_FOLDER, filename)

@app.route('/favicon.png')
def favicon():
    return send_from_directory(STATIC_FOLDER, 'favicon.png', mimetype='image/png')

@app.route('/oembed')
def oembed():
    video_id = request.args.get("id", "")
    timestamp = request.args.get("timestamp", "0")

    video_path = os.path.join(VIDEO_FOLDER, video_id)
    if not video_id or not os.path.exists(video_path):
        return jsonify({"error": "Plik nie istnieje"}), 404

    video_url = f"https://kongohouse.online/videos/{video_id}#t={timestamp}"
    thumbnail_url = f"https://kongohouse.online/thumbnails/{video_id}.jpg"

    data = {
        "type": "video",
        "version": "1.0",
        "title": f"Obejrzyj: {video_id}",
        "author_name": "Kongo House Archive",
        "provider_name": "Kongo House",
        "provider_url": "https://kongohouse.online",
        "thumbnail_url": thumbnail_url,
        "thumbnail_width": 1280,
        "thumbnail_height": 720,
        "html": f'''
            <iframe src="https://kongohouse.online/embed/{video_id}?timestamp={timestamp}" 
                    width="640" height="360" frameborder="0" allowfullscreen>
            </iframe>
        ''',
        "width": 640,
        "height": 360
    }

    return jsonify(data)



# 🔹 Endpoint dla osadzonego playera 🔹
@app.route('/embed/<filename>')
def embed_video(filename):
    timestamp = request.args.get("timestamp", "0")
    return render_template("embed.html", filename=filename, timestamp=timestamp)


# Funkcja konwertująca MKV na MP4
def convert_mkv_to_mp4(mkv_filename):
    try:
        base_name = os.path.splitext(mkv_filename)[0]
        mp4_filename = base_name + '.mp4'
        video_path = os.path.join(VIDEO_FOLDER, mkv_filename)
        mp4_path = os.path.join(VIDEO_FOLDER, mp4_filename)
        ffmpeg_cmd = [
            'ffmpeg', '-i', video_path, '-c:v', 'libx264',
            '-c:a', 'aac', '-strict', 'experimental', mp4_path
        ]
        subprocess.run(ffmpeg_cmd)
    finally:
        converting_files.discard(mkv_filename)

def monitor_videos():
    while True:
        try:
            files = os.listdir(VIDEO_FOLDER)
            for file in files:
                if file.lower().endswith('.mkv'):
                    base_name = os.path.splitext(file)[0]
                    mp4_filename = base_name + '.mp4'
                    mp4_path = os.path.join(VIDEO_FOLDER, mp4_filename)
                    mkv_path = os.path.join(VIDEO_FOLDER, file)
                    
                    if os.path.exists(mp4_path):
                        os.remove(mkv_path)
                        continue
                    
                    if file not in converting_files:
                        converting_files.add(file)
                        threading.Thread(target=convert_mkv_to_mp4, args=(file,), daemon=True).start()
        except Exception as e:
            print(f"Błąd w monitorze: {e}")
        time.sleep(10)

if __name__ == '__main__':
    context = ('/var/www/kongo/kongohouse.online.pem', '/var/www/kongo/kongohouse.online.key')
    app.run(host='0.0.0.0', port=443, ssl_context=context)
