from flask import Blueprint, request, jsonify, Response, stream_with_context
from flask_cors import cross_origin
import requests
import os
from dotenv import load_dotenv
import logging
from urllib.parse import unquote
from src.models.db import db
from src.models.gif_feedback import GifFeedback, GifUsage
from datetime import datetime
import uuid
from urllib.parse import unquote, urlparse
import time
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

# .env 로드
load_dotenv(os.path.join(os.path.dirname(__file__), '..', '.env'))

gif_bp = Blueprint('gif', __name__)

# Tenor API 설정
TENOR_API_KEY = os.getenv("TENOR_API_KEY")
TENOR_BASE_URL = "https://tenor.googleapis.com/v2"
logger = logging.getLogger(__name__)

# 허용된 이미지 호스트 목록
ALLOWED_IMAGE_HOSTS = {
    "media.tenor.com",
    "mlink.kdjsystem.com"
}

def create_robust_session():
    """강력한 재시도 로직이 있는 requests 세션 생성"""
    session = requests.Session()
    
    # 재시도 전략 설정
    retry_strategy = Retry(
        total=3,
        backoff_factor=1,
        status_forcelist=[429, 500, 502, 503, 504],
        allowed_methods=["HEAD", "GET", "OPTIONS"]
    )
    
    adapter = HTTPAdapter(max_retries=retry_strategy)
    session.mount("http://", adapter)
    session.mount("https://", adapter)
    
    return session

@gif_bp.route('/api/gif/proxy/<path:image_url>')
@cross_origin()
def proxy_image(image_url):
    """
    개선된 이미지 프록시:
    - SSL 오류 처리 개선
    - 재시도 로직 추가
    - 타임아웃 설정 강화
    - 더 나은 오류 처리
    """
    try:
        # 1) 1회 디코딩
        raw = unquote(image_url)
        logger.info(f"프록시 요청: {raw}")

        # 2) 누락/오타 보정
        if raw.startswith("https:/") and not raw.startswith("https://"):
            raw = raw.replace("https:/", "https://", 1)
        if raw.startswith("http:/") and not raw.startswith("http://"):
            raw = raw.replace("http:/", "http://", 1)
        if not raw.startswith("http://") and not raw.startswith("https://"):
            raw = "https://" + raw.lstrip("/")

        # 3) 호스트 화이트리스트 체크(SSRF 방지)
        p = urlparse(raw)
        if p.hostname not in ALLOWED_IMAGE_HOSTS:
            logger.warning(f"Blocked host: {p.hostname}")
            return jsonify({"error": "Host not allowed"}), 400

        logger.info(f"[GIF Proxy] GET {raw}")

        # 4) 강화된 요청 설정
        session = create_robust_session()
        
        # 요청 헤더 설정
        headers = {
            "User-Agent": "Mozilla/5.0 (compatible; MLINK-Proxy/1.0)",
            "Accept": "image/*,*/*;q=0.8",
            "Accept-Encoding": "gzip, deflate",
            "Connection": "keep-alive"
        }
        
        # 요청 옵션
        request_options = {
            "stream": True,
            "timeout": (5, 30),  # (연결 타임아웃, 읽기 타임아웃)
            "allow_redirects": True,
            "headers": headers,
            "verify": True  # SSL 인증서 검증
        }
        
        # 최대 3번 재시도
        max_retries = 3
        for attempt in range(max_retries):
            try:
                logger.info(f"프록시 시도 {attempt + 1}/{max_retries}: {raw}")
                
                upstream = session.get(raw, **request_options)
                upstream.raise_for_status()
                
                # 성공 시 루프 종료
                break
                
            except requests.exceptions.SSLError as e:
                logger.warning(f"SSL 오류 (시도 {attempt + 1}): {e}")
                if attempt == max_retries - 1:
                    # 마지막 시도에서 SSL 검증 비활성화
                    request_options["verify"] = False
                    logger.warning("SSL 검증 비활성화로 재시도")
                    upstream = session.get(raw, **request_options)
                    upstream.raise_for_status()
                else:
                    time.sleep(1)  # 1초 대기 후 재시도
                    continue
                    
            except requests.exceptions.Timeout as e:
                logger.warning(f"타임아웃 오류 (시도 {attempt + 1}): {e}")
                if attempt == max_retries - 1:
                    raise
                time.sleep(1)
                continue
                
            except requests.exceptions.RequestException as e:
                logger.warning(f"요청 오류 (시도 {attempt + 1}): {e}")
                if attempt == max_retries - 1:
                    raise
                time.sleep(1)
                continue

        # 5) 응답 헤더 설정
        response_headers = {
            "Content-Type": upstream.headers.get("Content-Type", "image/gif"),
            "Cache-Control": "public, max-age=3600",
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Methods": "GET",
            "Access-Control-Allow-Headers": "Content-Type",
            "X-Proxy-Source": "MLINK-GIF-Proxy"
        }

        # 6) 스트리밍 응답 (청크 크기 조정)
        def generate():
            try:
                for chunk in upstream.iter_content(chunk_size=8192):
                    if chunk:
                        yield chunk
            except Exception as e:
                logger.error(f"스트리밍 중 오류: {e}")
                yield b""

        return Response(
            generate(),
            status=upstream.status_code,
            headers=response_headers
        )

    except requests.exceptions.SSLError as e:
        logger.error(f"SSL 연결 오류: {e}")
        return jsonify({"error": "SSL 연결 오류가 발생했습니다."}), 502
        
    except requests.exceptions.Timeout as e:
        logger.error(f"요청 타임아웃: {e}")
        return jsonify({"error": "요청이 시간 초과되었습니다."}), 504
        
    except requests.exceptions.RequestException as e:
        logger.error(f"요청 오류: {e}")
        return jsonify({"error": "이미지를 가져올 수 없습니다."}), 502
        
    except Exception as e:
        logger.error(f"예상치 못한 오류: {str(e)}")
        return jsonify({"error": "서버 내부 오류가 발생했습니다."}), 500

# 나머지 기존 함수들은 그대로 유지
# ... (기존 코드 계속)
