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

# .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"
}

@gif_bp.route('/api/gif/proxy/<path:image_url>')
@cross_origin()
def proxy_image(image_url):
    """
    이미지 프록시:
    - 프론트에서 전체 URL을 encodeURIComponent 해서 넘김
    - 여기서 1회만 unquote
    - 잘못된 scheme/slash 보정
    - 화이트리스트 호스트만 허용 (SSRF 방지)
    - 원격 상태코드/헤더를 최대한 유지하여 반환
    """
    try:
        # 1) 1회 디코딩
        raw = unquote(image_url)
        logger.info(f"프록시 요청: {raw}")

        # 2) 누락/오타 보정
        #    https:/... → https://...
        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)
        #    스킴이 아예 없고 호스트부터 시작하는 경우 → https:// 추가
        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) 원본 요청 (UA/타임아웃/리다이렉트 허용)
        upstream = requests.get(
            raw,
            stream=True,
            timeout=10,
            allow_redirects=True,
            headers={
                "User-Agent": "Mozilla/5.0 (compatible; MLINK-Proxy/1.0)"
            }
        )
        upstream.raise_for_status()

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

        # 6) 스트리밍 응답
        return Response(
            stream_with_context(upstream.iter_content(chunk_size=8192)),
            status=upstream.status_code,
            headers=headers
        )

    except Exception as e:
        logger.error(f"이미지 프록시 오류: {str(e)}")
        return jsonify({"error": "이미지를 가져올 수 없습니다."}), 500


@gif_bp.route('/api/gif/search', methods=['GET'])
def search_gifs():
    """Tenor API를 사용하여 GIF 검색"""
    try:
        # API 키 확인
        if not TENOR_API_KEY:
            return jsonify({
                "error": "Tenor API 키가 설정되지 않았습니다.",
                "gifs": []
            }), 500
        
        # 요청 파라미터
        query = request.args.get('q', '')
        limit = int(request.args.get('limit', 20))
        pos = int(request.args.get('pos', 0))
        
        # Tenor API 호출
        params = {
            'key': TENOR_API_KEY,
            'q': query,
            'limit': limit,
            'pos': pos,
            'media_filter': 'gif',
            'contentfilter': 'high',
            'ar_range': 'all'
        }
        
        response = requests.get(f"{TENOR_BASE_URL}/search", params=params)
        response.raise_for_status()
        
        data = response.json()
        
        # GIF 데이터 처리
        gifs = []
        for item in data.get('results', []):
            gif_data = {
                'id': item.get('id'),
                'title': item.get('content_description', ''),
                'url': item.get('media_formats', {}).get('gif', {}).get('url', ''),
                'preview_url': item.get('media_formats', {}).get('tinygif', {}).get('url', ''),
                'width': item.get('media_formats', {}).get('gif', {}).get('dims', [0, 0])[0],
                'height': item.get('media_formats', {}).get('gif', {}).get('dims', [0, 0])[1]
            }
            
            # 프록시 URL 생성
            if gif_data['url']:
                gif_data['proxy_url'] = f"/api/gif/proxy/{gif_data['url']}"
            if gif_data['preview_url']:
                gif_data['preview_proxy_url'] = f"/api/gif/proxy/{gif_data['preview_url']}"
            
            gifs.append(gif_data)
        
        return jsonify({
            "gifs": gifs,
            "next": data.get('next', 0)
        })
        
    except Exception as e:
        logger.error(f"GIF 검색 실패: {str(e)}")
        return jsonify({
            "error": "GIF 검색에 실패했습니다.",
            "gifs": []
        }), 500

@gif_bp.route('/api/gif/trending', methods=['GET'])
@cross_origin()
def get_trending_gifs():
    """인기 GIF 가져오기"""
    try:
        if not TENOR_API_KEY:
            return jsonify({
                "error": "Tenor API 키가 설정되지 않았습니다.",
                "gifs": []
            }), 500
        
        limit = request.args.get('limit', 20)
        popular_keywords = ['funny', 'reaction', 'celebration', 'happy', 'excited', 'love', 'wow', 'cool']
        
        params = {
            'key': TENOR_API_KEY,
            'q': popular_keywords[0],
            'limit': min(int(limit), 50),
            'media_filter': 'gif',
            'contentfilter': 'high',
            'ar_range': 'all'
        }
        
        response = requests.get(f"{TENOR_BASE_URL}/search", params=params, timeout=10)
        response.raise_for_status()
        
        data = response.json()
        
        gifs = []
        for result in data.get('results', []):
            gif_data = process_gif_data(result)
            if gif_data:
                gifs.append(gif_data)
        
        return jsonify({
            'gifs': gifs,
            'next': data.get('next', 0)
        }), 200
        
    except Exception as e:
        logger.error(f"인기 GIF 가져오기 실패: {e}")
        return jsonify({
            "error": "인기 GIF를 가져오는 중 오류가 발생했습니다.",
            "gifs": []
        }), 500

