"""
Classroom API - Feedback Endpoints.

Endpoints fuer Lehrer-Feedback (Feature Request Tracking).
"""

from uuid import uuid4
from typing import Dict, List, Optional, Any
from datetime import datetime
import logging

from fastapi import APIRouter, HTTPException, Query
from pydantic import BaseModel, Field

from .shared import init_db_if_needed, DB_ENABLED, logger

try:
    from classroom_engine.database import SessionLocal
    from classroom_engine.repository import TeacherFeedbackRepository
except ImportError:
    pass

router = APIRouter(tags=["Feedback"])

# In-Memory Storage (Fallback)
_feedback: Dict[str, dict] = {}


# === Pydantic Models ===

class CreateFeedbackRequest(BaseModel):
    """Request zum Erstellen von Feedback."""
    teacher_id: str
    session_id: Optional[str] = None
    category: str = Field(..., description="bug, feature, usability, content, other")
    title: str = Field(..., min_length=1, max_length=200)
    description: str = Field(..., min_length=10, max_length=5000)
    priority: str = Field("medium", description="low, medium, high, critical")
    context_data: Optional[Dict[str, Any]] = None


class FeedbackResponse(BaseModel):
    """Response fuer ein Feedback."""
    feedback_id: str
    teacher_id: str
    session_id: Optional[str]
    category: str
    title: str
    description: str
    priority: str
    status: str
    context_data: Optional[Dict[str, Any]]
    admin_notes: Optional[str]
    created_at: str
    updated_at: Optional[str]


class FeedbackListResponse(BaseModel):
    """Response fuer Feedback-Liste."""
    feedback: List[FeedbackResponse]
    total_count: int


class FeedbackStatsResponse(BaseModel):
    """Response fuer Feedback-Statistiken."""
    total: int
    by_category: Dict[str, int]
    by_status: Dict[str, int]
    by_priority: Dict[str, int]


# === Endpoints ===

@router.post("/feedback", response_model=FeedbackResponse, status_code=201)
async def create_feedback(request: CreateFeedbackRequest) -> FeedbackResponse:
    """Erstellt ein neues Feedback."""
    init_db_if_needed()

    valid_categories = ["bug", "feature", "usability", "content", "other"]
    if request.category not in valid_categories:
        raise HTTPException(status_code=400, detail=f"Invalid category. Must be one of: {valid_categories}")

    valid_priorities = ["low", "medium", "high", "critical"]
    if request.priority not in valid_priorities:
        raise HTTPException(status_code=400, detail=f"Invalid priority. Must be one of: {valid_priorities}")

    feedback_id = str(uuid4())
    now = datetime.utcnow()

    feedback_data = {
        "feedback_id": feedback_id,
        "teacher_id": request.teacher_id,
        "session_id": request.session_id,
        "category": request.category,
        "title": request.title,
        "description": request.description,
        "priority": request.priority,
        "status": "open",
        "context_data": request.context_data,
        "admin_notes": None,
        "created_at": now.isoformat(),
        "updated_at": None,
    }

    if DB_ENABLED:
        try:
            db = SessionLocal()
            repo = TeacherFeedbackRepository(db)
            repo.create(feedback_data)
            db.close()
        except Exception as e:
            logger.warning(f"DB persist failed for feedback: {e}")

    _feedback[feedback_id] = feedback_data
    return FeedbackResponse(**feedback_data)


