from fastapi import APIRouter, Depends, Query
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func, and_, desc, asc
from config.database import get_db
from src.models.user import User
from src.models.project import Project
from src.schemas.project import (
    ProjectCreate,
    ProjectUpdate,
    ProjectResponse,
    ProjectListResponse,
)
from src.middleware.auth import (
    get_current_user,
    require_market_or_admin,
)
from src.dependencies import get_project_or_404
from typing import Optional
from datetime import date
from decimal import Decimal

router = APIRouter(prefix="/projects", tags=["项目管理"])


@router.get("", response_model=dict)
async def get_projects(
    page: int = Query(1, ge=1),
    page_size: int = Query(10, ge=1, le=100),
    project_no: Optional[str] = None,
    engineering_type: Optional[str] = None,
    project_department: Optional[str] = None,
    signing_date_start: Optional[date] = None,
    signing_date_end: Optional[date] = None,
    contract_amount_min: Optional[Decimal] = None,
    contract_amount_max: Optional[Decimal] = None,
    keyword: Optional[str] = None,
    sort_by: Optional[str] = None,
    sort_order: Optional[str] = Query(None, pattern="^(asc|desc)$"),
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    query = select(Project)

    conditions = []
    if project_no:
        conditions.append(Project.project_no == project_no)
    if engineering_type:
        conditions.append(Project.engineering_type == engineering_type)
    if project_department:
        conditions.append(Project.project_department == project_department)
    if signing_date_start:
        conditions.append(Project.signing_date >= signing_date_start)
    if signing_date_end:
        conditions.append(Project.signing_date <= signing_date_end)
    if contract_amount_min:
        conditions.append(Project.contract_amount >= contract_amount_min)
    if contract_amount_max:
        conditions.append(Project.contract_amount <= contract_amount_max)
    if keyword:
        conditions.append(
            (Project.name.contains(keyword)) |
            (Project.owner_unit.contains(keyword))
        )

    if conditions:
        query = query.where(and_(*conditions))

    if sort_by:
        sort_column = getattr(Project, sort_by, None)
        if sort_column:
            order = desc if sort_order == "desc" else asc
            query = query.order_by(order(sort_column))
    else:
        query = query.order_by(Project.created_at.desc())

    total_query = select(func.count()).select_from(query.subquery())
    total_result = await db.execute(total_query)
    total = total_result.scalar()

    query = query.offset((page - 1) * page_size).limit(page_size)
    result = await db.execute(query)
    projects = result.scalars().all()

    project_data = []
    for p in projects:
        creator_result = await db.execute(
            select(User.real_name).where(User.id == p.created_by)
        )
        creator_name = creator_result.scalar_one_or_none()
        p_dict = ProjectResponse.model_validate(p).model_dump()
        p_dict["created_by_name"] = creator_name
        project_data.append(p_dict)

    return {
        "success": True,
        "message": "获取成功",
        "data": {
            "items": project_data,
            "total": total,
            "page": page,
            "page_size": page_size,
        },
        "error_code": None,
    }


@router.get("/{project_id}", response_model=dict)
async def get_project(
    project: Project = Depends(get_project_or_404),
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    result = await db.execute(
        select(User.real_name).where(User.id == project.created_by)
    )
    creator_name = result.scalar_one_or_none()

    project_dict = ProjectResponse.model_validate(project).model_dump()
    project_dict["created_by_name"] = creator_name

    return {
        "success": True,
        "message": "获取成功",
        "data": project_dict,
        "error_code": None,
    }


@router.post("", response_model=dict)
async def create_project(
    project_data: ProjectCreate,
    current_user: User = Depends(require_market_or_admin),
    db: AsyncSession = Depends(get_db),
):
    result = await db.execute(
        select(Project).where(Project.project_no == project_data.project_no)
    )
    if result.scalar_one_or_none():
        return {
            "success": False,
            "message": "项目编号已存在",
            "data": None,
            "error_code": "2002",
        }

    project = Project(
        **project_data.model_dump(),
        created_by=current_user.id,
    )
    db.add(project)
    await db.commit()
    await db.refresh(project)

    return {
        "success": True,
        "message": "项目创建成功",
        "data": ProjectResponse.model_validate(project),
        "error_code": None,
    }


@router.put("/{project_id}", response_model=dict)
async def update_project(
    project_id: int,
    project_data: ProjectUpdate,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    result = await db.execute(select(Project).where(Project.id == project_id))
    project = result.scalar_one_or_none()

    if not project:
        return {
            "success": False,
            "message": "项目不存在",
            "data": None,
            "error_code": "2001",
        }

    if current_user.role == "market" and project.created_by != current_user.id:
        return {
            "success": False,
            "message": "无权修改此项目",
            "data": None,
            "error_code": "3001",
        }

    update_data = project_data.model_dump(exclude_unset=True)
    for field, value in update_data.items():
        setattr(project, field, value)

    await db.commit()
    await db.refresh(project)

    return {
        "success": True,
        "message": "项目更新成功",
        "data": ProjectResponse.model_validate(project),
        "error_code": None,
    }


@router.delete("/{project_id}", response_model=dict)
async def delete_project(
    project_id: int,
    current_user: User = Depends(require_market_or_admin),
    db: AsyncSession = Depends(get_db),
):
    result = await db.execute(select(Project).where(Project.id == project_id))
    project = result.scalar_one_or_none()

    if not project:
        return {
            "success": False,
            "message": "项目不存在",
            "data": None,
            "error_code": "2001",
        }

    if current_user.role == "market" and project.created_by != current_user.id:
        return {
            "success": False,
            "message": "无权删除此项目",
            "data": None,
            "error_code": "3001",
        }

    await db.delete(project)
    await db.commit()

    return {
        "success": True,
        "message": "项目删除成功",
        "data": None,
        "error_code": None,
    }


@router.get("/statistics/basic", response_model=dict)
async def get_statistics(
    engineering_type: Optional[str] = None,
    signing_date_start: Optional[date] = None,
    signing_date_end: Optional[date] = None,
    contract_amount_min: Optional[Decimal] = None,
    contract_amount_max: Optional[Decimal] = None,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    query = select(Project)

    conditions = []
    if engineering_type:
        conditions.append(Project.engineering_type == engineering_type)
    if signing_date_start:
        conditions.append(Project.signing_date >= signing_date_start)
    if signing_date_end:
        conditions.append(Project.signing_date <= signing_date_end)
    if contract_amount_min:
        conditions.append(Project.contract_amount >= contract_amount_min)
    if contract_amount_max:
        conditions.append(Project.contract_amount <= contract_amount_max)

    if conditions:
        query = query.where(and_(*conditions))

    result = await db.execute(query)
    projects = result.scalars().all()

    total_count = len(projects)
    total_contract_amount = sum(
        p.contract_amount or Decimal(0) for p in projects
    )
    total_receipt_amount = sum(
        p.actual_receipt_amount or Decimal(0) for p in projects
    )
    total_payment_amount = sum(
        p.actual_payment_amount or Decimal(0) for p in projects
    )

    avg_receipt_rate = 0
    if total_contract_amount > 0:
        avg_receipt_rate = (
            (total_receipt_amount / total_contract_amount) * 100
        )

    avg_payment_rate = 0
    total_payable = sum(p.payable_amount or Decimal(0) for p in projects)
    if total_payable > 0:
        avg_payment_rate = (
            (total_payment_amount / total_payable) * 100
        )

    avg_progress = 0
    if total_count > 0:
        avg_progress = sum(
            p.cumulative_progress or Decimal(0) for p in projects
        ) / total_count

    return {
        "success": True,
        "message": "统计成功",
        "data": {
            "total_count": total_count,
            "total_contract_amount": float(total_contract_amount),
            "total_receipt_amount": float(total_receipt_amount),
            "total_payment_amount": float(total_payment_amount),
            "avg_receipt_completion_rate": float(avg_receipt_rate),
            "avg_payment_completion_rate": float(avg_payment_rate),
            "avg_cumulative_progress": float(avg_progress),
        },
        "error_code": None,
    }


@router.get("/statistics/group", response_model=dict)
async def get_group_statistics(
    group_by: str = Query(..., pattern="^(engineering_type|project_department)$"),
    signing_date_start: Optional[date] = None,
    signing_date_end: Optional[date] = None,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    query = select(Project)

    if signing_date_start:
        query = query.where(Project.signing_date >= signing_date_start)
    if signing_date_end:
        query = query.where(Project.signing_date <= signing_date_end)

    result = await db.execute(query)
    projects = result.scalars().all()

    groups = {}
    for p in projects:
        group_value = getattr(p, group_by)
        if group_value not in groups:
            groups[group_value] = {
                "count": 0,
                "total_contract_amount": Decimal(0),
                "total_receipt_amount": Decimal(0),
                "total_payment_amount": Decimal(0),
            }
        groups[group_value]["count"] += 1
        groups[group_value]["total_contract_amount"] += p.contract_amount or Decimal(0)
        groups[group_value]["total_receipt_amount"] += p.actual_receipt_amount or Decimal(0)
        groups[group_value]["total_payment_amount"] += p.actual_payment_amount or Decimal(0)

    result_list = []
    for key, value in groups.items():
        if group_by == "engineering_type":
            item = {"engineering_type": key}
        else:
            item = {"project_department": key}
        item.update({
            "count": value["count"],
            "total_contract_amount": float(value["total_contract_amount"]),
            "total_receipt_amount": float(value["total_receipt_amount"]),
            "total_payment_amount": float(value["total_payment_amount"]),
        })
        result_list.append(item)

    return {
        "success": True,
        "message": "统计成功",
        "data": result_list,
        "error_code": None,
    }


@router.get("/statistics/timeline", response_model=dict)
async def get_timeline_statistics(
    time_field: str = Query(..., pattern="^(signing_date|start_date|planned_end_date)$"),
    group_by: str = Query("month", pattern="^(day|month|year)$"),
    engineering_type: Optional[str] = None,
    start_date: Optional[date] = None,
    end_date: Optional[date] = None,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    query = select(Project)

    if engineering_type:
        query = query.where(Project.engineering_type == engineering_type)
    if start_date:
        date_column = getattr(Project, time_field)
        query = query.where(date_column >= start_date)
    if end_date:
        date_column = getattr(Project, time_field)
        query = query.where(date_column <= end_date)

    result = await db.execute(query)
    projects = result.scalars().all()

    groups = {}
    for p in projects:
        date_value = getattr(p, time_field)
        if not date_value:
            continue

        if group_by == "day":
            key = date_value.strftime("%Y-%m-%d")
        elif group_by == "month":
            key = date_value.strftime("%Y-%m")
        else:
            key = str(date_value.year)

        if key not in groups:
            groups[key] = {"count": 0, "total_contract_amount": Decimal(0)}
        groups[key]["count"] += 1
        groups[key]["total_contract_amount"] += p.contract_amount or Decimal(0)

    result_list = []
    for key in sorted(groups.keys()):
        value = groups[key]
        if group_by == "day":
            item = {"day": key}
        elif group_by == "month":
            item = {"month": key}
        else:
            item = {"year": key}
        item.update({
            "count": value["count"],
            "total_contract_amount": float(value["total_contract_amount"]),
        })
        result_list.append(item)

    return {
        "success": True,
        "message": "统计成功",
        "data": result_list,
        "error_code": None,
    }