@gif_bp.route('/api/gif/random', methods=['GET'])
def get_random_gifs():
    """랜덤 GIF 가져오기"""
    try:
        # API 키 확인
        if not TENOR_API_KEY:
            return jsonify({
                "error": "Tenor API 키가 설정되지 않았습니다.",
                "gifs": []
            }), 500
        
        # 요청 파라미터
        limit = int(request.args.get('limit', 20))
        
        # Tenor API 호출 (빈 검색어로 랜덤 결과)
        params = {
            'key': TENOR_API_KEY,
            'q': 'funny',  # 기본 키워드 사용
            'limit': limit,
            'media_filter': 'gif',
            'contentfilter': 'high',
            'ar_range': 'all'
        }
        
        response = requests.get(f"{TENOR_BASE_URL}/search", params=params)
        response.raise_for_status()
        
        data = response.json()
        
        # GIF 데이터 처리
        gifs = []
        for item in data.get('results', []):
            gif_data = {
                'id': item.get('id'),
                'title': item.get('content_description', ''),
                'url': item.get('media_formats', {}).get('gif', {}).get('url', ''),
                'preview_url': item.get('media_formats', {}).get('tinygif', {}).get('url', ''),
                'width': item.get('media_formats', {}).get('gif', {}).get('dims', [0, 0])[0],
                'height': item.get('media_formats', {}).get('gif', {}).get('dims', [0, 0])[1]
            }
            
            # 프록시 URL 생성
            if gif_data['url']:
                gif_data['proxy_url'] = f"/api/gif/proxy/{gif_data['url']}"
            if gif_data['preview_url']:
                gif_data['preview_proxy_url'] = f"/api/gif/proxy/{gif_data['preview_url']}"
            
            gifs.append(gif_data)
        
        return jsonify({
            "gifs": gifs,
            "next": data.get('next', 0)
        })
        
    except Exception as e:
        logger.error(f"랜덤 GIF 가져오기 실패: {str(e)}")
        return jsonify({
            "error": "랜덤 GIF를 가져올 수 없습니다.",
            "gifs": []
        }), 500
    except Exception as e:
        logger.error(f"랜덤 GIF 가져오기 예외: {e}")
        return jsonify({
            "error": "서버 오류가 발생했습니다.",
            "gifs": []
        }), 500

@gif_bp.route('/api/gif/categories', methods=['GET'])
@cross_origin()
def get_gif_categories():
    """GIF 카테고리 가져오기"""
    try:
        if not TENOR_API_KEY:
            return jsonify({
                "error": "Tenor API 키가 설정되지 않았습니다.",
                "categories": []
            }), 500
        
        categories = [
            {'name': 'Funny', 'searchterm': 'funny', 'image': '', 'path': 'funny'},
            {'name': 'Reaction', 'searchterm': 'reaction', 'image': '', 'path': 'reaction'},
            {'name': 'Celebration', 'searchterm': 'celebration', 'image': '', 'path': 'celebration'},
            {'name': 'Happy', 'searchterm': 'happy', 'image': '', 'path': 'happy'},
            {'name': 'Love', 'searchterm': 'love', 'image': '', 'path': 'love'},
            {'name': 'Cool', 'searchterm': 'cool', 'image': '', 'path': 'cool'},
            {'name': 'Excited', 'searchterm': 'excited', 'image': '', 'path': 'excited'},
            {'name': 'Wow', 'searchterm': 'wow', 'image': '', 'path': 'wow'}
        ]
        
        return jsonify({'categories': categories}), 200
        
    except Exception as e:
        logger.error(f"GIF 카테고리 가져오기 실패: {e}")
        return jsonify({
            "error": "GIF 카테고리를 가져오는 중 오류가 발생했습니다.",
            "categories": []
        }), 500

