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

from app.models.project import ClassificationTask, ClassificationProject, ClassificationResult, TaskStatus, ResultStatus
from app.models.metadata import DataColumn, DataTable, Database as MetaDatabase


def get_task(db: Session, task_id: int) -> Optional[ClassificationTask]:
    return db.query(ClassificationTask).filter(ClassificationTask.id == task_id).first()


def list_tasks(
    db: Session,
    project_id: Optional[int] = None,
    assignee_id: Optional[int] = None,
    status: Optional[str] = None,
    page: int = 1,
    page_size: int = 20,
) -> Tuple[List[ClassificationTask], int]:
    query = db.query(ClassificationTask)
    if project_id:
        query = query.filter(ClassificationTask.project_id == project_id)
    if assignee_id:
        query = query.filter(ClassificationTask.assignee_id == assignee_id)
    if status:
        query = query.filter(ClassificationTask.status == status)
    total = query.count()
    items = query.order_by(ClassificationTask.created_at.desc()).offset((page - 1) * page_size).limit(page_size).all()
    return items, total


def create_task(
    db: Session,
    project_id: int,
    name: str,
    assigner_id: int,
    assignee_id: int,
    target_type: str = "column",
    target_ids: Optional[str] = None,
    deadline: Optional[str] = None,
) -> ClassificationTask:
    from datetime import datetime
    db_obj = ClassificationTask(
        project_id=project_id,
        name=name,
        assigner_id=assigner_id,
        assignee_id=assignee_id,
        target_type=target_type,
        target_ids=target_ids,
        status=TaskStatus.PENDING.value,
        deadline=datetime.fromisoformat(deadline) if deadline else None,
    )
    db.add(db_obj)
    db.commit()
    db.refresh(db_obj)
    return db_obj


def update_task_status(db: Session, task: ClassificationTask, status: str) -> ClassificationTask:
    task.status = status
    if status == TaskStatus.COMPLETED.value:
        from datetime import datetime
        task.completed_at = datetime.utcnow()
    db.commit()
    db.refresh(task)
    return task


def assign_columns_to_task(db: Session, project_id: int, task_id: int, column_ids: List[int]) -> None:
    """Assign columns to a task by creating/updating classification results."""
    from app.services.project_service import list_results
    for col_id in column_ids:
        result = db.query(ClassificationResult).filter(
            ClassificationResult.project_id == project_id,
            ClassificationResult.column_id == col_id,
        ).first()
        if not result:
            result = ClassificationResult(
                project_id=project_id,
                column_id=col_id,
                status=ResultStatus.AUTO.value,
                source="auto",
                confidence=0.0,
            )
            db.add(result)
    db.commit()


def get_task_label_items(db: Session, project_id: int, keyword: Optional[str] = None) -> List[dict]:
    """Get all label items for a project (used in task labeling view)."""
    query = db.query(ClassificationResult).filter(ClassificationResult.project_id == project_id)
    results = query.all()

    items = []
    for r in results:
        col = r.column
        if not col:
            continue
        table = col.table
        database = table.database if table else None
        source = database.source if database else None

        items.append({
            "result_id": r.id,
            "column_id": col.id,
            "column_name": col.name,
            "data_type": col.data_type,
            "comment": col.comment,
            "table_name": table.name if table else None,
            "database_name": database.name if database else None,
            "source_name": source.name if source else None,
            "category_id": r.category_id,
            "category_name": r.category.name if r.category else None,
            "level_id": r.level_id,
            "level_name": r.level.name if r.level else None,
            "level_color": r.level.color if r.level else None,
            "source": r.source,
            "confidence": r.confidence,
            "status": r.status,
        })
    return items
