"""
BreakPilot Content Service - FastAPI Application
Educational Content Management & Publishing
"""
from fastapi import FastAPI, Depends, HTTPException, UploadFile, File, Form, Query
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.orm import Session
from sqlalchemy import or_, and_, func, desc, asc
from typing import List, Optional
from datetime import datetime
import os

from database import get_db, engine
from models import Base, Content, Rating, Tag, Download, ContentStatus
from schemas import (
    ContentCreate, ContentUpdate, ContentResponse, ContentListItem,
    RatingCreate, RatingResponse, ContentFilter, ContentStats,
    CreatorStats, FileUploadResponse, ContentWithRatings
)
from storage import storage

# Create tables
Base.metadata.create_all(bind=engine)

# FastAPI app
app = FastAPI(
    title="BreakPilot Content Service",
    description="Educational Content Management API with Creative Commons",
    version="1.0.0"
)

# CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # TODO: Restrict in production
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# ============= AUTHENTICATION =============

# TODO: Integration mit consent-service OAuth2
async def get_current_user(token: str = None):
    """Get current user from JWT token (consent-service)"""
    # Placeholder - TODO: Implement JWT validation
    return {
        "id": "test-user-123",
        "name": "Test Creator",
        "email": "test@breakpilot.app",
        "role": "creator"
    }

# ============= FILE UPLOAD ENDPOINTS =============

@app.post("/api/v1/upload", response_model=FileUploadResponse)
async def upload_file(
    file: UploadFile = File(...),
    user: dict = Depends(get_current_user)
):
    """Upload content file (Video, PDF, Image)"""
    # Validate file size (max 100MB)
    MAX_SIZE = 100 * 1024 * 1024
    file.file.seek(0, os.SEEK_END)
    file_size = file.file.tell()
    file.file.seek(0)

    if file_size > MAX_SIZE:
        raise HTTPException(400, f"File too large (max 100MB)")

    # Validate file type
    allowed_types = [
        "video/mp4", "video/webm",
        "application/pdf",
        "image/jpeg", "image/png", "image/gif",
        "audio/mpeg", "audio/wav"
    ]

    if file.content_type not in allowed_types:
        raise HTTPException(400, f"File type not allowed: {file.content_type}")

    # Upload to MinIO
    result = await storage.upload_file(
        file_data=file.file,
        file_name=file.filename,
        content_type=file.content_type,
        creator_id=user["id"]
    )

    return FileUploadResponse(**result)

@app.post("/api/v1/upload/thumbnail", response_model=FileUploadResponse)
async def upload_thumbnail(
    file: UploadFile = File(...),
    user: dict = Depends(get_current_user)
):
    """Upload content thumbnail"""
    if not file.content_type.startswith("image/"):
        raise HTTPException(400, "Thumbnail must be an image")

    result = await storage.upload_file(
        file_data=file.file,
        file_name=file.filename,
        content_type=file.content_type,
        creator_id=f"{user['id']}/thumbnails"
    )

    return FileUploadResponse(**result)

# ============= CONTENT CRUD ENDPOINTS =============

@app.post("/api/v1/content", response_model=ContentResponse)
async def create_content(
    content_data: ContentCreate,
    db: Session = Depends(get_db),
    user: dict = Depends(get_current_user)
):
    """Create new educational content"""
    # Create content
    content = Content(
        creator_id=user["id"],
        creator_name=user["name"],
        creator_email=user.get("email"),
        title=content_data.title,
        description=content_data.description,
        content_type=content_data.content_type,
        category=content_data.category,
        license=content_data.license,
        age_min=content_data.age_min,
        age_max=content_data.age_max,
        embed_url=content_data.embed_url,
        status=ContentStatus.DRAFT
    )

    # Add tags
    for tag_name in content_data.tags:
        tag = db.query(Tag).filter(Tag.name == tag_name).first()
        if not tag:
            tag = Tag(name=tag_name)
            db.add(tag)
        content.tags.append(tag)

    db.add(content)
    db.commit()
    db.refresh(content)

    return content

@app.get("/api/v1/content/{content_id}", response_model=ContentWithRatings)
async def get_content(
    content_id: str,
    db: Session = Depends(get_db)
):
    """Get content by ID (with ratings)"""
    content = db.query(Content).filter(Content.id == content_id).first()
    if not content:
        raise HTTPException(404, "Content not found")

    # Increment view count
    content.views += 1
    db.commit()

    return content

