import logging
from collections import defaultdict
from datetime import date
from decimal import Decimal
import json
from typing import Any, Dict, List, Optional

from fastapi import APIRouter, HTTPException, Query, Request
from pydantic import BaseModel, Field

from app.core.config import settings
from app.core.database import execute_insert, execute_query, execute_query_single, execute_update

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/economy", tags=["Economy"])


class BulkIdsRequest(BaseModel):
    ids: List[int] = Field(..., min_length=1)


class BulkUpdateRequest(BaseModel):
    ids: List[int] = Field(..., min_length=1)
    description: Optional[str] = None
    original_hours: Optional[float] = Field(None, gt=0)
    billable: Optional[bool] = None
    billing_method: Optional[str] = None


class BulkSoftDeleteRequest(BaseModel):
    ids: List[int] = Field(..., min_length=1)
    reason: Optional[str] = "Soft deleted from economy queue"


class BulkApproveRequest(BaseModel):
    ids: List[int] = Field(..., min_length=1)
    billable: Optional[bool] = None
    billing_method: Optional[str] = None


class BulkPrepaidRequest(BaseModel):
    ids: List[int] = Field(..., min_length=1)
    prepaid_card_id: int = Field(..., gt=0)


class BulkSendRequest(BaseModel):
    ids: List[int] = Field(..., min_length=1)


def _ensure_ids(ids: List[int]) -> List[int]:
    clean = sorted(set(int(i) for i in ids if int(i) > 0))
    if not clean:
        raise HTTPException(status_code=400, detail="No valid ids provided")
    return clean


@router.get("/time-queue")
async def list_hub_time_queue(
    customer_id: Optional[int] = Query(None, gt=0),
    status: Optional[str] = Query(None),
    billable: Optional[bool] = Query(None),
    q: Optional[str] = Query(None),
    limit: int = Query(500, ge=1, le=2000),
):
    """List non-billed Hub-created time entries for the economy queue."""
    try:
        conditions = [
            "t.vtiger_id IS NULL",
            "t.billed_via_thehub_id IS NULL",
            "t.status <> 'billed'",
        ]
        params: List[Any] = []

        if customer_id is not None:
            conditions.append("t.customer_id = %s")
            params.append(customer_id)

        if status:
            conditions.append("t.status = %s")
            params.append(status)

        if billable is not None:
            conditions.append("COALESCE(t.billable, true) = %s")
            params.append(billable)

        if q:
            conditions.append(
                "(" 
                "COALESCE(t.description, '') ILIKE %s OR "
                "COALESCE(cust.name, '') ILIKE %s OR "
                "COALESCE(c.title, s.titel, '') ILIKE %s"
                ")"
            )
            like = f"%{q}%"
            params.extend([like, like, like])

        where_sql = " AND ".join(conditions)

        query = f"""
            SELECT
                t.id,
                t.customer_id,
                cust.name AS customer_name,
                t.status,
                t.entry_status,
                t.billable,
                t.billing_method,
                t.prepaid_card_id,
                t.fixed_price_agreement_id,
                t.original_hours,
                t.approved_hours,
                t.rounded_to,
                t.worked_date,
                t.description,
                t.entry_type,
                t.kilde,
                t.case_id,
                t.sag_id,
                COALESCE(c.title, s.titel, 'No title') AS case_title,
                t.created_at,
                t.updated_at
            FROM tmodule_times t
            LEFT JOIN tmodule_customers cust ON cust.id = t.customer_id
            LEFT JOIN tmodule_cases c ON c.id = t.case_id
            LEFT JOIN sag_sager s ON s.id = t.sag_id
            WHERE {where_sql}
            ORDER BY COALESCE(t.worked_date, DATE(t.created_at)) DESC, t.id DESC
            LIMIT %s
        """
        params.append(limit)

        rows = execute_query(query, tuple(params))
        return {"items": rows, "count": len(rows)}
    except HTTPException:
        raise
    except Exception as e:
        logger.error("Failed listing economy time queue: %s", e)
        raise HTTPException(status_code=500, detail="Failed to list time queue")