@router.get("/feedback", response_model=FeedbackListResponse)
async def list_feedback(
    teacher_id: Optional[str] = Query(None),
    category: Optional[str] = Query(None),
    status: Optional[str] = Query(None),
    priority: Optional[str] = Query(None),
    limit: int = Query(50, ge=1, le=100),
    offset: int = Query(0, ge=0)
) -> FeedbackListResponse:
    """Listet Feedback (optional gefiltert)."""
    init_db_if_needed()

    feedback_list = []

    if DB_ENABLED:
        try:
            db = SessionLocal()
            repo = TeacherFeedbackRepository(db)
            db_feedback = repo.get_all(
                teacher_id=teacher_id,
                category=category,
                status=status,
                priority=priority,
                limit=limit,
                offset=offset
            )

            for fb in db_feedback:
                feedback_list.append(FeedbackResponse(**fb))

            total = repo.count(teacher_id=teacher_id, category=category, status=status)
            db.close()
            return FeedbackListResponse(feedback=feedback_list, total_count=total)
        except Exception as e:
            logger.warning(f"DB read failed for feedback: {e}")

    # Fallback auf Memory
    for fb in _feedback.values():
        if teacher_id and fb["teacher_id"] != teacher_id:
            continue
        if category and fb["category"] != category:
            continue
        if status and fb["status"] != status:
            continue
        if priority and fb["priority"] != priority:
            continue
        feedback_list.append(FeedbackResponse(**fb))

    total = len(feedback_list)
    feedback_list = feedback_list[offset:offset + limit]

    return FeedbackListResponse(feedback=feedback_list, total_count=total)


@router.get("/feedback/stats", response_model=FeedbackStatsResponse)
async def get_feedback_stats() -> FeedbackStatsResponse:
    """Gibt Feedback-Statistiken zurueck."""
    init_db_if_needed()

    if DB_ENABLED:
        try:
            db = SessionLocal()
            repo = TeacherFeedbackRepository(db)
            stats = repo.get_stats()
            db.close()
            return FeedbackStatsResponse(**stats)
        except Exception as e:
            logger.warning(f"DB read failed for feedback stats: {e}")

    # Fallback auf Memory
    by_category: Dict[str, int] = {}
    by_status: Dict[str, int] = {}
    by_priority: Dict[str, int] = {}

    for fb in _feedback.values():
        cat = fb["category"]
        by_category[cat] = by_category.get(cat, 0) + 1

        st = fb["status"]
        by_status[st] = by_status.get(st, 0) + 1

        pr = fb["priority"]
        by_priority[pr] = by_priority.get(pr, 0) + 1

    return FeedbackStatsResponse(
        total=len(_feedback),
        by_category=by_category,
        by_status=by_status,
        by_priority=by_priority,
    )


@router.get("/feedback/{feedback_id}")
async def get_feedback(feedback_id: str) -> FeedbackResponse:
    """Ruft ein einzelnes Feedback ab."""
    init_db_if_needed()

    if feedback_id in _feedback:
        return FeedbackResponse(**_feedback[feedback_id])

    if DB_ENABLED:
        try:
            db = SessionLocal()
            repo = TeacherFeedbackRepository(db)
            fb = repo.get_by_id(feedback_id)
            db.close()
            if fb:
                return FeedbackResponse(**fb)
        except Exception as e:
            logger.warning(f"DB read failed: {e}")

    raise HTTPException(status_code=404, detail="Feedback nicht gefunden")


@router.put("/feedback/{feedback_id}/status")
async def update_feedback_status(
    feedback_id: str,
    status: str = Query(..., description="open, in_progress, resolved, closed, wont_fix")
) -> FeedbackResponse:
    """Aktualisiert den Status eines Feedbacks."""
    init_db_if_needed()

    valid_statuses = ["open", "in_progress", "resolved", "closed", "wont_fix"]
    if status not in valid_statuses:
        raise HTTPException(status_code=400, detail=f"Invalid status. Must be one of: {valid_statuses}")

    feedback_data = _feedback.get(feedback_id)

    if not feedback_data and DB_ENABLED:
        try:
            db = SessionLocal()
            repo = TeacherFeedbackRepository(db)
            feedback_data = repo.get_by_id(feedback_id)
            db.close()
        except Exception as e:
            logger.warning(f"DB read failed: {e}")

    if not feedback_data:
        raise HTTPException(status_code=404, detail="Feedback nicht gefunden")

    feedback_data["status"] = status
    feedback_data["updated_at"] = datetime.utcnow().isoformat()

    if DB_ENABLED:
        try:
            db = SessionLocal()
            repo = TeacherFeedbackRepository(db)
            repo.update_status(feedback_id, status)
            db.close()
        except Exception as e:
            logger.warning(f"DB update failed: {e}")

    _feedback[feedback_id] = feedback_data
    return FeedbackResponse(**feedback_data)