@gif_bp.route('/api/gif/featured', methods=['GET'])
@cross_origin()
def get_featured_gifs():
    """추천 GIF 가져오기"""
    try:
        if not TENOR_API_KEY:
            return jsonify({
                "error": "Tenor API 키가 설정되지 않았습니다.",
                "gifs": []
            }), 500
        
        limit = request.args.get('limit', 20)
        
        params = {
            'key': TENOR_API_KEY,
            'q': 'trending',
            'limit': min(int(limit), 50),
            'media_filter': 'gif',
            'contentfilter': 'high',
            'ar_range': 'all'
        }
        
        response = requests.get(f"{TENOR_BASE_URL}/search", params=params, timeout=10)
        response.raise_for_status()
        
        data = response.json()
        
        gifs = []
        for result in data.get('results', []):
            gif_data = process_gif_data(result)
            if gif_data:
                gifs.append(gif_data)
        
        return jsonify({
            'gifs': gifs,
            'next': data.get('next', 0)
        }), 200
        
    except Exception as e:
        logger.error(f"추천 GIF 가져오기 실패: {e}")
        return jsonify({
            "error": "추천 GIF를 가져오는 중 오류가 발생했습니다.",
            "gifs": []
        }), 500 

@gif_bp.route('/api/gif/feedback', methods=['POST'])
@cross_origin()
def submit_gif_feedback():
    """GIF 피드백 제출"""
    try:
        data = request.get_json()
        
        # 필수 필드 검증
        required_fields = ['gif_id', 'gif_url', 'feedback_type']
        for field in required_fields:
            if field not in data:
                return jsonify({"error": f"필수 필드가 누락되었습니다: {field}"}), 400
        
        # 피드백 타입 검증
        valid_feedback_types = ['like', 'dislike', 'funny', 'useful', 'inappropriate']
        if data['feedback_type'] not in valid_feedback_types:
            return jsonify({"error": "유효하지 않은 피드백 타입입니다."}), 400
        
        # 평점 검증 (있는 경우)
        if 'rating' in data and data['rating'] is not None:
            if not isinstance(data['rating'], int) or data['rating'] < 1 or data['rating'] > 5:
                return jsonify({"error": "평점은 1-5 사이의 정수여야 합니다."}), 400
        
        # 세션 ID 생성 (없는 경우)
        session_id = data.get('session_id')
        if not session_id:
            session_id = str(uuid.uuid4())
        
        # 피드백 생성
        feedback = GifFeedback(
            gif_id=data['gif_id'],
            gif_title=data.get('gif_title', ''),
            gif_url=data['gif_url'],
            user_id=data.get('user_id'),
            session_id=session_id,
            feedback_type=data['feedback_type'],
            rating=data.get('rating'),
            comment=data.get('comment', '')
        )
        
        db.session.add(feedback)
        db.session.commit()
        
        return jsonify({
            "message": "피드백이 성공적으로 제출되었습니다.",
            "feedback_id": feedback.id,
            "session_id": session_id
        }), 201
        
    except Exception as e:
        db.session.rollback()
        logger.error(f"GIF 피드백 제출 실패: {str(e)}")
        return jsonify({"error": "피드백 제출에 실패했습니다."}), 500

@gif_bp.route('/api/gif/feedback/<gif_id>', methods=['GET'])
@cross_origin()
def get_gif_feedback(gif_id):
    """특정 GIF의 피드백 조회"""
    try:
        # 피드백 통계 조회
        feedback_stats = db.session.query(
            GifFeedback.feedback_type,
            db.func.count(GifFeedback.id).label('count')
        ).filter(
            GifFeedback.gif_id == gif_id
        ).group_by(GifFeedback.feedback_type).all()
        
        # 평점 통계 조회
        rating_stats = db.session.query(
            db.func.avg(GifFeedback.rating).label('average_rating'),
            db.func.count(GifFeedback.rating).label('rating_count')
        ).filter(
            GifFeedback.gif_id == gif_id,
            GifFeedback.rating.isnot(None)
        ).first()
        
        # 최근 피드백 조회 (최대 10개)
        recent_feedbacks = GifFeedback.query.filter(
            GifFeedback.gif_id == gif_id
        ).order_by(GifFeedback.created_at.desc()).limit(10).all()
        
        # 통계 데이터 구성
        stats = {
            'total_feedbacks': sum(stat.count for stat in feedback_stats),
            'feedback_breakdown': {stat.feedback_type: stat.count for stat in feedback_stats},
            'average_rating': float(rating_stats.average_rating) if rating_stats.average_rating else None,
            'rating_count': rating_stats.rating_count if rating_stats.rating_count else 0,
            'recent_feedbacks': [feedback.to_dict() for feedback in recent_feedbacks]
        }
        
        return jsonify(stats), 200
        
    except Exception as e:
        logger.error(f"GIF 피드백 조회 실패: {str(e)}")
        return jsonify({"error": "피드백 조회에 실패했습니다."}), 500