@router.get("/time-queue/customers")
async def list_time_queue_customers():
    """List customers that currently have queue-relevant (not billed) Hub entries."""
    try:
        rows = execute_query(
            """
            SELECT
                t.customer_id,
                COALESCE(cust.name, CONCAT('Kunde #', t.customer_id::text)) AS customer_name,
                COUNT(*)::int AS open_count
            FROM tmodule_times t
            LEFT JOIN tmodule_customers cust ON cust.id = t.customer_id
            WHERE t.customer_id IS NOT NULL
              AND t.vtiger_id IS NULL
              AND t.billed_via_thehub_id IS NULL
                            AND t.status = 'pending'
            GROUP BY t.customer_id, cust.name
            ORDER BY COALESCE(cust.name, CONCAT('Kunde #', t.customer_id::text)) ASC
            """
        )
        return {"items": rows, "count": len(rows)}
    except Exception as e:
        logger.error("Failed listing time queue customers: %s", e)
        raise HTTPException(status_code=500, detail="Failed listing customer filter options")


@router.get("/time-queue/prepaid-cards")
async def list_prepaid_cards():
    try:
        cards = execute_query(
            """
            SELECT id, card_number, customer_id, purchased_hours AS total_hours, used_hours, remaining_hours, status, expires_at
            FROM tticket_prepaid_cards
            WHERE status IN ('active', 'depleted')
            ORDER BY remaining_hours DESC, id DESC
            """
        )
        return {"items": cards, "count": len(cards)}
    except Exception as e:
        logger.error("Failed listing prepaid cards: %s", e)
        raise HTTPException(status_code=500, detail="Failed to list prepaid cards")


@router.patch("/time-queue/bulk-update")
async def bulk_update_time_queue(payload: BulkUpdateRequest):
    ids = _ensure_ids(payload.ids)

    updates: List[str] = []
    values: List[Any] = []

    if payload.description is not None:
        updates.append("description = %s")
        values.append(payload.description)

    if payload.original_hours is not None:
        updates.append("original_hours = %s")
        values.append(payload.original_hours)

    if payload.billable is not None:
        updates.append("billable = %s")
        values.append(payload.billable)
        if payload.billable is False and payload.billing_method is None:
            updates.append("billing_method = 'internal'")

    if payload.billing_method is not None:
        updates.append("billing_method = %s")
        values.append(payload.billing_method)

    if not updates:
        raise HTTPException(status_code=400, detail="No update fields provided")

    try:
        placeholders = ",".join(["%s"] * len(ids))
        query = f"""
            UPDATE tmodule_times
            SET {", ".join(updates)}
            WHERE id IN ({placeholders})
              AND vtiger_id IS NULL
              AND billed_via_thehub_id IS NULL
              AND status <> 'billed'
        """
        execute_update(query, tuple(values + ids))
        return {"success": True, "updated": len(ids)}
    except Exception as e:
        logger.error("Failed bulk update: %s", e)
        raise HTTPException(status_code=500, detail="Failed bulk update")


@router.post("/time-queue/bulk-soft-delete")
async def bulk_soft_delete_time_queue(payload: BulkSoftDeleteRequest):
    ids = _ensure_ids(payload.ids)
    reason = (payload.reason or "Soft deleted from economy queue").strip()

    try:
        placeholders = ",".join(["%s"] * len(ids))
        execute_update(
            f"""
            UPDATE tmodule_times
            SET status = 'rejected',
                entry_status = 'kladde',
                approval_note = %s,
                updated_at = CURRENT_TIMESTAMP
            WHERE id IN ({placeholders})
              AND vtiger_id IS NULL
              AND billed_via_thehub_id IS NULL
              AND status <> 'billed'
            """,
            tuple([reason] + ids),
        )
        return {"success": True, "soft_deleted": len(ids)}
    except Exception as e:
        logger.error("Failed bulk soft delete: %s", e)
        raise HTTPException(status_code=500, detail="Failed bulk soft delete")


