from flask import Flask, send_from_directory, request, Response
import os
import mimetypes
import re

app = Flask(__name__)

MEDIA_DIR = '/home/redjifox/obs'

def parse_range_header(range_header, file_size):
    """Правильный парсинг Range заголовка"""
    if not range_header or not range_header.startswith('bytes='):
        return None, None, file_size
    
    try:
        # Формат: bytes=start-end
        range_str = range_header[6:]
        if '-' not in range_str:
            return None, None, file_size
        
        start_str, end_str = range_str.split('-', 1)
        
        if start_str:
            start = int(start_str)
        else:
            start = 0
            
        if end_str:
            end = int(end_str)
        else:
            end = file_size - 1
            
        # Проверяем границы
        if start >= file_size:
            return None, None, file_size
        if end >= file_size:
            end = file_size - 1
            
        length = end - start + 1
        return start, end, length
        
    except (ValueError, AttributeError):
        return None, None, file_size

@app.route('/media/<path:filename>')
def stream_media(filename):
    file_path = os.path.join(MEDIA_DIR, filename)
    
    if not os.path.exists(file_path):
        return f"Файл {filename} не найден", 404
    
    file_size = os.path.getsize(file_path)
    range_header = request.headers.get('Range')
    
    # Определяем MIME тип
    mime_type, _ = mimetypes.guess_type(file_path)
    if not mime_type:
        mime_type = 'application/octet-stream'
    
    # Если нет Range заголовка, отдаем весь файл
    if not range_header:
        response = send_from_directory(MEDIA_DIR, filename)
        response.headers['Accept-Ranges'] = 'bytes'
        response.headers['Access-Control-Allow-Origin'] = '*'
        return response
    
    # Парсим Range заголовок
    start, end, length = parse_range_header(range_header, file_size)
    
    if start is None:
        # Некорректный Range, отдаем весь файл
        response = send_from_directory(MEDIA_DIR, filename)
        response.headers['Accept-Ranges'] = 'bytes'
        response.headers['Access-Control-Allow-Origin'] = '*'
        return response
    
    # Создаем ответ с частичным содержимым
    def generate():
        with open(file_path, 'rb') as f:
            f.seek(start)
            remaining = length
            chunk_size = 40000
            
            while remaining > 0:
                chunk = min(chunk_size, remaining)
                data = f.read(chunk)
                if not data:
                    break
                yield data
                remaining -= len(data)
    
    response = Response(
        generate(),
        status=206,
        mimetype=mime_type,
        direct_passthrough=True
    )
    
    response.headers.add('Content-Length', str(length))
    response.headers.add('Accept-Ranges', 'bytes')
    response.headers.add('Content-Range', f'bytes {start}-{end}/{file_size}')
    response.headers.add('Access-Control-Allow-Origin', '*')
    response.headers.add('Access-Control-Expose-Headers', 'Content-Range, Content-Length, Accept-Ranges')
    response.headers.add('Cache-Control', 'no-cache')
    
    return response

@app.after_request
def after_request(response):
    """Добавляем CORS заголовки ко всем ответам"""
    response.headers.add('Access-Control-Allow-Origin', '*')
    response.headers.add('Access-Control-Allow-Headers', 'Range, Content-Type')
    response.headers.add('Access-Control-Allow-Methods', 'GET, HEAD, OPTIONS')
    response.headers.add('Access-Control-Expose-Headers', 'Content-Range, Content-Length, Accept-Ranges')
    return response

@app.route('/media/<path:filename>', methods=['OPTIONS'])
def options_handler(filename):
    """Обработчик OPTIONS запросов для CORS"""
    response = Response()
    response.headers['Access-Control-Allow-Origin'] = '*'
    response.headers['Access-Control-Allow-Headers'] = 'Range, Content-Type'
    response.headers['Access-Control-Allow-Methods'] = 'GET, HEAD, OPTIONS'
    response.headers['Access-Control-Expose-Headers'] = 'Content-Range, Content-Length, Accept-Ranges'
    return response