@gif_bp.route('/api/gif/usage', methods=['POST'])
@cross_origin()
def track_gif_usage():
    """GIF 사용 추적"""
    try:
        data = request.get_json()
        
        # 필수 필드 검증
        required_fields = ['gif_id', 'gif_url', 'usage_type']
        for field in required_fields:
            if field not in data:
                return jsonify({"error": f"필수 필드가 누락되었습니다: {field}"}), 400
        
        # 사용 타입 검증
        valid_usage_types = ['sent', 'viewed', 'shared']
        if data['usage_type'] not in valid_usage_types:
            return jsonify({"error": "유효하지 않은 사용 타입입니다."}), 400
        
        # 세션 ID 생성 (없는 경우)
        session_id = data.get('session_id')
        if not session_id:
            session_id = str(uuid.uuid4())
        
        # 사용 기록 생성
        usage = GifUsage(
            gif_id=data['gif_id'],
            gif_title=data.get('gif_title', ''),
            gif_url=data['gif_url'],
            user_id=data.get('user_id'),
            session_id=session_id,
            usage_type=data['usage_type'],
            context=data.get('context', 'chat')
        )
        
        db.session.add(usage)
        db.session.commit()
        
        return jsonify({
            "message": "사용 기록이 성공적으로 저장되었습니다.",
            "usage_id": usage.id,
            "session_id": session_id
        }), 201
        
    except Exception as e:
        db.session.rollback()
        logger.error(f"GIF 사용 추적 실패: {str(e)}")
        return jsonify({"error": "사용 추적에 실패했습니다."}), 500

@gif_bp.route('/api/gif/analytics', methods=['GET'])
@cross_origin()
def get_gif_analytics():
    """GIF 분석 데이터 조회"""
    try:
        # 전체 통계
        total_gifs = GifUsage.query.count()
        total_feedbacks = GifFeedback.query.count()
        
        # 인기 GIF (사용량 기준)
        popular_gifs = db.session.query(
            GifUsage.gif_id,
            GifUsage.gif_title,
            db.func.count(GifUsage.id).label('usage_count')
        ).group_by(
            GifUsage.gif_id, GifUsage.gif_title
        ).order_by(
            db.func.count(GifUsage.id).desc()
        ).limit(10).all()
        
        # 피드백 타입별 통계
        feedback_by_type = db.session.query(
            GifFeedback.feedback_type,
            db.func.count(GifFeedback.id).label('count')
        ).group_by(GifFeedback.feedback_type).all()
        
        # 일별 사용량 (최근 7일)
        from datetime import datetime, timedelta
        seven_days_ago = datetime.now() - timedelta(days=7)
        
        daily_usage = db.session.query(
            db.func.date(GifUsage.created_at).label('date'),
            db.func.count(GifUsage.id).label('count')
        ).filter(
            GifUsage.created_at >= seven_days_ago
        ).group_by(
            db.func.date(GifUsage.created_at)
        ).all()
        
        analytics = {
            'total_gifs_used': total_gifs,
            'total_feedbacks': total_feedbacks,
            'popular_gifs': [
                {
                    'gif_id': gif.gif_id,
                    'gif_title': gif.gif_title,
                    'usage_count': gif.usage_count
                }
                for gif in popular_gifs
            ],
            'feedback_breakdown': {
                feedback.feedback_type: feedback.count 
                for feedback in feedback_by_type
            },
            'daily_usage': [
                {
                    'date': usage.date.isoformat(),
                    'count': usage.count
                }
                for usage in daily_usage
            ]
        }
        
        return jsonify(analytics), 200
        
    except Exception as e:
        logger.error(f"GIF 분석 데이터 조회 실패: {str(e)}")
        return jsonify({"error": "분석 데이터 조회에 실패했습니다."}), 500 