"""
资产分配相关CRUD操作
"""
from typing import List, Optional, Tuple
from sqlalchemy.orm import Session
from sqlalchemy import and_, or_
from app.models.allocation import AssetAllocationOrder, AssetAllocationItem
from app.models.asset import Asset
from app.schemas.allocation import AllocationOrderCreate, AllocationOrderUpdate


class AllocationOrderCRUD:
    """分配单CRUD操作"""

    def get(self, db: Session, id: int) -> Optional[AssetAllocationOrder]:
        """根据ID获取分配单"""
        return db.query(AssetAllocationOrder).filter(
            AssetAllocationOrder.id == id
        ).first()

    def get_by_code(self, db: Session, order_code: str) -> Optional[AssetAllocationOrder]:
        """根据单号获取分配单"""
        return db.query(AssetAllocationOrder).filter(
            AssetAllocationOrder.order_code == order_code
        ).first()

    def get_multi(
        self,
        db: Session,
        skip: int = 0,
        limit: int = 20,
        order_type: Optional[str] = None,
        approval_status: Optional[str] = None,
        execute_status: Optional[str] = None,
        applicant_id: Optional[int] = None,
        target_organization_id: Optional[int] = None,
        keyword: Optional[str] = None
    ) -> Tuple[List[AssetAllocationOrder], int]:
        """获取分配单列表"""
        query = db.query(AssetAllocationOrder)

        # 筛选条件
        if order_type:
            query = query.filter(AssetAllocationOrder.order_type == order_type)
        if approval_status:
            query = query.filter(AssetAllocationOrder.approval_status == approval_status)
        if execute_status:
            query = query.filter(AssetAllocationOrder.execute_status == execute_status)
        if applicant_id:
            query = query.filter(AssetAllocationOrder.applicant_id == applicant_id)
        if target_organization_id:
            query = query.filter(AssetAllocationOrder.target_organization_id == target_organization_id)
        if keyword:
            query = query.filter(
                or_(
                    AssetAllocationOrder.order_code.like(f"%{keyword}%"),
                    AssetAllocationOrder.title.like(f"%{keyword}%")
                )
            )

        # 排序
        query = query.order_by(AssetAllocationOrder.created_at.desc())

        # 总数
        total = query.count()

        # 分页
        items = query.offset(skip).limit(limit).all()

        return items, total

    def create(
        self,
        db: Session,
        obj_in: AllocationOrderCreate,
        order_code: str,
        applicant_id: int
    ) -> AssetAllocationOrder:
        """创建分配单"""
        # 创建分配单
        db_obj = AssetAllocationOrder(
            order_code=order_code,
            order_type=obj_in.order_type,
            title=obj_in.title,
            source_organization_id=obj_in.source_organization_id,
            target_organization_id=obj_in.target_organization_id,
            applicant_id=applicant_id,
            expect_execute_date=obj_in.expect_execute_date,
            remark=obj_in.remark,
            created_by=applicant_id,
            approval_status="pending",
            execute_status="pending"
        )
        db.add(db_obj)
        db.commit()
        db.refresh(db_obj)

        # 创建分配单明细
        self._create_items(
            db=db,
            order_id=db_obj.id,
            asset_ids=obj_in.asset_ids,
            target_org_id=obj_in.target_organization_id
        )

        return db_obj

    def update(
        self,
        db: Session,
        db_obj: AssetAllocationOrder,
        obj_in: AllocationOrderUpdate,
        updater_id: int
    ) -> AssetAllocationOrder:
        """更新分配单"""
        update_data = obj_in.model_dump(exclude_unset=True)
        for field, value in update_data.items():
            setattr(db_obj, field, value)
        db_obj.updated_by = updater_id
        db.add(db_obj)
        db.commit()
        db.refresh(db_obj)
        return db_obj

    def approve(
        self,
        db: Session,
        db_obj: AssetAllocationOrder,
        approval_status: str,
        approver_id: int,
        approval_remark: Optional[str] = None
    ) -> AssetAllocationOrder:
        """审批分配单"""
        from datetime import datetime

        db_obj.approval_status = approval_status
        db_obj.approver_id = approver_id
        db_obj.approval_time = datetime.utcnow()
        db_obj.approval_remark = approval_remark

        # 如果审批通过，自动设置为可执行状态
        if approval_status == "approved":
            db_obj.execute_status = "pending"
        elif approval_status == "rejected":
            db_obj.execute_status = "cancelled"

        db.add(db_obj)
        db.commit()
        db.refresh(db_obj)
        return db_obj

    def execute(
        self,
        db: Session,
        db_obj: AssetAllocationOrder,
        executor_id: int
    ) -> AssetAllocationOrder:
        """执行分配单"""
        from datetime import datetime, date

        db_obj.execute_status = "completed"
        db_obj.actual_execute_date = date.today()
        db_obj.executor_id = executor_id

        db.add(db_obj)
        db.commit()
        db.refresh(db_obj)
        return db_obj

    def cancel(self, db: Session, db_obj: AssetAllocationOrder) -> AssetAllocationOrder:
        """取消分配单"""
        db_obj.approval_status = "cancelled"
        db_obj.execute_status = "cancelled"
        db.add(db_obj)
        db.commit()
        db.refresh(db_obj)
        return db_obj

    def delete(self, db: Session, id: int) -> bool:
        """删除分配单"""
        obj = self.get(db, id)
        if obj:
            db.delete(obj)
            db.commit()
            return True
        return False

    def get_statistics(
        self,
        db: Session,
        applicant_id: Optional[int] = None
    ) -> dict:
        """获取分配单统计信息"""
        query = db.query(AssetAllocationOrder)

        if applicant_id:
            query = query.filter(AssetAllocationOrder.applicant_id == applicant_id)

        total = query.count()
        pending = query.filter(AssetAllocationOrder.approval_status == "pending").count()
        approved = query.filter(AssetAllocationOrder.approval_status == "approved").count()
        rejected = query.filter(AssetAllocationOrder.approval_status == "rejected").count()
        executing = query.filter(AssetAllocationOrder.execute_status == "executing").count()
        completed = query.filter(AssetAllocationOrder.execute_status == "completed").count()

        return {
            "total": total,
            "pending": pending,
            "approved": approved,
            "rejected": rejected,
            "executing": executing,
            "completed": completed
        }

    def _create_items(
        self,
        db: Session,
        order_id: int,
        asset_ids: List[int],
        target_org_id: int
    ):
        """创建分配单明细"""
        # 查询资产信息
        assets = db.query(Asset).filter(Asset.id.in_(asset_ids)).all()

        for asset in assets:
            item = AssetAllocationItem(
                order_id=order_id,
                asset_id=asset.id,
                asset_code=asset.asset_code,
                asset_name=asset.asset_name,
                from_organization_id=asset.organization_id,
                to_organization_id=target_org_id,
                from_status=asset.status,
                to_status=self._get_target_status(asset.status),
                execute_status="pending"
            )
            db.add(item)

        db.commit()

    def _get_target_status(self, current_status: str) -> str:
        """根据当前状态获取目标状态"""
        status_map = {
            "in_stock": "transferring",
            "in_use": "transferring",
            "maintenance": "in_stock"
        }
        return status_map.get(current_status, "transferring")