@router.post("/time-queue/bulk-approve")
async def bulk_approve_time_queue(payload: BulkApproveRequest):
    ids = _ensure_ids(payload.ids)

    try:
        set_parts = [
            "status = 'approved'",
            "entry_status = 'godkendt'",
            "approved_hours = COALESCE(approved_hours, original_hours)",
            "approved_at = CURRENT_TIMESTAMP",
            "updated_at = CURRENT_TIMESTAMP",
        ]
        params: List[Any] = []

        if payload.billable is not None:
            set_parts.append("billable = %s")
            params.append(payload.billable)

        if payload.billing_method is not None:
            set_parts.append("billing_method = %s")
            params.append(payload.billing_method)

        placeholders = ",".join(["%s"] * len(ids))
        query = f"""
            UPDATE tmodule_times
            SET {", ".join(set_parts)}
            WHERE id IN ({placeholders})
              AND vtiger_id IS NULL
              AND billed_via_thehub_id IS NULL
              AND status <> 'billed'
        """
        execute_update(query, tuple(params + ids))
        return {"success": True, "approved": len(ids)}
    except Exception as e:
        logger.error("Failed bulk approve: %s", e)
        raise HTTPException(status_code=500, detail="Failed bulk approve")


@router.post("/time-queue/bulk-apply-prepaid")
async def bulk_apply_prepaid(payload: BulkPrepaidRequest):
    ids = _ensure_ids(payload.ids)

    card = execute_query_single(
        "SELECT id FROM tticket_prepaid_cards WHERE id = %s",
        (payload.prepaid_card_id,),
    )
    if not card:
        raise HTTPException(status_code=404, detail="Prepaid card not found")

    try:
        placeholders = ",".join(["%s"] * len(ids))
        execute_update(
            f"""
            UPDATE tmodule_times
            SET prepaid_card_id = %s,
                billing_method = 'prepaid',
                billable = TRUE,
                updated_at = CURRENT_TIMESTAMP
            WHERE id IN ({placeholders})
              AND vtiger_id IS NULL
              AND billed_via_thehub_id IS NULL
              AND status <> 'billed'
            """,
            tuple([payload.prepaid_card_id] + ids),
        )
        return {"success": True, "updated": len(ids), "prepaid_card_id": payload.prepaid_card_id}
    except Exception as e:
        logger.error("Failed applying prepaid card: %s", e)
        raise HTTPException(status_code=500, detail="Failed applying prepaid card")


