from datetime import datetime
from typing import Optional
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func
from loguru import logger

from app.models.material import Coil, MaterialTracking, CoilStatus
from app.services.message_parser import dispatcher


class MaterialService:

    @staticmethod
    async def get_coil(db: AsyncSession, coil_no: str) -> Optional[Coil]:
        result = await db.execute(select(Coil).where(Coil.coil_no == coil_no))
        return result.scalar_one_or_none()

    @staticmethod
    async def create_tracking(db: AsyncSession, coil: Coil, event_type: str,
                               position: str = None, **kwargs) -> MaterialTracking:
        tracking = MaterialTracking(
            coil_id=coil.id,
            coil_no=coil.coil_no,
            position=position,
            event_type=event_type,
            event_time=kwargs.get("event_time", datetime.now()),
            **{k: v for k, v in kwargs.items() if k != "event_time"},
        )
        db.add(tracking)
        await db.flush()
        return tracking

    @staticmethod
    async def update_coil_status(db: AsyncSession, coil: Coil, status: CoilStatus):
        coil.status = status
        await db.flush()


material_service = MaterialService()


# 注册L1报文处理器
@dispatcher.register("PC01")
async def handle_coil_entry(data: dict):
    """处理卷材入口报文"""
    from app.database import AsyncSessionLocal
    async with AsyncSessionLocal() as db:
        coil = await material_service.get_coil(db, data["coil_no"])
        if coil:
            await material_service.update_coil_status(db, coil, CoilStatus.ON_LINE)
            await material_service.create_tracking(
                db, coil, "entry", position="入口", **data
            )
            await db.commit()
            logger.info(f"卷材入线: {data['coil_no']}")


@dispatcher.register("PC02")
async def handle_coil_exit(data: dict):
    """处理卷材出口报文"""
    from app.database import AsyncSessionLocal
    async with AsyncSessionLocal() as db:
        coil = await material_service.get_coil(db, data["coil_no"])
        if coil:
            await material_service.update_coil_status(db, coil, CoilStatus.FINISHED)
            await material_service.create_tracking(
                db, coil, "exit", position="出口", **data
            )
            await db.commit()
            logger.info(f"卷材出线: {data['coil_no']}")