@app.put("/api/v1/content/{content_id}", response_model=ContentResponse)
async def update_content(
    content_id: str,
    content_data: ContentUpdate,
    db: Session = Depends(get_db),
    user: dict = Depends(get_current_user)
):
    """Update content"""
    content = db.query(Content).filter(Content.id == content_id).first()
    if not content:
        raise HTTPException(404, "Content not found")

    # Check ownership
    if content.creator_id != user["id"]:
        raise HTTPException(403, "Not authorized to update this content")

    # Update fields
    update_data = content_data.dict(exclude_unset=True)
    for field, value in update_data.items():
        if field != "tags":
            setattr(content, field, value)

    # Update tags
    if content_data.tags is not None:
        content.tags.clear()
        for tag_name in content_data.tags:
            tag = db.query(Tag).filter(Tag.name == tag_name).first()
            if not tag:
                tag = Tag(name=tag_name)
                db.add(tag)
            content.tags.append(tag)

    db.commit()
    db.refresh(content)

    return content

@app.delete("/api/v1/content/{content_id}")
async def delete_content(
    content_id: str,
    db: Session = Depends(get_db),
    user: dict = Depends(get_current_user)
):
    """Delete content"""
    content = db.query(Content).filter(Content.id == content_id).first()
    if not content:
        raise HTTPException(404, "Content not found")

    # Check ownership or admin
    if content.creator_id != user["id"] and user["role"] != "admin":
        raise HTTPException(403, "Not authorized")

    # Delete files from MinIO
    for file_url in content.files:
        # Extract object name from URL
        object_name = "/".join(file_url.split("/")[-2:])
        await storage.delete_file(object_name)

    db.delete(content)
    db.commit()

    return {"message": "Content deleted"}

@app.post("/api/v1/content/{content_id}/files")
async def add_content_files(
    content_id: str,
    file_urls: List[str],
    db: Session = Depends(get_db),
    user: dict = Depends(get_current_user)
):
    """Add files to content (after upload)"""
    content = db.query(Content).filter(Content.id == content_id).first()
    if not content:
        raise HTTPException(404, "Content not found")

    if content.creator_id != user["id"]:
        raise HTTPException(403, "Not authorized")

    # Add file URLs
    if not content.files:
        content.files = []
    content.files.extend(file_urls)

    db.commit()
    db.refresh(content)

    return content

@app.post("/api/v1/content/{content_id}/publish")
async def publish_content(
    content_id: str,
    db: Session = Depends(get_db),
    user: dict = Depends(get_current_user)
):
    """Publish content (make public)"""
    content = db.query(Content).filter(Content.id == content_id).first()
    if not content:
        raise HTTPException(404, "Content not found")

    if content.creator_id != user["id"]:
        raise HTTPException(403, "Not authorized")

    # Validate content is ready
    if not content.files and not content.embed_url and not content.h5p_content_id:
        raise HTTPException(400, "Content has no files/media")

    content.status = ContentStatus.PUBLISHED
    content.published_at = datetime.utcnow()

    db.commit()
    db.refresh(content)

    # TODO: Publish to Matrix Feed (Sprint 3-4)

    return content

# ============= SEARCH & FILTER ENDPOINTS =============

@app.get("/api/v1/content", response_model=List[ContentListItem])
async def list_content(
    search: Optional[str] = None,
    category: Optional[str] = None,
    content_type: Optional[str] = None,
    license: Optional[str] = None,
    age_min: Optional[int] = None,
    age_max: Optional[int] = None,
    min_rating: Optional[float] = None,
    status: str = "published",
    skip: int = 0,
    limit: int = 20,
    sort_by: str = "created_at",
    sort_desc: bool = True,
    db: Session = Depends(get_db)
):
    """List/Search content with filters"""
    query = db.query(Content)

    # Status filter
    query = query.filter(Content.status == status)

    # Search
    if search:
        query = query.filter(
            or_(
                Content.title.ilike(f"%{search}%"),
                Content.description.ilike(f"%{search}%")
            )
        )

    # Category filter
    if category:
        query = query.filter(Content.category == category)

    # Content type filter
    if content_type:
        query = query.filter(Content.content_type == content_type)

    # License filter
    if license:
        query = query.filter(Content.license == license)

    # Age range filter
    if age_min:
        query = query.filter(Content.age_max >= age_min)
    if age_max:
        query = query.filter(Content.age_min <= age_max)

    # Rating filter
    if min_rating:
        query = query.filter(Content.avg_rating >= min_rating)

    # Sorting
    sort_column = getattr(Content, sort_by, Content.created_at)
    if sort_desc:
        query = query.order_by(desc(sort_column))
    else:
        query = query.order_by(asc(sort_column))

    # Pagination
    total = query.count()
    contents = query.offset(skip).limit(limit).all()

    return contents

@app.get("/api/v1/content/creator/{creator_id}", response_model=List[ContentListItem])
async def get_creator_content(
    creator_id: str,
    db: Session = Depends(get_db)
):
    """Get all content by a creator"""
    contents = db.query(Content).filter(
        Content.creator_id == creator_id
    ).order_by(desc(Content.created_at)).all()

    return contents

# ============= RATING ENDPOINTS =============

