"""
Sync Shopify fulfillment tracking for one order to Digistore24 updateDelivery.

Usage:
  python manage.py sync_digistore_tracking --digistore-order-id=53J5D4PV
  python manage.py sync_digistore_tracking --shopify-order-id=5678901234
  python manage.py sync_digistore_tracking --digistore-order-id=53J5D4PV --dry-run
  python manage.py sync_digistore_tracking --digistore-order-id=53J5D4PV --notify
  python manage.py sync_digistore_tracking --digistore-order-id=53J5D4PV --no-notify

Optional overrides (skip / override Shopify tracking):
  python manage.py sync_digistore_tracking --digistore-order-id=53J5D4PV \\
      --tracking-id=1Z999AA10123456784 --parcel-service=ups
"""
from __future__ import annotations

import json

from django.conf import settings
from django.core.management.base import BaseCommand, CommandError

from orders.services import OrderService


class Command(BaseCommand):
    help = (
        "Sync Shopify fulfillment tracking for one mapped order to Digistore24 "
        "(listDeliveries + updateDelivery)."
    )

    def add_arguments(self, parser):
        parser.add_argument(
            "--digistore-order-id",
            "--purchase_id",
            dest="digistore_order_id",
            default="",
            help="Digistore purchase/order id (Order.digistore_order_id).",
        )
        parser.add_argument(
            "--shopify-order-id",
            default="",
            help="Shopify order numeric id (Order.shopify_order_id).",
        )
        parser.add_argument(
            "--tracking-id",
            default="",
            help="Override tracking number (default: from Shopify fulfillments).",
        )
        parser.add_argument(
            "--parcel-service",
            default="",
            help="Override carrier key, e.g. ups, dhl (default: mapped from Shopify).",
        )
        parser.add_argument(
            "--tracking-url",
            default="",
            help="Override tracking URL (default: from Shopify).",
        )
        parser.add_argument(
            "--quantity",
            type=int,
            default=0,
            help=(
                "Quantity to add toward Digistore quantity_delivered. "
                "0 = remaining on the Digistore delivery row."
            ),
        )
        notify_group = parser.add_mutually_exclusive_group()
        notify_group.add_argument(
            "--notify",
            dest="notify",
            action="store_true",
            default=None,
            help="Email the Digistore buyer about the delivery update.",
        )
        notify_group.add_argument(
            "--no-notify",
            dest="notify",
            action="store_false",
            default=None,
            help="Do not email the Digistore buyer (overrides the global setting).",
        )
        parser.add_argument(
            "--dry-run",
            action="store_true",
            help="Resolve Shopify tracking + Digistore delivery; do not call updateDelivery.",
        )

    def handle(self, *args, **options):
        digistore_order_id = str(options.get("digistore_order_id") or "").strip()
        shopify_order_id = str(options.get("shopify_order_id") or "").strip()
        if not digistore_order_id and not shopify_order_id:
            raise CommandError(
                "Provide --digistore-order-id and/or --shopify-order-id"
            )

        # Resolve notify: --notify > --no-notify > global setting.
        notify = options.get("notify")
        if notify is None:
            notify = bool(
                getattr(settings, "DIGISTORE_TRACKING_NOTIFY_VIA_EMAIL", False)
            )

        try:
            result = OrderService.sync_tracking_to_digistore(
                digistore_order_id=digistore_order_id,
                shopify_order_id=shopify_order_id,
                tracking_id=str(options.get("tracking_id") or "").strip(),
                parcel_service=str(options.get("parcel_service") or "").strip(),
                tracking_url=str(options.get("tracking_url") or "").strip(),
                quantity=int(options.get("quantity") or 0),
                notify_via_email=bool(notify),
                dry_run=bool(options.get("dry_run")),
            )
        except ValueError as exc:
            raise CommandError(str(exc)) from exc
        except Exception as exc:
            raise CommandError(f"sync_tracking_to_digistore failed: {exc}") from exc

        self.stdout.write(
            json.dumps(result, indent=2, sort_keys=True, default=str)
        )

        if not result.get("ok"):
            raise CommandError(result.get("error") or "updateDelivery failed")

        if result.get("dry_run"):
            self.stdout.write(self.style.WARNING("dry-run: skipped updateDelivery"))
            return

        self.stdout.write(self.style.SUCCESS("tracking sync ok"))