def _create_order_from_selected(customer_id: int, rows: List[Dict[str, Any]], user_id: Optional[int]) -> int:
    customer = execute_query_single(
        "SELECT id, hub_customer_id, name, hourly_rate FROM tmodule_customers WHERE id = %s",
        (customer_id,),
    )
    if not customer:
        raise HTTPException(status_code=404, detail=f"Customer {customer_id} not found")

    hourly_rate = Decimal(str(customer.get("hourly_rate") or settings.TIMETRACKING_DEFAULT_HOURLY_RATE))

    grouped: Dict[str, Dict[str, Any]] = defaultdict(lambda: {
        "rows": [],
        "case_title": "Time entries",
        "case_id": None,
        "sag_id": None,
    })

    for row in rows:
        group_key = f"{row.get('case_id') or 0}:{row.get('sag_id') or 0}"
        grouped[group_key]["rows"].append(row)
        grouped[group_key]["case_title"] = row.get("case_title") or "Time entries"
        grouped[group_key]["case_id"] = row.get("case_id")
        grouped[group_key]["sag_id"] = row.get("sag_id")

    line_payloads: List[Dict[str, Any]] = []
    total_hours = Decimal("0")

    for _, group in grouped.items():
        qty = Decimal("0")
        ids: List[int] = []
        latest_date = None

        for row in group["rows"]:
            qty += Decimal(str(row.get("approved_hours") or row.get("original_hours") or 0))
            ids.append(int(row["id"]))
            wd = row.get("worked_date")
            if wd and (latest_date is None or wd > latest_date):
                latest_date = wd

        line_total = (qty * hourly_rate).quantize(Decimal("0.01"))
        line_payloads.append(
            {
                "description": group["case_title"],
                "quantity": qty,
                "line_total": line_total,
                "time_entry_ids": ids,
                "case_id": group["case_id"],
                "sag_id": group["sag_id"],
                "time_date": latest_date,
            }
        )
        total_hours += qty

    subtotal = (total_hours * hourly_rate).quantize(Decimal("0.01"))
    vat_rate = Decimal("25.00")
    vat_amount = (subtotal * vat_rate / Decimal("100")).quantize(Decimal("0.01"))
    total_amount = subtotal + vat_amount

    order_id = execute_insert(
        """
        INSERT INTO tmodule_orders
            (customer_id, hub_customer_id, order_date, total_hours, hourly_rate,
             subtotal, vat_rate, vat_amount, total_amount, status, created_by)
        VALUES
            (%s, %s, CURRENT_DATE, %s, %s, %s, %s, %s, %s, 'draft', %s)
        RETURNING id
        """,
        (
            customer_id,
            customer.get("hub_customer_id"),
            total_hours,
            hourly_rate,
            subtotal,
            vat_rate,
            vat_amount,
            total_amount,
            user_id,
        ),
    )

    for idx, line in enumerate(line_payloads, start=1):
        execute_insert(
            """
            INSERT INTO tmodule_order_lines
                (order_id, case_id, sag_id, line_number, description, quantity, unit_price,
                 line_total, time_entry_ids, case_contact, time_date, is_travel)
            VALUES
                (%s, %s, %s, %s, %s, %s, %s, %s, %s, NULL, %s, FALSE)
            RETURNING id
            """,
            (
                order_id,
                line["case_id"],
                line["sag_id"],
                idx,
                line["description"],
                line["quantity"],
                hourly_rate,
                line["line_total"],
                line["time_entry_ids"],
                line["time_date"],
            ),
        )

    return int(order_id)


