//! Outbound carrier integrations for creating shipments.
//!
//! Shipments are **never created automatically**. An admin reviews an order and,
//! once the goods are physically ready, explicitly triggers
//! [`create_shipment`] from the order page. Only then does the eshop call the
//! carrier's API. `orders::place` (checkout) does not touch any of this.
//!
//! Each delivery option (`shipping_methods.carrier`) maps to one carrier here.
//! "none" means the option is fulfilled manually and has no API.

pub mod dhl;
pub mod dpd;
pub mod packeta;

use loco_rs::prelude::*;

/// Everything a carrier needs to register a parcel, snapshotted from an order.
pub struct ShipmentRequest<'a> {
    pub order_number: &'a str,
    pub recipient_name: &'a str,
    pub email: &'a str,
    pub phone: Option<&'a str>,
    pub address: Option<&'a str>,
    pub city: Option<&'a str>,
    pub zip: Option<&'a str>,
    pub country: Option<&'a str>,
    /// Carrier pickup-point / locker id, when the method requires one.
    pub pickup_point_id: Option<&'a str>,
    /// Cash-on-delivery amount in cents; `0` when payment is not COD.
    pub cod_cents: i64,
    /// Total order value in cents (for insurance / customs declarations).
    pub value_cents: i64,
    pub weight_grams: i32,
}

/// What a carrier returns once the parcel is registered.
pub struct ShipmentResult {
    /// Carrier-internal shipment/packet id.
    pub shipment_id: String,
    /// Public tracking number / barcode shown to the customer.
    pub tracking_number: String,
    /// Direct link to the shipping label PDF, if the carrier returns one.
    pub label_url: Option<String>,
}

/// Dispatch to the carrier named by `shipping_methods.carrier`. Returns an error
/// for `"none"` (manual fulfilment) or an unknown carrier.
pub async fn create_shipment(
    ctx: &AppContext,
    carrier: &str,
    req: ShipmentRequest<'_>,
) -> Result<ShipmentResult> {
    match carrier {
        "packeta" => packeta::create_shipment(ctx, req).await,
        "dpd" => dpd::create_shipment(ctx, req).await,
        "dhl" => dhl::create_shipment(ctx, req).await,
        "none" | "" => Err(Error::BadRequest(
            "this delivery option is fulfilled manually (no carrier API)".to_string(),
        )),
        other => Err(Error::BadRequest(format!("unknown carrier '{other}'"))),
    }
}

/// The carrier values offered in the admin UI. `none` is the manual default.
pub const CARRIERS: [&str; 4] = ["none", "packeta", "dpd", "dhl"];
