from typing import Optional, List, Tuple
from sqlalchemy.orm import Session
from fastapi import HTTPException, status

from app.models.project import ClassificationProject, ClassificationTask, ClassificationResult
from app.models.classification import Category, DataLevel
from app.models.metadata import DataColumn, DataTable, Database as MetaDatabase


def get_project(db: Session, project_id: int) -> Optional[ClassificationProject]:
    return db.query(ClassificationProject).filter(ClassificationProject.id == project_id).first()


def list_projects(
    db: Session, keyword: Optional[str] = None, page: int = 1, page_size: int = 20, created_by: Optional[int] = None
) -> Tuple[List[ClassificationProject], int]:
    query = db.query(ClassificationProject)
    if keyword:
        query = query.filter(ClassificationProject.name.contains(keyword))
    if created_by:
        query = query.filter(ClassificationProject.created_by == created_by)
    total = query.count()
    items = query.order_by(ClassificationProject.created_at.desc()).offset((page - 1) * page_size).limit(page_size).all()
    return items, total


def create_project(db: Session, name: str, template_id: int, created_by: int, **kwargs) -> ClassificationProject:
    db_obj = ClassificationProject(
        name=name,
        template_id=template_id,
        created_by=created_by,
        **kwargs,
    )
    db.add(db_obj)
    db.commit()
    db.refresh(db_obj)
    return db_obj


def update_project(db: Session, db_obj: ClassificationProject, **kwargs) -> ClassificationProject:
    for k, v in kwargs.items():
        if v is not None:
            setattr(db_obj, k, v)
    db.commit()
    db.refresh(db_obj)
    return db_obj


def delete_project(db: Session, project_id: int) -> None:
    db_obj = get_project(db, project_id)
    if not db_obj:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="项目不存在")
    db.delete(db_obj)
    db.commit()


def get_project_stats(db: Session, project_id: int) -> dict:
    total = db.query(ClassificationResult).filter(ClassificationResult.project_id == project_id).count()
    auto_count = db.query(ClassificationResult).filter(
        ClassificationResult.project_id == project_id,
        ClassificationResult.source == "auto",
    ).count()
    manual_count = db.query(ClassificationResult).filter(
        ClassificationResult.project_id == project_id,
        ClassificationResult.source == "manual",
    ).count()
    reviewed_count = db.query(ClassificationResult).filter(
        ClassificationResult.project_id == project_id,
        ClassificationResult.status == "reviewed",
    ).count()
    return {
        "total": total,
        "auto": auto_count,
        "manual": manual_count,
        "reviewed": reviewed_count,
    }


def list_results(
    db: Session,
    project_id: Optional[int] = None,
    table_id: Optional[int] = None,
    status: Optional[str] = None,
    keyword: Optional[str] = None,
    page: int = 1,
    page_size: int = 50,
    project_ids: Optional[List[int]] = None,
) -> Tuple[List[ClassificationResult], int]:
    query = db.query(ClassificationResult)
    if project_id:
        query = query.filter(ClassificationResult.project_id == project_id)
    if project_ids:
        query = query.filter(ClassificationResult.project_id.in_(project_ids))
    if table_id:
        query = query.join(DataColumn).filter(DataColumn.table_id == table_id)
    if status:
        query = query.filter(ClassificationResult.status == status)
    if keyword:
        query = query.join(DataColumn).filter(
            (DataColumn.name.contains(keyword)) | (DataColumn.comment.contains(keyword))
        )
    total = query.count()
    items = query.offset((page - 1) * page_size).limit(page_size).all()
    return items, total


def update_result_label(
    db: Session,
    result_id: int,
    category_id: int,
    level_id: int,
    labeler_id: int,
) -> ClassificationResult:
    result = db.query(ClassificationResult).filter(ClassificationResult.id == result_id).first()
    if not result:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="结果不存在")
    result.category_id = category_id
    result.level_id = level_id
    result.labeler_id = labeler_id
    result.source = "manual"
    result.status = "manual"
    result.label_time = __import__('datetime').datetime.utcnow()
    db.commit()
    db.refresh(result)
    return result