def _create_ordre_draft_from_selected(customer_id: int, rows: List[Dict[str, Any]], user_id: Optional[int]) -> int:
    customer = execute_query_single(
        "SELECT id, hub_customer_id, name, hourly_rate FROM tmodule_customers WHERE id = %s",
        (customer_id,),
    )
    if not customer:
        raise HTTPException(status_code=404, detail=f"Customer {customer_id} not found")

    hourly_rate = Decimal(str(customer.get("hourly_rate") or settings.TIMETRACKING_DEFAULT_HOURLY_RATE))
    hub_customer_id = customer.get("hub_customer_id")

    hub_customer = None
    if hub_customer_id:
        hub_customer = execute_query_single(
            """
            SELECT
                standard_hourly_rate,
                standard_margin_percent,
                special_freight_price,
                supplier_service_enrolled,
                invoice_fee_amount
            FROM customers
            WHERE id = %s
            """,
            (hub_customer_id,),
        )

    invoice_fee_amount = Decimal(
        str(
            (hub_customer or {}).get("invoice_fee_amount")
            if (hub_customer or {}).get("invoice_fee_amount") is not None
            else settings.CUSTOMER_DEFAULT_INVOICE_FEE
        )
    )
    special_freight_price = (hub_customer or {}).get("special_freight_price")
    special_freight_amount = Decimal(str(special_freight_price)) if special_freight_price is not None else Decimal("0")
    supplier_service_enrolled = bool((hub_customer or {}).get("supplier_service_enrolled"))
    standard_margin_percent = Decimal(
        str(
            (hub_customer or {}).get("standard_margin_percent")
            if (hub_customer or {}).get("standard_margin_percent") is not None
            else settings.CUSTOMER_DEFAULT_MARGIN_PERCENT
        )
    )
    base_hourly_rate = Decimal(
        str(
            (hub_customer or {}).get("standard_hourly_rate")
            if (hub_customer or {}).get("standard_hourly_rate") is not None
            else hourly_rate
        )
    )

    grouped: Dict[str, Dict[str, Any]] = defaultdict(lambda: {
        "rows": [],
        "case_title": "Time entries",
        "case_id": None,
        "sag_id": None,
    })

    for row in rows:
        group_key = f"{row.get('case_id') or 0}:{row.get('sag_id') or 0}"
        grouped[group_key]["rows"].append(row)
        grouped[group_key]["case_title"] = row.get("case_title") or "Time entries"
        grouped[group_key]["case_id"] = row.get("case_id")
        grouped[group_key]["sag_id"] = row.get("sag_id")

    line_payloads: List[Dict[str, Any]] = []

    for _, group in grouped.items():
        qty = Decimal("0")
        ids: List[int] = []
        latest_date = None

        for row in group["rows"]:
            qty += Decimal(str(row.get("approved_hours") or row.get("original_hours") or 0))
            ids.append(int(row["id"]))
            wd = row.get("worked_date")
            if wd and (latest_date is None or wd > latest_date):
                latest_date = wd

        effective_margin_percent = standard_margin_percent if standard_margin_percent >= Decimal("0") else Decimal("0")
        unit_price = base_hourly_rate.quantize(Decimal("0.01"))
        amount = (qty * unit_price).quantize(Decimal("0.01"))

        line_payloads.append(
            {
                "line_key": f"timequeue:{ids[0] if ids else 0}:{group.get('case_id') or 0}:{group.get('sag_id') or 0}",
                "source_type": "timequeue",
                "source_id": ids[0] if ids else None,
                "description": group["case_title"],
                "quantity": float(qty),
                "unit_price": float(unit_price),
                "discount_percentage": 0,
                "unit": "timer",
                "product_id": None,
                "selected": True,
                "amount": float(amount),
                "customer_id": int(hub_customer_id) if hub_customer_id else None,
                "customer_name": customer.get("name") or f"Kunde {customer_id}",
                "sag_id": group["sag_id"],
                "time_entry_ids": ids,
                "time_date": str(latest_date) if latest_date else None,
                "meta": {
                    "base_hourly_rate": float(base_hourly_rate.quantize(Decimal("0.01"))),
                    "standard_margin_percent": float(effective_margin_percent),
                },
            }
        )

    if special_freight_amount > 0:
        line_payloads.append(
            {
                "line_key": f"freight:{hub_customer_id or customer_id}",
                "source_type": "freight",
                "source_id": None,
                "description": "Særlig fragtpris",
                "quantity": 1.0,
                "unit_price": float(special_freight_amount.quantize(Decimal("0.01"))),
                "discount_percentage": 0,
                "unit": "stk",
                "product_id": None,
                "selected": True,
                "amount": float(special_freight_amount.quantize(Decimal("0.01"))),
                "customer_id": int(hub_customer_id) if hub_customer_id else None,
                "customer_name": customer.get("name") or f"Kunde {customer_id}",
                "sag_id": None,
                "time_entry_ids": [],
                "time_date": None,
            }
        )

    # Fee line is included by default unless customer-specific value is 0.
    if invoice_fee_amount > 0 and not supplier_service_enrolled:
        line_payloads.append(
            {
                "line_key": f"invoice_fee:{hub_customer_id or customer_id}",
                "source_type": "invoice_fee",
                "source_id": None,
                "description": "Faktureringsgebyr",
                "quantity": 1.0,
                "unit_price": float(invoice_fee_amount.quantize(Decimal("0.01"))),
                "discount_percentage": 0,
                "unit": "stk",
                "product_id": None,
                "selected": True,
                "amount": float(invoice_fee_amount.quantize(Decimal("0.01"))),
                "customer_id": int(hub_customer_id) if hub_customer_id else None,
                "customer_name": customer.get("name") or f"Kunde {customer_id}",
                "sag_id": None,
                "time_entry_ids": [],
                "time_date": None,
                "meta": {
                    "standard_margin_percent": float(standard_margin_percent),
                    "supplier_service_enrolled": supplier_service_enrolled,
                },
            }
        )

    if not line_payloads:
        raise HTTPException(status_code=400, detail="No order lines generated from selected entries")

    draft_title = f"Timefaktura {customer.get('name') or f'Kunde {customer_id}'} - {date.today().isoformat()}"
    invoice_aggregate_key = f"timequeue-customer-{hub_customer_id or customer_id}"

    draft = execute_query_single(
        """
        INSERT INTO ordre_drafts (
            title,
            customer_id,
            lines_json,
            notes,
            layout_number,
            created_by_user_id,
            sync_status,
            export_status_json,
            invoice_aggregate_key,
            updated_at
        ) VALUES (%s, %s, %s::jsonb, %s, %s, %s, 'pending', %s::jsonb, %s, CURRENT_TIMESTAMP)
        RETURNING id
        """,
        (
            draft_title,
            int(hub_customer_id) if hub_customer_id else None,
            json.dumps(line_payloads, ensure_ascii=False),
            "Genereret fra Economy Time Queue",
            1,
            user_id,
            json.dumps({}, ensure_ascii=False),
            invoice_aggregate_key,
        ),
    )
    if not draft:
        raise HTTPException(status_code=500, detail="Failed creating ordre draft")

    return int(draft["id"])


