from typing import Any, Dict, List, Optional


class Paylinks:
    """Create and manage payment links."""

    def __init__(self, client):
        self._client = client

    def create(
        self,
        products: List[Dict[str, Any]],
        type: str = None,
        expires_in_seconds: int = None,
        max_uses: int = None,
        success_url: str = None,
        cancel_url: str = None,
        collect_name: str = None,
        collect_email: str = None,
        collect_phone: str = None,
        collect_address: str = None,
        recurring_interval: str = None,
        recurring_interval_count: int = None,
        brand_color: str = None,
        logo_url: str = None,
    ) -> dict:
        """
        Create a new payment link.

        Args:
            products: List of product dicts with keys: name, price, description,
                      productType, stockEnabled, stockQty, digitalUrl, sortOrder
            type: FIXED, VARIABLE, or RECURRING (default: FIXED)
            expires_in_seconds: Expiry in seconds (0 = no expiry)
            max_uses: Maximum number of uses
            success_url: Post-payment redirect URL
            cancel_url: Cancel redirect URL
            collect_name: REQUIRED, OPTIONAL, or HIDDEN (default: HIDDEN)
            collect_email: REQUIRED, OPTIONAL, or HIDDEN (default: HIDDEN)
            collect_phone: REQUIRED, OPTIONAL, or HIDDEN (default: HIDDEN)
            collect_address: REQUIRED, OPTIONAL, or HIDDEN (default: HIDDEN)
            recurring_interval: WEEKLY, MONTHLY, or YEARLY (for RECURRING type)
            recurring_interval_count: Billing interval count
            brand_color: Hex color (e.g. "#635BFF")
            logo_url: Logo URL

        Returns:
            Dict with paylink details including id, slug, products, paymentUrl.
        """
        body = {"products": products}
        if type is not None:
            body["type"] = type
        if expires_in_seconds is not None:
            body["expiresInSeconds"] = expires_in_seconds
        if max_uses is not None:
            body["maxUses"] = max_uses
        if success_url is not None:
            body["successUrl"] = success_url
        if cancel_url is not None:
            body["cancelUrl"] = cancel_url
        if collect_name is not None:
            body["collectName"] = collect_name
        if collect_email is not None:
            body["collectEmail"] = collect_email
        if collect_phone is not None:
            body["collectPhone"] = collect_phone
        if collect_address is not None:
            body["collectAddress"] = collect_address
        if recurring_interval is not None:
            body["recurringInterval"] = recurring_interval
        if recurring_interval_count is not None:
            body["recurringIntervalCount"] = recurring_interval_count
        if brand_color is not None:
            body["brandColor"] = brand_color
        if logo_url is not None:
            body["logoUrl"] = logo_url

        res = self._client.post("/paylinks", json=body)
        return res["data"]

    def get(self, paylink_id: str) -> dict:
        """Get a paylink by ID."""
        res = self._client.get(f"/paylinks/{paylink_id}")
        return res["data"]

    def list(
        self,
        page: int = None,
        limit: int = None,
        status: str = None,
    ) -> dict:
        """
        List paylinks with optional filters.

        Returns:
            Dict with "items" (list) and "total" (int).
        """
        res = self._client.get("/paylinks", params={"page": page, "limit": limit, "status": status})
        return res["data"]

    def update(self, paylink_id: str, **kwargs) -> dict:
        """
        Update a paylink.

        Keyword Args:
            status: ACTIVE, PAUSED, EXPIRED, or DEPLETED
            max_uses, success_url, cancel_url, collect_name, collect_email,
            collect_phone, collect_address, brand_color, logo_url
        """
        body = {}
        field_map = {
            "status": "status",
            "max_uses": "maxUses",
            "success_url": "successUrl",
            "cancel_url": "cancelUrl",
            "collect_name": "collectName",
            "collect_email": "collectEmail",
            "collect_phone": "collectPhone",
            "collect_address": "collectAddress",
            "brand_color": "brandColor",
            "logo_url": "logoUrl",
        }
        for py_key, api_key in field_map.items():
            if py_key in kwargs and kwargs[py_key] is not None:
                body[api_key] = kwargs[py_key]

        res = self._client.patch(f"/paylinks/{paylink_id}", json=body)
        return res["data"]

    def delete(self, paylink_id: str) -> dict:
        """Delete a paylink."""
        return self._client.delete(f"/paylinks/{paylink_id}")

    def get_stats(self, paylink_id: str) -> dict:
        """Get analytics for a single paylink."""
        res = self._client.get(f"/paylinks/{paylink_id}/stats")
        return res["data"]

    def get_dashboard_stats(self) -> dict:
        """Get aggregate dashboard stats across all paylinks."""
        res = self._client.get("/paylinks/dashboard-stats")
        return res["data"]

    # ─── Orders ──────────────────────────────────────────────────────────────

    def list_orders(
        self,
        paylink_id: str,
        page: int = None,
        limit: int = None,
    ) -> dict:
        """List orders for a paylink."""
        res = self._client.get(
            f"/paylinks/{paylink_id}/orders",
            params={"page": page, "limit": limit},
        )
        return res["data"]

    def export_orders_csv(self, paylink_id: str) -> str:
        """Export orders as CSV."""
        return self._client.get_raw(f"/paylinks/{paylink_id}/orders/export")

    # ─── Promo Codes ─────────────────────────────────────────────────────────

    def create_promo_code(
        self,
        paylink_id: str,
        code: str,
        discount_type: str,
        discount_value: str,
        max_uses: int = None,
    ) -> dict:
        """
        Create a promo code for a paylink.

        Args:
            paylink_id: Paylink ID
            code: Promo code string (e.g. "PROMO10")
            discount_type: PERCENT or FIXED
            discount_value: Discount value (percentage or USDT amount)
            max_uses: Maximum redemptions
        """
        body = {
            "code": code,
            "discountType": discount_type,
            "discountValue": discount_value,
        }
        if max_uses is not None:
            body["maxUses"] = max_uses

        res = self._client.post(f"/paylinks/{paylink_id}/promo-codes", json=body)
        return res["data"]

    def list_promo_codes(self, paylink_id: str) -> list:
        """List promo codes for a paylink."""
        res = self._client.get(f"/paylinks/{paylink_id}/promo-codes")
        return res["data"]

    def toggle_promo_code(self, paylink_id: str, code_id: str, is_active: bool) -> dict:
        """Toggle promo code active status."""
        res = self._client.patch(f"/paylinks/{paylink_id}/promo-codes/{code_id}", json={"isActive": is_active})
        return res["data"]

    def delete_promo_code(self, paylink_id: str, code_id: str) -> dict:
        """Delete a promo code."""
        return self._client.delete(f"/paylinks/{paylink_id}/promo-codes/{code_id}")

    # ─── Templates ───────────────────────────────────────────────────────────

    def create_template(self, name: str, config: dict) -> dict:
        """Create a paylink template."""
        res = self._client.post("/paylinks/templates", json={"name": name, "config": config})
        return res["data"]

    def list_templates(self) -> list:
        """List paylink templates."""
        res = self._client.get("/paylinks/templates")
        return res["data"]

    def delete_template(self, template_id: str) -> dict:
        """Delete a template."""
        return self._client.delete(f"/paylinks/templates/{template_id}")

    def save_as_template(self, paylink_id: str, name: str) -> dict:
        """Save an existing paylink as a template."""
        res = self._client.post(f"/paylinks/{paylink_id}/save-as-template", json={"name": name})
        return res["data"]

    # ─── Subscriptions ───────────────────────────────────────────────────────

    def list_subscriptions(self, paylink_id: str) -> list:
        """List subscriptions for a recurring paylink."""
        res = self._client.get(f"/paylinks/{paylink_id}/subscriptions")
        return res["data"]

    def cancel_subscription(self, paylink_id: str, subscription_id: str) -> dict:
        """Cancel a subscription."""
        res = self._client.post(f"/paylinks/{paylink_id}/subscriptions/{subscription_id}/cancel")
        return res["data"]

    # ─── Images ──────────────────────────────────────────────────────────────

    def upload_cover_image(self, paylink_id: str, file_path: str) -> dict:
        """Upload a cover image from a local file."""
        res = self._client.post_file(f"/paylinks/{paylink_id}/cover-image", file_path, field_name="file")
        return res["data"]

    def delete_cover_image(self, paylink_id: str) -> dict:
        """Delete cover image."""
        return self._client.delete(f"/paylinks/{paylink_id}/cover-image")

    def upload_product_image(self, paylink_id: str, product_id: str, file_path: str) -> dict:
        """Upload a product image from a local file."""
        res = self._client.post_file(
            f"/paylinks/{paylink_id}/products/{product_id}/image",
            file_path,
            field_name="file",
        )
        return res["data"]

    def import_products_csv(self, paylink_id: str, file_path: str) -> dict:
        """Bulk import products via CSV file."""
        res = self._client.post_file(
            f"/paylinks/{paylink_id}/products/import-csv",
            file_path,
            field_name="file",
        )
        return res["data"]
