from datetime import datetime

from sqlalchemy import inspect, select
from sqlalchemy.orm import Session

from app.models.operations import PurchaseOrderItem, PurchaseOrderSalesOrderLink
from app.models.planning import MaterialDemand
from app.models.sales import SalesOrder, SalesOrderItem


def ensure_purchase_order_sales_link_table(db: Session) -> None:
    """Keep the explicit purchase-sales link table available when DB patches lag behind code."""
    if db.info.get("purchase_order_sales_link_table_ensured"):
        return
    bind = db.connection()
    inspector = inspect(bind)
    existed = inspector.has_table(PurchaseOrderSalesOrderLink.__tablename__)
    PurchaseOrderSalesOrderLink.__table__.create(bind=bind, checkfirst=True)
    if not existed:
        backfill_purchase_order_sales_links(db)
    db.info["purchase_order_sales_link_table_ensured"] = True


def backfill_purchase_order_sales_links(db: Session) -> None:
    existing_pairs = {
        (int(row.purchase_order_id), int(row.sales_order_id))
        for row in db.execute(
            select(PurchaseOrderSalesOrderLink.purchase_order_id, PurchaseOrderSalesOrderLink.sales_order_id)
        )
    }
    inferred_rows = db.execute(
        select(
            PurchaseOrderItem.purchase_order_id.label("purchase_order_id"),
            SalesOrder.id.label("sales_order_id"),
        )
        .join(MaterialDemand, MaterialDemand.id == PurchaseOrderItem.source_demand_id)
        .join(SalesOrderItem, SalesOrderItem.id == MaterialDemand.sales_order_item_id)
        .join(SalesOrder, SalesOrder.id == SalesOrderItem.sales_order_id)
        .distinct()
    ).all()
    now = datetime.now()
    for row in inferred_rows:
        pair = (int(row.purchase_order_id), int(row.sales_order_id))
        if pair in existing_pairs:
            continue
        db.add(
            PurchaseOrderSalesOrderLink(
                purchase_order_id=pair[0],
                sales_order_id=pair[1],
                created_at=now,
                updated_at=now,
            )
        )
        existing_pairs.add(pair)