def _resolve_tmodule_customer_id(raw_customer_id: Optional[int], sag_id: Optional[int]) -> Optional[int]:
    """Resolve any incoming customer reference to a valid tmodule_customers.id.

    Accepts:
    - direct tmodule customer id
    - hub customer id (customers.id) via tmodule_customers.hub_customer_id
    - fallback via sag_sager.customer_id -> tmodule_customers.hub_customer_id
    """
    def _find_by_tmodule_id(candidate_id: int) -> Optional[int]:
        row = execute_query_single("SELECT id FROM tmodule_customers WHERE id = %s", (candidate_id,))
        return int(row["id"]) if row else None

    def _find_by_hub_customer_id(hub_customer_id: int) -> Optional[int]:
        row = execute_query_single(
            """
            SELECT id
            FROM tmodule_customers
            WHERE hub_customer_id = %s
            ORDER BY id ASC
            LIMIT 1
            """,
            (hub_customer_id,),
        )
        return int(row["id"]) if row else None

    if raw_customer_id is not None:
        try:
            cid = int(raw_customer_id)
        except (TypeError, ValueError):
            cid = None

        if cid and cid > 0:
            direct = _find_by_tmodule_id(cid)
            if direct:
                return direct
            mapped = _find_by_hub_customer_id(cid)
            if mapped:
                return mapped

    if sag_id is not None:
        try:
            sid = int(sag_id)
        except (TypeError, ValueError):
            sid = None

        if sid and sid > 0:
            sag = execute_query_single("SELECT customer_id FROM sag_sager WHERE id = %s", (sid,))
            hub_customer_id = (sag or {}).get("customer_id") if sag else None
            if hub_customer_id:
                mapped = _find_by_hub_customer_id(int(hub_customer_id))
                if mapped:
                    return mapped

    return None