@app.route('/list')
def list_files():
    """API для получения списка файлов"""
    files = []
    try:
        for file in os.listdir(MEDIA_DIR):
            if os.path.isfile(os.path.join(MEDIA_DIR, file)):
                file_path = os.path.join(MEDIA_DIR, file)
                files.append({
                    'name': file,
                    'size': os.path.getsize(file_path),
                    'type': mimetypes.guess_type(file_path)[0] or 'unknown',
                    'url': f'/media/{file}'
                })
    except Exception as e:
        return {'error': str(e)}, 500
    
    return {'files': files}

@app.route('/')
def home():
    files = []
    try:
        for file in os.listdir(MEDIA_DIR):
            if os.path.isfile(os.path.join(MEDIA_DIR, file)):
                files.append(file)
    except:
        files = ["Не удалось прочитать директорию"]
    
    file_list = "\n".join([f'<li><a href="/media/{file}">{file}</a></li>' for file in files[:20]])
    
    return f"""
    <!DOCTYPE html>
    <html>
    <head>
        <title>uSharpVideo Media Server</title>
        <style>
            body {{ font-family: Arial, sans-serif; margin: 40px; }}
            .file-list {{ max-height: 400px; overflow-y: auto; border: 1px solid #ccc; padding: 10px; }}
            .info {{ background: #f0f0f0; padding: 10px; border-radius: 5px; }}
            .test-video {{ margin: 20px 0; }}
        </style>
    </head>
    <body>
        <h1>uSharpVideo Media Server</h1>
        
        <div class="info">
            <p><strong>Статус:</strong> HTTP 206 Partial Content поддерживается</p>
            <p><strong>Для uSharpVideo используйте:</strong></p>
            <p>URL: <code>http://ваш_ip:1214/media/имя_файла.mp4</code></p>
        </div>
        
        <h2>Доступные файлы:</h2>
        <div class="file-list">
            <ul>{file_list}</ul>
        </div>
        
        <div class="test-video">
            <h3>Тест HTML5 видео:</h3>
            <p>Выберите видео файл для теста:</p>
            <select id="videoSelect" onchange="updateVideo()">
                <option value="">-- Выберите видео --</option>
                {"".join([f'<option value="{file}">{file}</option>' for file in files if file.lower().endswith(('.mp4', '.avi', '.mov', '.mkv'))])}
            </select>
            
            <div id="videoContainer" style="margin-top: 20px; display: none;">
                <video controls width="600" id="testVideo">
                    Ваш браузер не поддерживает видео тег.
                </video>
                <p>Статус: <span id="status">Не воспроизводится</span></p>
            </div>
        </div>
        
        <p>Также доступен API: <a href="/list">/list</a> для получения списка файлов в JSON</p>
        
        <script>
            function updateVideo() {{
                var select = document.getElementById('videoSelect');
                var video = document.getElementById('testVideo');
                var container = document.getElementById('videoContainer');
                var status = document.getElementById('status');
                
                if (select.value) {{
                    var videoUrl = '/media/' + encodeURIComponent(select.value);
                    video.src = videoUrl;
                    container.style.display = 'block';
                    status.textContent = 'Загрузка...';
                    
                    video.onloadedmetadata = function() {{
                        status.textContent = 'Загружено: ' + video.duration.toFixed(2) + ' сек';
                    }};
                    
                    video.onerror = function() {{
                        status.textContent = 'Ошибка загрузки';
                    }};
                }} else {{
                    container.style.display = 'none';
                }}
            }}
        </script>
    </body>
    </html>
    """

if __name__ == '__main__':
    print("=" * 60)
    print("uSharpVideo Media Server запускается...")
    print(f"Директория: {MEDIA_DIR}")
    print("HTTP 206 Partial Content поддерживается")
    print("=" * 60)
    
    try:
        files = os.listdir(MEDIA_DIR)
        video_files = [f for f in files if f.lower().endswith(('.mp4', '.avi', '.mov', '.mkv'))]
        
        print("Видео файлы:")
        for file in video_files[:5]:
            print(f"  - {file}")
        if len(video_files) > 5:
            print(f"  ... и еще {len(video_files)-5} видео файлов")
            
    except Exception as e:
        print(f"Ошибка при чтении директории: {e}")
    
    print("=" * 60)
    print("Сервер запущен на http://0.0.0.0:1214")
    print("Для теста откройте в браузере и проверьте работу видео")
    print("=" * 60)
    
    app.run(host='0.0.0.0', port=1214, debug=True, threaded=True)