@app.post("/api/v1/content/{content_id}/rate", response_model=RatingResponse)
async def rate_content(
    content_id: str,
    rating_data: RatingCreate,
    db: Session = Depends(get_db),
    user: dict = Depends(get_current_user)
):
    """Rate content (teachers only)"""
    content = db.query(Content).filter(Content.id == content_id).first()
    if not content:
        raise HTTPException(404, "Content not found")

    # Check if user already rated
    existing = db.query(Rating).filter(
        Rating.content_id == content_id,
        Rating.user_id == user["id"]
    ).first()

    if existing:
        # Update existing rating
        existing.stars = rating_data.stars
        existing.comment = rating_data.comment
        rating = existing
    else:
        # Create new rating
        rating = Rating(
            content_id=content_id,
            user_id=user["id"],
            user_name=user.get("name"),
            stars=rating_data.stars,
            comment=rating_data.comment
        )
        db.add(rating)

    # Recalculate avg rating
    all_ratings = db.query(Rating).filter(Rating.content_id == content_id).all()
    if all_ratings:
        content.avg_rating = sum(r.stars for r in all_ratings) / len(all_ratings)
        content.rating_count = len(all_ratings)

    db.commit()
    db.refresh(rating)

    return rating

@app.get("/api/v1/content/{content_id}/ratings", response_model=List[RatingResponse])
async def get_content_ratings(
    content_id: str,
    db: Session = Depends(get_db)
):
    """Get all ratings for content"""
    ratings = db.query(Rating).filter(
        Rating.content_id == content_id
    ).order_by(desc(Rating.created_at)).all()

    return ratings

# ============= DOWNLOAD TRACKING =============

@app.post("/api/v1/content/{content_id}/download")
async def track_download(
    content_id: str,
    db: Session = Depends(get_db),
    user: dict = Depends(get_current_user)
):
    """Track content download"""
    content = db.query(Content).filter(Content.id == content_id).first()
    if not content:
        raise HTTPException(404, "Content not found")

    # Increment download count
    content.downloads += 1

    # Track download
    download = Download(
        content_id=content_id,
        user_id=user["id"]
    )
    db.add(download)
    db.commit()

    return {"message": "Download tracked"}

# ============= ANALYTICS ENDPOINTS =============

@app.get("/api/v1/stats/platform", response_model=ContentStats)
async def get_platform_stats(db: Session = Depends(get_db)):
    """Get platform-wide statistics"""
    from .models import ContentCategory, ContentType, CCLicense

    total_contents = db.query(Content).filter(Content.status == "published").count()
    total_downloads = db.query(func.sum(Content.downloads)).scalar() or 0
    total_views = db.query(func.sum(Content.views)).scalar() or 0
    avg_rating = db.query(func.avg(Content.avg_rating)).scalar() or 0.0

    # By category
    by_category = {}
    for cat in ContentCategory:
        count = db.query(Content).filter(
            Content.category == cat,
            Content.status == "published"
        ).count()
        by_category[cat.value] = count

    # By type
    by_type = {}
    for ctype in ContentType:
        count = db.query(Content).filter(
            Content.content_type == ctype,
            Content.status == "published"
        ).count()
        by_type[ctype.value] = count

    # By license
    by_license = {}
    for lic in CCLicense:
        count = db.query(Content).filter(
            Content.license == lic,
            Content.status == "published"
        ).count()
        by_license[lic.value] = count

    return ContentStats(
        total_contents=total_contents,
        total_downloads=total_downloads,
        total_views=total_views,
        avg_rating=float(avg_rating),
        by_category=by_category,
        by_type=by_type,
        by_license=by_license
    )

@app.get("/api/v1/stats/creator/{creator_id}", response_model=CreatorStats)
async def get_creator_stats(
    creator_id: str,
    db: Session = Depends(get_db)
):
    """Get creator statistics"""
    contents = db.query(Content).filter(
        Content.creator_id == creator_id,
        Content.status == "published"
    ).all()

    if not contents:
        raise HTTPException(404, "Creator not found")

    total_contents = len(contents)
    total_downloads = sum(c.downloads for c in contents)
    total_views = sum(c.views for c in contents)
    avg_rating = sum(c.avg_rating for c in contents) / total_contents if total_contents > 0 else 0.0

    # Content breakdown
    content_breakdown = {}
    for content in contents:
        cat = content.category.value
        content_breakdown[cat] = content_breakdown.get(cat, 0) + 1

    return CreatorStats(
        creator_id=creator_id,
        creator_name=contents[0].creator_name,
        total_contents=total_contents,
        total_downloads=total_downloads,
        total_views=total_views,
        avg_rating=avg_rating,
        impact_score=0.0,  # TODO: Calculate impact score
        content_breakdown=content_breakdown
    )

# ============= HEALTH CHECK =============

@app.get("/health")
async def health_check():
    """Health check endpoint"""
    return {
        "status": "healthy",
        "service": "content-service",
        "version": "1.0.0"
    }

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8002)
