"""
维修管理业务服务层
"""
from typing import List, Optional, Dict, Any
from sqlalchemy.orm import Session, selectinload
from app.crud.maintenance import maintenance_record
from app.crud.asset import asset
from app.schemas.maintenance import (
    MaintenanceRecordCreate,
    MaintenanceRecordUpdate,
    MaintenanceRecordStart,
    MaintenanceRecordComplete
)
from app.core.exceptions import NotFoundException, BusinessException


class MaintenanceService:
    """维修管理服务类"""

    async def get_record(
        self,
        db: Session,
        record_id: int
    ) -> Dict[str, Any]:
        """获取维修记录详情"""
        # 使用selectinload预加载关联数据，避免N+1查询
        from app.models.maintenance import MaintenanceRecord
        from app.models.asset import Asset
        from app.models.user import User
        from app.models.brand_supplier import Supplier

        obj = db.query(
            MaintenanceRecord
        ).options(
            selectinload(MaintenanceRecord.asset.of_type(Asset)),
            selectinload(MaintenanceRecord.report_user.of_type(User)),
            selectinload(MaintenanceRecord.maintenance_user.of_type(User)),
            selectinload(MaintenanceRecord.vendor.of_type(Supplier))
        ).filter(
            MaintenanceRecord.id == record_id
        ).first()

        if not obj:
            raise NotFoundException("维修记录")

        return self._load_relations(db, obj)

    def get_records(
        self,
        db: Session,
        skip: int = 0,
        limit: int = 20,
        asset_id: Optional[int] = None,
        status: Optional[str] = None,
        fault_type: Optional[str] = None,
        priority: Optional[str] = None,
        maintenance_type: Optional[str] = None,
        keyword: Optional[str] = None
    ) -> tuple:
        """获取维修记录列表"""
        items, total = maintenance_record.get_multi(
            db=db,
            skip=skip,
            limit=limit,
            asset_id=asset_id,
            status=status,
            fault_type=fault_type,
            priority=priority,
            maintenance_type=maintenance_type,
            keyword=keyword
        )

        # 加载关联信息
        items_with_relations = [self._load_relations(db, item) for item in items]

        return items_with_relations, total

    async def create_record(
        self,
        db: Session,
        obj_in: MaintenanceRecordCreate,
        report_user_id: int,
        creator_id: int
    ):
        """创建维修记录"""
        # 验证资产存在
        asset_obj = asset.get(db, obj_in.asset_id)
        if not asset_obj:
            raise NotFoundException("资产")

        # 生成维修单号
        record_code = await self._generate_record_code(db)

        # 创建维修记录
        db_obj = maintenance_record.create(
            db=db,
            obj_in=obj_in,
            record_code=record_code,
            asset_code=asset_obj.asset_code,
            report_user_id=report_user_id,
            creator_id=creator_id
        )

        # 如果资产状态不是维修中，则更新状态
        if asset_obj.status != "maintenance":
            from app.services.asset_service import asset_service
            from app.schemas.asset import AssetStatusTransition

            try:
                await asset_service.change_asset_status(
                    db=db,
                    asset_id=asset_obj.id,
                    status_transition=AssetStatusTransition(
                        new_status="maintenance",
                        remark=f"报修: {record_code}"
                    ),
                    operator_id=report_user_id
                )
            except Exception as e:
                # 状态更新失败不影响维修记录创建
                pass

        return self._load_relations(db, db_obj)

    def update_record(
        self,
        db: Session,
        record_id: int,
        obj_in: MaintenanceRecordUpdate,
        updater_id: int
    ):
        """更新维修记录"""
        db_obj = maintenance_record.get(db, record_id)
        if not db_obj:
            raise NotFoundException("维修记录")

        # 已完成的维修记录不能更新
        if db_obj.status == "completed":
            raise BusinessException("已完成的维修记录不能更新")

        return maintenance_record.update(db, db_obj, obj_in, updater_id)

    async def start_maintenance(
        self,
        db: Session,
        record_id: int,
        start_in: MaintenanceRecordStart,
        maintenance_user_id: int
    ):
        """开始维修"""
        db_obj = maintenance_record.get(db, record_id)
        if not db_obj:
            raise NotFoundException("维修记录")

        # 检查状态
        if db_obj.status != "pending":
            raise BusinessException("只有待处理状态的维修记录可以开始维修")

        # 验证维修类型
        if start_in.maintenance_type == "vendor_repair" and not start_in.vendor_id:
            raise BusinessException("外部维修必须指定维修供应商")

        # 开始维修
        db_obj = maintenance_record.start_maintenance(
            db=db,
            db_obj=db_obj,
            maintenance_type=start_in.maintenance_type,
            maintenance_user_id=maintenance_user_id,
            vendor_id=start_in.vendor_id
        )

        return self._load_relations(db, db_obj)

    async def complete_maintenance(
        self,
        db: Session,
        record_id: int,
        complete_in: MaintenanceRecordComplete,
        maintenance_user_id: int
    ):
        """完成维修"""
        db_obj = maintenance_record.get(db, record_id)
        if not db_obj:
            raise NotFoundException("维修记录")

        # 检查状态
        if db_obj.status != "in_progress":
            raise BusinessException("只有维修中的记录可以完成")

        # 完成维修
        db_obj = maintenance_record.complete_maintenance(
            db=db,
            db_obj=db_obj,
            maintenance_result=complete_in.maintenance_result,
            maintenance_cost=complete_in.maintenance_cost,
            replaced_parts=complete_in.replaced_parts,
            images=complete_in.images
        )

        # 恢复资产状态
        from app.services.asset_service import asset_service
        from app.schemas.asset import AssetStatusTransition

        try:
            await asset_service.change_asset_status(
                db=db,
                asset_id=db_obj.asset_id,
                status_transition=AssetStatusTransition(
                    new_status=complete_in.asset_status,
                    remark=f"维修完成: {db_obj.record_code}"
                ),
                operator_id=maintenance_user_id
            )
        except Exception as e:
            # 状态更新失败不影响维修记录完成
            pass

        return self._load_relations(db, db_obj)

    def cancel_maintenance(
        self,
        db: Session,
        record_id: int
    ):
        """取消维修"""
        db_obj = maintenance_record.get(db, record_id)
        if not db_obj:
            raise NotFoundException("维修记录")

        # 检查状态
        if db_obj.status == "completed":
            raise BusinessException("已完成的维修记录不能取消")

        # 取消维修
        db_obj = maintenance_record.cancel_maintenance(db, db_obj)

        # 恢复资产状态
        asset_obj = asset.get(db, db_obj.asset_id)
        if asset_obj and asset_obj.status == "maintenance":
            from app.services.asset_service import asset_service
            from app.schemas.asset import AssetStatusTransition

            try:
                # 根据维修前的状态恢复
                target_status = "in_stock"  # 默认恢复为库存中
                asset_service.change_asset_status(
                    db=db,
                    asset_id=asset_obj.id,
                    status_transition=AssetStatusTransition(
                        new_status=target_status,
                        remark=f"取消维修: {db_obj.record_code}"
                    ),
                    operator_id=db_obj.report_user_id or 0
                )
            except Exception as e:
                # 状态更新失败不影响维修记录取消
                pass

        return self._load_relations(db, db_obj)

    def delete_record(
        self,
        db: Session,
        record_id: int
    ) -> bool:
        """删除维修记录"""
        db_obj = maintenance_record.get(db, record_id)
        if not db_obj:
            raise NotFoundException("维修记录")

        # 只能删除待处理或已取消的记录
        if db_obj.status not in ["pending", "cancelled"]:
            raise BusinessException("只能删除待处理或已取消的维修记录")

        return maintenance_record.delete(db, record_id)

    def get_asset_records(
        self,
        db: Session,
        asset_id: int,
        skip: int = 0,
        limit: int = 50
    ) -> List:
        """获取资产的维修记录"""
        # 验证资产存在
        if not asset.get(db, asset_id):
            raise NotFoundException("资产")

        records = maintenance_record.get_by_asset(db, asset_id, skip, limit)
        return [self._load_relations(db, record) for record in records]

    def get_statistics(
        self,
        db: Session,
        asset_id: Optional[int] = None
    ) -> Dict[str, Any]:
        """获取维修统计信息"""
        return maintenance_record.get_statistics(db, asset_id)

    def _load_relations(
        self,
        db: Session,
        obj
    ) -> Dict[str, Any]:
        """加载维修记录关联信息"""
        from app.models.asset import Asset
        from app.models.user import User
        from app.models.brand_supplier import Supplier

        result = {
            "id": obj.id,
            "record_code": obj.record_code,
            "asset_id": obj.asset_id,
            "asset_code": obj.asset_code,
            "fault_description": obj.fault_description,
            "fault_type": obj.fault_type,
            "report_user_id": obj.report_user_id,
            "report_time": obj.report_time,
            "priority": obj.priority,
            "maintenance_type": obj.maintenance_type,
            "vendor_id": obj.vendor_id,
            "maintenance_cost": float(obj.maintenance_cost) if obj.maintenance_cost else None,
            "start_time": obj.start_time,
            "complete_time": obj.complete_time,
            "maintenance_user_id": obj.maintenance_user_id,
            "maintenance_result": obj.maintenance_result,
            "replaced_parts": obj.replaced_parts,
            "status": obj.status,
            "images": obj.images,
            "remark": obj.remark,
            "created_at": obj.created_at,
            "updated_at": obj.updated_at
        }

        # 加载资产信息
        if obj.asset_id:
            asset_obj = db.query(Asset).filter(Asset.id == obj.asset_id).first()
            if asset_obj:
                result["asset"] = {
                    "id": asset_obj.id,
                    "asset_code": asset_obj.asset_code,
                    "asset_name": asset_obj.asset_name,
                    "status": asset_obj.status
                }

        # 加载报修人信息
        if obj.report_user_id:
            report_user = db.query(User).filter(User.id == obj.report_user_id).first()
            if report_user:
                result["report_user"] = {
                    "id": report_user.id,
                    "real_name": report_user.real_name,
                    "username": report_user.username
                }

        # 加载维修人员信息
        if obj.maintenance_user_id:
            maintenance_user = db.query(User).filter(User.id == obj.maintenance_user_id).first()
            if maintenance_user:
                result["maintenance_user"] = {
                    "id": maintenance_user.id,
                    "real_name": maintenance_user.real_name,
                    "username": maintenance_user.username
                }

        # 加载供应商信息
        if obj.vendor_id:
            vendor = db.query(Supplier).filter(Supplier.id == obj.vendor_id).first()
            if vendor:
                result["vendor"] = {
                    "id": vendor.id,
                    "supplier_name": vendor.supplier_name,
                    "contact_person": vendor.contact_person,
                    "contact_phone": vendor.contact_phone
                }

        return result

    async def _generate_record_code(self, db: Session) -> str:
        """生成维修单号"""
        from datetime import datetime
        import random
        import string

        # 日期部分
        date_str = datetime.now().strftime("%Y%m%d")

        # 序号部分（4位随机数）
        sequence = "".join(random.choices(string.digits, k=4))

        # 组合单号: MT202501240001
        record_code = f"MT{date_str}{sequence}"

        # 检查是否重复，如果重复则重新生成
        while maintenance_record.get_by_code(db, record_code):
            sequence = "".join(random.choices(string.digits, k=4))
            record_code = f"MT{date_str}{sequence}"

        return record_code


# 创建全局实例
maintenance_service = MaintenanceService()
