"""Public, unauthenticated DHL tracking endpoint used by the customer-facing
``/shop/track/:number`` page.

We intentionally do **not** leak order details — only the tracking number the
user already has, plus the human-readable events and status. The associated
order number is exposed because the customer typically already has it from
their order confirmation email.
"""

from __future__ import annotations

import logging
from datetime import timezone
from typing import Optional

from core.database import get_db
from fastapi import APIRouter, Depends, HTTPException, status
from models.orders import Orders
from schemas.dhl import (
    DhlPublicNotificationList,
    DhlPublicNotificationOut,
    DhlTrackingEvent,
    DhlTrackingResult,
)
from services.dhl import get_settings, get_tracking, list_notifications
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession


def _mask_email(email: Optional[str]) -> Optional[str]:
    """Return a masked form of the email, e.g. ``j***@example.com``."""
    if not email or "@" not in email:
        return None
    local, _, domain = email.partition("@")
    local = local.strip()
    if not local:
        return None
    if len(local) <= 1:
        masked_local = local + "***"
    else:
        masked_local = local[0] + "***"
    return f"{masked_local}@{domain}"

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/v1/shop/tracking", tags=["dhl-public"])


@router.get("/{tracking_number}", response_model=DhlTrackingResult)
async def track_shipment(
    tracking_number: str,
    db: AsyncSession = Depends(get_db),
) -> DhlTrackingResult:
    tracking_number = (tracking_number or "").strip()
    if not tracking_number:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Missing tracking number")

    # Best-effort lookup of the matching order so stub events can start from
    # the correct "shipment created at" timestamp.
    created_at: Optional[object] = None
    order_info: Optional[dict] = None
    try:
        result = await db.execute(select(Orders).where(Orders.tracking_number == tracking_number))
        order = result.scalars().first()
        if order is not None:
            created_at = order.updated_at or order.created_at
            if created_at is not None and created_at.tzinfo is None:
                created_at = created_at.replace(tzinfo=timezone.utc)
            order_info = {
                "order_number": order.order_number,
                "status": order.status,
                "total": order.total,
                "currency": order.currency,
            }
    except Exception as exc:  # noqa: BLE001
        logger.debug("[dhl] order lookup for tracking %s failed: %s", tracking_number, exc)

    settings = await get_settings(db)
    data = await get_tracking(settings, tracking_number, created_at=created_at)
    return DhlTrackingResult(
        tracking_number=data["tracking_number"],
        status=data["status"],
        stub=data["stub"],
        message=data["message"],
        events=[DhlTrackingEvent(**e) for e in data.get("events", [])],
        order=order_info,
    )


@router.get(
    "/{tracking_number}/notifications",
    response_model=DhlPublicNotificationList,
)
async def list_shipment_notifications(
    tracking_number: str,
    db: AsyncSession = Depends(get_db),
) -> DhlPublicNotificationList:
    """Return a sanitized notification log for a given tracking number.

    Only customer-safe fields are returned (no raw recipient email, no server
    error messages). This lets the customer-facing tracker confirm which
    status updates actually triggered an email.
    """
    tracking_number = (tracking_number or "").strip()
    if not tracking_number:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Missing tracking number",
        )

    rows = await list_notifications(db, tracking_number=tracking_number, limit=50)
    items = [
        DhlPublicNotificationOut(
            previous_status=row.previous_status,
            new_status=row.new_status,
            event_description=row.event_description,
            event_location=row.event_location,
            event_timestamp=row.event_timestamp,
            sent=bool(row.success),
            recipient_masked=_mask_email(row.recipient_email),
            created_at=row.created_at.isoformat() if row.created_at else None,
        )
        for row in rows
    ]
    return DhlPublicNotificationList(items=items)