"""
Instagram Video Downloader Service
Отдельный микросервис для скачивания видео с Instagram
"""
import os
import logging
import time
from pathlib import Path
from flask import Flask, request, jsonify
from flask_cors import CORS
import yt_dlp
import uuid
import re

# Настройка логирования
logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    level=logging.INFO
)
logger = logging.getLogger(__name__)

app = Flask(__name__)
CORS(app)  # Разрешаем CORS для взаимодействия с основным ботом

# Директория для временных файлов
DOWNLOADS_DIR = Path('downloads')
DOWNLOADS_DIR.mkdir(exist_ok=True)


def check_instagram_cookies_expiry() -> tuple[bool, int]:
    """
    Проверяет срок действия Instagram cookies
    Returns: (is_valid, days_until_expiry)
    """
    cookies_file = os.getenv('INSTAGRAM_COOKIES_FILE', 'instagram_cookies.txt')
    cookies_file_path = Path(cookies_file)
    
    if not cookies_file_path.exists():
        return False, 0
    
    try:
        current_time = time.time()
        valid_expiries = []
        
        # Важные cookies для Instagram (проверяем их в первую очередь)
        important_cookies = ['sessionid', 'csrftoken', 'ds_user_id']
        
        with open(cookies_file_path, 'r') as f:
            for line in f:
                line = line.strip()
                if not line or line.startswith('#'):
                    continue
                parts = line.split('\t')
                if len(parts) >= 7:
                    domain = parts[0]
                    if 'instagram' in domain.lower():
                        try:
                            expiry = int(parts[4])  # Unix timestamp
                            cookie_name = parts[5] if len(parts) > 5 else ''
                            
                            # Игнорируем невалидные expiry (0, отрицательные, или слишком старые)
                            # Session cookies (expiry = 0) также игнорируем для проверки срока
                            if expiry > 0 and expiry > 946684800:  # Фильтр: после 2000-01-01 (избегаем epoch 0)
                                # Для важных cookies проверяем строже
                                if cookie_name in important_cookies:
                                    if expiry > current_time:
                                        valid_expiries.append(expiry)
                                else:
                                    valid_expiries.append(expiry)
                        except (ValueError, IndexError):
                            continue
        
        if not valid_expiries:
            logger.warning("Не найдено валидных Instagram cookies с нормальным сроком действия")
            # Если нет валидных expiry, но есть cookies - считаем их действительными
            # (возможно, это session cookies)
            return True, 30  # Возвращаем разумное значение по умолчанию
        
        # Берем минимальный валидный expiry
        min_expiry = min(valid_expiries)
        days_until_expiry = (min_expiry - current_time) / 86400
        is_valid = min_expiry > current_time
        
        return is_valid, int(days_until_expiry)
    except Exception as e:
        logger.error(f"Ошибка при проверке срока действия cookies: {e}")
        # В случае ошибки считаем cookies действительными (не блокируем работу)
        return True, 30