class AllocationItemCRUD:
    """分配单明细CRUD操作"""

    def get_by_order(self, db: Session, order_id: int) -> List[AssetAllocationItem]:
        """根据分配单ID获取明细列表"""
        return db.query(AssetAllocationItem).filter(
            AssetAllocationItem.order_id == order_id
        ).order_by(AssetAllocationItem.id).all()

    def get_multi(
        self,
        db: Session,
        skip: int = 0,
        limit: int = 20,
        order_id: Optional[int] = None,
        execute_status: Optional[str] = None
    ) -> Tuple[List[AssetAllocationItem], int]:
        """获取明细列表"""
        query = db.query(AssetAllocationItem)

        if order_id:
            query = query.filter(AssetAllocationItem.order_id == order_id)
        if execute_status:
            query = query.filter(AssetAllocationItem.execute_status == execute_status)

        total = query.count()
        items = query.offset(skip).limit(limit).all()

        return items, total

    def update_execute_status(
        self,
        db: Session,
        item_id: int,
        execute_status: str,
        failure_reason: Optional[str] = None
    ) -> AssetAllocationItem:
        """更新明细执行状态"""
        from datetime import datetime

        item = db.query(AssetAllocationItem).filter(
            AssetAllocationItem.id == item_id
        ).first()

        if item:
            item.execute_status = execute_status
            item.execute_time = datetime.utcnow()
            item.failure_reason = failure_reason
            db.add(item)
            db.commit()
            db.refresh(item)

        return item

    def batch_update_execute_status(
        self,
        db: Session,
        order_id: int,
        execute_status: str
    ):
        """批量更新明细执行状态"""
        from datetime import datetime

        items = db.query(AssetAllocationItem).filter(
            and_(
                AssetAllocationItem.order_id == order_id,
                AssetAllocationItem.execute_status == "pending"
            )
        ).all()

        for item in items:
            item.execute_status = execute_status
            item.execute_time = datetime.utcnow()
            db.add(item)

        db.commit()


# 创建全局实例
allocation_order = AllocationOrderCRUD()
allocation_item = AllocationItemCRUD()