@router.post("/time-queue/send-to-invoices")
async def send_selected_to_invoices(payload: BulkSendRequest, request: Request):
    ids = _ensure_ids(payload.ids)
    user_id = getattr(request.state, "user_id", None)

    try:
        placeholders = ",".join(["%s"] * len(ids))
        rows = execute_query(
            f"""
            SELECT
                t.id,
                t.customer_id,
                t.case_id,
                t.sag_id,
                t.status,
                t.billable,
                t.billing_method,
                t.original_hours,
                t.approved_hours,
                t.worked_date,
                COALESCE(c.title, s.titel, 'Time entries') AS case_title
            FROM tmodule_times t
            LEFT JOIN tmodule_cases c ON c.id = t.case_id
            LEFT JOIN sag_sager s ON s.id = t.sag_id
            WHERE t.id IN ({placeholders})
              AND t.vtiger_id IS NULL
              AND t.billed_via_thehub_id IS NULL
              AND t.status <> 'billed'
            """,
            tuple(ids),
        )

        if not rows:
            raise HTTPException(status_code=400, detail="No eligible entries found")

        # Local order creation must not depend on e-conomic data/mapping.
        # Selected entries are converted to local orders regardless of billing method.
        selected_order_ids = [int(r["id"]) for r in rows]

        if not selected_order_ids:
            raise HTTPException(status_code=400, detail="No selected entries found")

        placeholders_invoice = ",".join(["%s"] * len(selected_order_ids))
        execute_update(
            f"""
            UPDATE tmodule_times
            SET status = 'approved',
                entry_status = 'godkendt',
                approved_hours = COALESCE(approved_hours, original_hours),
                approved_at = COALESCE(approved_at, CURRENT_TIMESTAMP),
                updated_at = CURRENT_TIMESTAMP
            WHERE id IN ({placeholders_invoice})
              AND status <> 'billed'
            """,
            tuple(selected_order_ids),
        )

        rows_by_customer: Dict[int, List[Dict[str, Any]]] = defaultdict(list)
        skipped_missing_customer: List[int] = []
        for row in rows:
            if int(row["id"]) not in selected_order_ids:
                continue

            resolved_customer_id = _resolve_tmodule_customer_id(row.get("customer_id"), row.get("sag_id"))
            if not resolved_customer_id:
                skipped_missing_customer.append(int(row["id"]))
                continue

            rows_by_customer[int(resolved_customer_id)].append(row)

        created_drafts = []
        failed_customers: List[Dict[str, Any]] = []
        for cust_id, cust_rows in rows_by_customer.items():
            try:
                draft_id = _create_ordre_draft_from_selected(cust_id, cust_rows, user_id)
                created_drafts.append({"customer_id": cust_id, "draft_id": draft_id})
            except HTTPException as ex:
                failed_customers.append(
                    {
                        "customer_id": cust_id,
                        "entry_ids": [int(r.get("id")) for r in cust_rows if r.get("id") is not None],
                        "error": str(ex.detail),
                    }
                )

        if not created_drafts:
            if skipped_missing_customer:
                raise HTTPException(
                    status_code=400,
                    detail="No local orders created: selected entries are missing customer linkage",
                )
            if failed_customers:
                raise HTTPException(
                    status_code=400,
                    detail="No local orders created: customer data is invalid for selected entries",
                )
            raise HTTPException(status_code=400, detail="No local orders created")

        # Time queue must never push directly to e-conomic.
        # Orders are created locally and can be transferred manually from Orders page.
        draft_ids = [o["draft_id"] for o in created_drafts]
        orders_url = "/ordre"
        if len(draft_ids) == 1:
            orders_url = f"/ordre/{draft_ids[0]}"

        return {
            "success": True,
            "selected": len(ids),
            "order_candidates": len(selected_order_ids),
            "created_drafts": created_drafts,
            "created_orders": [{"customer_id": d["customer_id"], "order_id": d["draft_id"]} for d in created_drafts],
            "skipped_missing_customer": skipped_missing_customer,
            "failed_customers": failed_customers,
            "orders_url": orders_url,
            "message": "Ordrekladder oprettet i /ordre. Klar til konsolidering og overfoersel.",
        }
    except HTTPException:
        raise
    except Exception as e:
        logger.error("Failed send-to-invoices flow: %s", e)
        raise HTTPException(status_code=500, detail="Failed sending selected entries to invoices")