def download_instagram_video(url: str, max_retries: int = 3) -> Path:
    """Скачивает видео с Instagram - используем cookies с правильными заголовками"""
    cookies_file = os.getenv('INSTAGRAM_COOKIES_FILE', 'instagram_cookies.txt')
    cookies_file_path = Path(cookies_file)
    
    # Проверяем срок действия cookies перед использованием
    if cookies_file_path.exists():
        is_valid, days_left = check_instagram_cookies_expiry()
        if not is_valid:
            logger.error("Instagram cookies истекли! Необходимо обновить cookies.")
            raise Exception("Instagram cookies истекли. Пожалуйста, обновите cookies в файле instagram_cookies.txt")
        elif days_left < 7:
            logger.warning(f"Instagram cookies истекают через {days_left} дней. Рекомендуется обновить.")
    
    # Парсим cookies для получения csrf token (формат Netscape)
    csrf_token = None
    sessionid = None
    if cookies_file_path.exists():
        try:
            with open(cookies_file_path, 'r') as f:
                for line in f:
                    line = line.strip()
                    if not line or line.startswith('#'):
                        continue
                    parts = line.split('\t')
                    if len(parts) >= 7:
                        domain = parts[0]
                        # Ищем только cookies от instagram.com
                        if 'instagram' in domain.lower():
                            cookie_name = parts[5]  # Имя cookie
                            cookie_value = parts[6]  # Значение cookie
                            if cookie_name == 'csrftoken':
                                csrf_token = cookie_value
                            elif cookie_name == 'sessionid':
                                sessionid = cookie_value
                            # Если нашли оба - можно выходить
                            if csrf_token and sessionid:
                                break
        except Exception as e:
            logger.warning(f"Не удалось прочитать cookies: {e}")
    
    last_error = None
    for attempt in range(max_retries):
        try:
            # Базовые настройки
            ydl_opts = {
                'format': 'best',
                'outtmpl': str(DOWNLOADS_DIR / f'{uuid.uuid4()}_%(title)s.%(ext)s'),
                'quiet': False,
                'no_warnings': False,
                'socket_timeout': 30,
            }
            
            # Если есть файл с cookies, используем его
            if cookies_file_path.exists():
                # Используем абсолютный путь к cookies
                ydl_opts['cookiefile'] = str(cookies_file_path.absolute())
                logger.info(f"Instagram: используем cookies из {cookies_file_path}")
                
                # Добавляем заголовки с csrf token если есть
                headers = {
                    'Referer': 'https://www.instagram.com/',
                    'X-Requested-With': 'XMLHttpRequest',
                }
                if csrf_token:
                    headers['X-CSRFToken'] = csrf_token
                    logger.info(f"Instagram: добавлен csrf token в заголовки")
                if sessionid:
                    logger.info(f"Instagram: sessionid найден (длина: {len(sessionid)})")
                
                ydl_opts['http_headers'] = headers
            
            logger.info(f"Instagram: начинаем скачивание (попытка {attempt + 1}/{max_retries})")
            
            with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                ydl.download([url])
            
            # Находим скачанный файл
            downloaded_files = list(DOWNLOADS_DIR.glob('*'))
            if downloaded_files:
                downloaded_files.sort(key=lambda x: x.stat().st_mtime, reverse=True)
                return downloaded_files[0]
            else:
                raise Exception("Файл не был найден после скачивания")
                
        except Exception as e:
            last_error = e
            logger.warning(f"Instagram: попытка {attempt + 1}/{max_retries} не удалась: {e}")
            if attempt < max_retries - 1:
                time.sleep((attempt + 1) * 2)
    
    raise last_error or Exception("Неизвестная ошибка при скачивании с Instagram. Возможно, нужно обновить cookies.")


@app.route('/health', methods=['GET'])
def health():
    """Health check endpoint"""
    return jsonify({'status': 'ok', 'service': 'instagram-downloader'}), 200


@app.route('/download/stream', methods=['POST'])
def download_stream():
    """Скачивает видео с Instagram и возвращает бинарные данные"""
    try:
        data = request.get_json()
        if not data or 'url' not in data:
            return jsonify({'error': 'URL is required'}), 400
        
        url = data['url']
        logger.info(f"Получен запрос на скачивание (stream): {url}")
        
        # Проверяем, что это Instagram URL
        if 'instagram.com' not in url:
            return jsonify({'error': 'Only Instagram URLs are supported'}), 400
        
        # Скачиваем видео
        video_path = download_instagram_video(url)
        logger.info(f"Видео скачано: {video_path}")
        
        # Читаем файл и отправляем
        with open(video_path, 'rb') as f:
            video_data = f.read()
        
        # Безопасное имя файла без кириллицы для заголовка
        safe_filename = video_path.name.encode('ascii', 'ignore').decode('ascii') or 'instagram_video.mp4'
        if not safe_filename.endswith(('.mp4', '.webm', '.mkv')):
            safe_filename = 'instagram_video.mp4'
        
        # Определяем content-type
        content_type = 'video/mp4'
        if video_path.suffix == '.webm':
            content_type = 'video/webm'
        elif video_path.suffix == '.mkv':
            content_type = 'video/x-matroska'
        
        # Удаляем временный файл
        video_path.unlink()
        
        return video_data, 200, {
            'Content-Type': content_type,
            'Content-Disposition': f'attachment; filename="{safe_filename}"'
        }
        
    except Exception as e:
        logger.error(f"Ошибка при скачивании: {e}")
        return jsonify({'error': str(e)}), 500


if __name__ == '__main__':
    port = int(os.getenv('PORT', 5000))  # Внутренний порт контейнера
    host = os.getenv('HOST', '0.0.0.0')
    logger.info(f"Запуск Instagram Downloader сервиса на {host}:{port}")
    app.run(host=host, port=port, debug=False)

