"""Order service — order number generation and business logic."""
from datetime import datetime
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func, create_engine, update as sql_update
from sqlalchemy.orm import Session
from app.domains.orders.models import Order, OrderLine, OrderStatus
import logging

logger = logging.getLogger(__name__)


async def generate_order_number(db: AsyncSession) -> str:
    """Generate next sequential order number: SA-2026-XXXXX."""
    year = datetime.utcnow().year
    prefix = f"SA-{year}-"

    # Use MAX to find the highest existing sequence number this year.
    # COUNT-based approach breaks when orders are deleted (produces duplicates).
    result = await db.execute(
        select(func.max(Order.order_number)).where(Order.order_number.like(f"{prefix}%"))
    )
    max_num = result.scalar()
    if max_num:
        last_seq = int(max_num.split("-")[-1])
        return f"{prefix}{last_seq + 1:05d}"
    return f"{prefix}00001"


def check_order_completion(order_id: str) -> bool:
    """If all renderable lines are done, auto-advance order to completed.

    Called from Celery tasks (sync context).
    Returns True if the order was advanced to completed.
    """
    from app.config import settings as app_settings

    sync_url = app_settings.database_url.replace("+asyncpg", "")
    engine = create_engine(sync_url)

    try:
        with Session(engine) as session:
            # Get all lines that have an output type (i.e. renderable)
            lines = session.execute(
                select(OrderLine).where(
                    OrderLine.order_id == order_id,
                    OrderLine.output_type_id.isnot(None),
                )
            ).scalars().all()

            if not lines:
                return False

            # Check if all renderable lines are in a terminal state
            all_terminal = all(
                line.render_status in ("completed", "failed", "cancelled")
                for line in lines
            )

            if not all_terminal:
                return False

            # Check order is still in processing state
            order = session.execute(
                select(Order).where(Order.id == order_id)
            ).scalar_one_or_none()

            if order is None or order.status != OrderStatus.processing:
                return False

            # Auto-advance to completed
            now = datetime.utcnow()
            session.execute(
                sql_update(Order)
                .where(Order.id == order_id)
                .values(
                    status=OrderStatus.completed,
                    completed_at=now,
                    updated_at=now,
                )
            )
            session.commit()
            logger.info(f"Order {order_id} auto-advanced to completed (all {len(lines)} lines done)")

            # Notify order creator
            try:
                from app.domains.notifications.service import emit_notification_sync
                emit_notification_sync(
                    actor_user_id=None,
                    target_user_id=str(order.created_by),
                    action="order.completed",
                    entity_type="order",
                    entity_id=str(order_id),
                    details={"order_number": order.order_number},
                )
            except Exception:
                logger.exception("Failed to emit order.completed notification")

            return True

    finally:
        engine.dispose()
