from django.utils.translation import gettext_lazy as _
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiParameter, extend_schema
from rest_framework import status

from core.docs.drf import BASE_ERRORS
from core.serializers import (
    AddOrderProductSerializer,
    AddressSerializer,
    AddWishlistProductSerializer,
    AttributeDetailSerializer,
    AttributeGroupDetailSerializer,
    AttributeGroupSimpleSerializer,
    AttributeSimpleSerializer,
    AttributeValueDetailSerializer,
    AttributeValueSimpleSerializer,
    BulkAddOrderProductsSerializer,
    BulkAddWishlistProductSerializer,
    BulkRemoveOrderProductsSerializer,
    BulkRemoveWishlistProductSerializer,
    BuyOrderSerializer,
    BuyUnregisteredOrderSerializer,
    CategoryDetailSerializer,
    CategorySimpleSerializer,
    FeedbackDetailSerializer,
    FeedbackSimpleSerializer,
    OrderDetailSerializer,
    OrderProductDetailSerializer,
    OrderProductSimpleSerializer,
    OrderSimpleSerializer,
    ProductDetailSerializer,
    ProductSimpleSerializer,
    RemoveOrderProductSerializer,
    RemoveWishlistProductSerializer,
    WishlistDetailSerializer,
    WishlistSimpleSerializer,
)
from core.serializers.seo import SeoSnapshotSerializer
from core.serializers.utility import AddressCreateSerializer, AddressSuggestionSerializer, DoFeedbackSerializer
from payments.serializers import TransactionProcessSerializer

ATTRIBUTE_GROUP_SCHEMA = {
    "list": extend_schema(
        summary=_("list all attribute groups (simple view)"),
        responses={status.HTTP_200_OK: AttributeGroupSimpleSerializer(many=True), **BASE_ERRORS},
    ),
    "retrieve": extend_schema(
        summary=_("retrieve a single attribute group (detailed view)"),
        responses={status.HTTP_200_OK: AttributeGroupDetailSerializer(), **BASE_ERRORS},
    ),
    "create": extend_schema(
        summary=_("create an attribute group"),
        responses={status.HTTP_201_CREATED: AttributeGroupDetailSerializer(), **BASE_ERRORS},
    ),
    "destroy": extend_schema(
        summary=_("delete an attribute group"),
        responses={status.HTTP_204_NO_CONTENT: {}, **BASE_ERRORS},
    ),
    "update": extend_schema(
        summary=_("rewrite an existing attribute group saving non-editables"),
        responses={status.HTTP_200_OK: AttributeGroupDetailSerializer(), **BASE_ERRORS},
    ),
    "partial_update": extend_schema(
        summary=_("rewrite some fields of an existing attribute group saving non-editables"),
        responses={status.HTTP_200_OK: AttributeGroupDetailSerializer(), **BASE_ERRORS},
    ),
}

ATTRIBUTE_SCHEMA = {
    "list": extend_schema(
        summary=_("list all attributes (simple view)"),
        responses={status.HTTP_200_OK: AttributeSimpleSerializer(many=True), **BASE_ERRORS},
    ),
    "retrieve": extend_schema(
        summary=_("retrieve a single attribute (detailed view)"),
        responses={status.HTTP_200_OK: AttributeDetailSerializer(), **BASE_ERRORS},
    ),
    "create": extend_schema(
        summary=_("create an attribute"),
        responses={status.HTTP_201_CREATED: AttributeDetailSerializer(), **BASE_ERRORS},
    ),
    "destroy": extend_schema(
        summary=_("delete an attribute"),
        responses={status.HTTP_204_NO_CONTENT: {}, **BASE_ERRORS},
    ),
    "update": extend_schema(
        summary=_("rewrite an existing attribute saving non-editables"),
        responses={status.HTTP_200_OK: AttributeDetailSerializer(), **BASE_ERRORS},
    ),
    "partial_update": extend_schema(
        summary=_("rewrite some fields of an existing attribute saving non-editables"),
        responses={status.HTTP_200_OK: AttributeDetailSerializer(), **BASE_ERRORS},
    ),
}

ATTRIBUTE_VALUE_SCHEMA = {
    "list": extend_schema(
        summary=_("list all attribute values (simple view)"),
        responses={status.HTTP_200_OK: AttributeValueSimpleSerializer(many=True), **BASE_ERRORS},
    ),
    "retrieve": extend_schema(
        summary=_("retrieve a single attribute value (detailed view)"),
        responses={status.HTTP_200_OK: AttributeValueDetailSerializer(), **BASE_ERRORS},
    ),
    "create": extend_schema(
        summary=_("create an attribute value"),
        responses={status.HTTP_201_CREATED: AttributeValueDetailSerializer(), **BASE_ERRORS},
    ),
    "destroy": extend_schema(
        summary=_("delete an attribute value"),
        responses={status.HTTP_204_NO_CONTENT: {}, **BASE_ERRORS},
    ),
    "update": extend_schema(
        summary=_("rewrite an existing attribute value saving non-editables"),
        responses={status.HTTP_200_OK: AttributeValueDetailSerializer(), **BASE_ERRORS},
    ),
    "partial_update": extend_schema(
        summary=_("rewrite some fields of an existing attribute value saving non-editables"),
        responses={status.HTTP_200_OK: AttributeValueDetailSerializer(), **BASE_ERRORS},
    ),
}

CATEGORY_SCHEMA = {
    "list": extend_schema(
        summary=_("list all categories (simple view)"),
        description=_("list all categories (simple view)"),
        responses={status.HTTP_200_OK: CategorySimpleSerializer(many=True), **BASE_ERRORS},
    ),
    "retrieve": extend_schema(
        summary=_("retrieve a single category (detailed view)"),
        description=_("retrieve a single category (detailed view)"),
        responses={status.HTTP_200_OK: CategoryDetailSerializer(), **BASE_ERRORS},
    ),
    "create": extend_schema(
        summary=_("create a category"),
        description=_("create a category"),
        responses={status.HTTP_201_CREATED: CategoryDetailSerializer(), **BASE_ERRORS},
    ),
    "destroy": extend_schema(
        summary=_("delete a category"),
        description=_("delete a category"),
        responses={status.HTTP_204_NO_CONTENT: {}, **BASE_ERRORS},
    ),
    "update": extend_schema(
        summary=_("rewrite an existing category saving non-editables"),
        description=_("rewrite an existing category saving non-editables"),
        responses={status.HTTP_200_OK: CategoryDetailSerializer(), **BASE_ERRORS},
    ),
    "partial_update": extend_schema(
        summary=_("rewrite some fields of an existing category saving non-editables"),
        description=_("rewrite some fields of an existing category saving non-editables"),
        responses={status.HTTP_200_OK: CategoryDetailSerializer(), **BASE_ERRORS},
    ),
    "seo": extend_schema(
        summary=_("SEO Meta snapshot"),
        description=_("returns a snapshot of the category's SEO meta data"),
        parameters=[
            OpenApiParameter(
                name="lookup",
                location="path",
                description=_("Category UUID or slug"),
                type=str,
            ),
        ],
        responses={
            status.HTTP_200_OK: SeoSnapshotSerializer(),
            **BASE_ERRORS,
        },
    ),
}

ORDER_SCHEMA = {
    "list": extend_schema(
        summary=_("list all orders (simple view)"),
        description=_("for non-staff users, only their own orders are returned."),
        parameters=[
            OpenApiParameter(
                name="search",
                type=OpenApiTypes.STR,
                description=_(
                    "Case-insensitive substring search across human_readable_id, "
                    "order_products.product.name, and order_products.product.partnumber"
                ),
            ),
            OpenApiParameter(
                name="min_buy_time",
                type=OpenApiTypes.DATETIME,
                description=_("Filter orders with buy_time >= this ISO 8601 datetime"),
            ),
            OpenApiParameter(
                name="max_buy_time",
                type=OpenApiTypes.DATETIME,
                description=_("Filter orders with buy_time <= this ISO 8601 datetime"),
            ),
            OpenApiParameter(
                name="uuid",
                type=OpenApiTypes.UUID,
                description=_("Filter by exact order UUID"),
            ),
            OpenApiParameter(
                name="human_readable_id",
                type=OpenApiTypes.STR,
                description=_("Filter by exact human-readable order ID"),
            ),
            OpenApiParameter(
                name="user_email",
                type=OpenApiTypes.STR,
                description=_("Filter by user's email (case-insensitive exact match)"),
            ),
            OpenApiParameter(
                name="user",
                type=OpenApiTypes.UUID,
                description=_("Filter by user's UUID"),
            ),
            OpenApiParameter(
                name="status",
                type=OpenApiTypes.STR,
                description=_("Filter by order status (case-insensitive substring match)"),
            ),
            OpenApiParameter(
                name="order_by",
                type=OpenApiTypes.STR,
                description=_(
                    "Order by one of: uuid, human_readable_id, user_email, user, "
                    "status, created, modified, buy_time, random. "
                    "Prefix with '-' for descending (e.g. '-buy_time')."
                ),
            ),
        ],
        responses={status.HTTP_200_OK: OrderSimpleSerializer(many=True), **BASE_ERRORS},
    ),
    "retrieve": extend_schema(
        summary=_("retrieve a single order (detailed view)"),
        responses={status.HTTP_200_OK: OrderDetailSerializer(), **BASE_ERRORS},
    ),
    "create": extend_schema(
        summary=_("create an order"),
        description=_("doesn't work for non-staff users."),
        responses={status.HTTP_201_CREATED: OrderDetailSerializer(), **BASE_ERRORS},
    ),
    "destroy": extend_schema(
        summary=_("delete an order"),
        responses={status.HTTP_204_NO_CONTENT: {}, **BASE_ERRORS},
    ),
    "update": extend_schema(
        summary=_("rewrite an existing order saving non-editables"),
        responses={status.HTTP_200_OK: OrderDetailSerializer(), **BASE_ERRORS},
    ),
    "partial_update": extend_schema(
        summary=_("rewrite some fields of an existing order saving non-editables"),
        responses={status.HTTP_200_OK: OrderDetailSerializer(), **BASE_ERRORS},
    ),
    "buy": extend_schema(
        summary=_("purchase an order"),
        description=_(
            "finalizes the order purchase. if `force_balance` is used,"
            " the purchase is completed using the user's balance;"
            " if `force_payment` is used, a transaction is initiated."
        ),
        request=BuyOrderSerializer(),
        responses={
            status.HTTP_200_OK: OrderDetailSerializer(),
            status.HTTP_202_ACCEPTED: TransactionProcessSerializer(),
            **BASE_ERRORS,
        },
    ),
    "buy_unregistered": extend_schema(
        summary=_("purchase an order without account creation"),
        description=_("finalizes the order purchase for a non-registered user."),
        request=BuyUnregisteredOrderSerializer(),
        responses={
            status.HTTP_202_ACCEPTED: TransactionProcessSerializer(),
            **BASE_ERRORS,
        },
    ),
    "add_order_product": extend_schema(
        summary=_("add product to order"),
        description=_("adds a product to an order using the provided `product_uuid` and `attributes`."),
        request=AddOrderProductSerializer(),
        responses={status.HTTP_200_OK: OrderDetailSerializer(), **BASE_ERRORS},
    ),
    "bulk_add_order_products": extend_schema(
        summary=_("add a list of products to order, quantities will not count"),
        description=_("adds a list of products to an order using the provided `product_uuid` and `attributes`."),
        request=BulkAddOrderProductsSerializer(),
        responses={status.HTTP_200_OK: OrderDetailSerializer(), **BASE_ERRORS},
    ),
    "remove_order_product": extend_schema(
        summary=_("remove product from order"),
        description=_("removes a product from an order using the provided `product_uuid` and `attributes`."),
        request=RemoveOrderProductSerializer(),
        responses={status.HTTP_200_OK: OrderDetailSerializer(), **BASE_ERRORS},
    ),
    "bulk_remove_order_products": extend_schema(
        summary=_("remove product from order, quantities will not count"),
        description=_("removes a list of products from an order using the provided `product_uuid` and `attributes`"),
        request=BulkRemoveOrderProductsSerializer(),
        responses={status.HTTP_200_OK: OrderDetailSerializer(), **BASE_ERRORS},
    ),
}

WISHLIST_SCHEMA = {
    "list": extend_schema(
        summary=_("list all wishlists (simple view)"),
        description=_("for non-staff users, only their own wishlists are returned."),
        responses={status.HTTP_200_OK: WishlistSimpleSerializer(many=True), **BASE_ERRORS},
    ),
    "retrieve": extend_schema(
        summary=_("retrieve a single wishlist (detailed view)"),
        responses={status.HTTP_200_OK: WishlistDetailSerializer(), **BASE_ERRORS},
    ),
    "create": extend_schema(
        summary=_("create an wishlist"),
        description=_("Doesn't work for non-staff users."),
        responses={status.HTTP_201_CREATED: WishlistDetailSerializer(), **BASE_ERRORS},
    ),
    "destroy": extend_schema(
        summary=_("delete an wishlist"),
        responses={status.HTTP_204_NO_CONTENT: {}, **BASE_ERRORS},
    ),
    "update": extend_schema(
        summary=_("rewrite an existing wishlist saving non-editables"),
        responses={status.HTTP_200_OK: WishlistDetailSerializer(), **BASE_ERRORS},
    ),
    "partial_update": extend_schema(
        summary=_("rewrite some fields of an existing wishlist saving non-editables"),
        responses={status.HTTP_200_OK: WishlistDetailSerializer(), **BASE_ERRORS},
    ),
    "add_wishlist_product": extend_schema(
        summary=_("add product to wishlist"),
        description=_("adds a product to an wishlist using the provided `product_uuid`"),
        request=AddWishlistProductSerializer(),
        responses={status.HTTP_200_OK: WishlistDetailSerializer(), **BASE_ERRORS},
    ),
    "remove_wishlist_product": extend_schema(
        summary=_("remove product from wishlist"),
        description=_("removes a product from an wishlist using the provided `product_uuid`"),
        request=RemoveWishlistProductSerializer(),
        responses={status.HTTP_200_OK: WishlistDetailSerializer(), **BASE_ERRORS},
    ),
    "bulk_add_wishlist_products": extend_schema(
        summary=_("add many products to wishlist"),
        description=_("adds many products to an wishlist using the provided `product_uuids`"),
        request=BulkAddWishlistProductSerializer(),
        responses={status.HTTP_200_OK: WishlistDetailSerializer(), **BASE_ERRORS},
    ),
    "bulk_remove_wishlist_products": extend_schema(
        summary=_("remove many products from wishlist"),
        description=_("removes many products from an wishlist using the provided `product_uuids`"),
        request=BulkRemoveWishlistProductSerializer(),
        responses={status.HTTP_200_OK: WishlistDetailSerializer(), **BASE_ERRORS},
    ),
}

ATTRIBUTES_DESC = _(
    "Filter by one or more attribute name/value pairs.  \n"
    "• **Syntax**: `attr_name=method-value[;attr2=method2-value2]…`  \n"
    "• **Methods** (defaults to `icontains` if omitted): "
    "`iexact`, `exact`, `icontains`, `contains`, `isnull`, "
    "`startswith`, `istartswith`, `endswith`, `iendswith`, "
    "`regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`  \n"
    "• **Value typing**: JSON is attempted first (so you can pass lists/dicts), "
    "`true`/`false` for booleans, integers, floats; otherwise treated as string.  \n"
    "• **Base64**: prefix with `b64-` to URL-safe base64-encode the raw value.  \n"
    "Examples:  \n"
    '`color=exact-red`,  `size=gt-10`,  `features=in-["wifi","bluetooth"]`,  \n'
    "`b64-description=icontains-aGVhdC1jb2xk`"
)

PRODUCT_SCHEMA = {
    "list": extend_schema(
        summary=_("list all products (simple view)"),
        description=_("list all products (simple view)"),
        parameters=[
            OpenApiParameter(
                name="uuid",
                location="query",
                description=_("(exact) Product UUID"),
                type=str,
            ),
            OpenApiParameter(
                name="order_by",
                location="query",
                description=_(
                    "Comma-separated list of fields to sort by. "
                    "Prefix with `-` for descending.  \n"
                    "**Allowed:** uuid, rating, name, slug, created, modified, price, random"
                ),
                required=False,
                type=str,
            ),
        ],
        responses={
            status.HTTP_200_OK: ProductSimpleSerializer(many=True),
            **BASE_ERRORS,
        },
    ),
    "retrieve": extend_schema(
        summary=_("retrieve a single product (detailed view)"),
        description=_("retrieve a single product (detailed view)"),
        parameters=[
            OpenApiParameter(
                name="lookup_value",
                location="path",
                description=_("Product UUID or slug"),
                type=str,
            ),
        ],
        responses={
            status.HTTP_200_OK: ProductDetailSerializer(),
            **BASE_ERRORS,
        },
    ),
    "create": extend_schema(
        summary=_("create a product"),
        description=_("create a product"),
        responses={
            status.HTTP_201_CREATED: ProductDetailSerializer(),
            **BASE_ERRORS,
        },
    ),
    "update": extend_schema(
        summary=_("rewrite an existing product, preserving non-editable fields"),
        description=_("rewrite an existing product, preserving non-editable fields"),
        parameters=[
            OpenApiParameter(
                name="lookup_value",
                location="path",
                description=_("Product UUID or slug"),
                type=str,
            ),
        ],
        responses={
            status.HTTP_200_OK: ProductDetailSerializer(),
            **BASE_ERRORS,
        },
    ),
    "partial_update": extend_schema(
        summary=_("update some fields of an existing product, preserving non-editable fields"),
        description=_("update some fields of an existing product, preserving non-editable fields"),
        parameters=[
            OpenApiParameter(
                name="lookup_value",
                location="path",
                description=_("Product UUID or slug"),
                type=str,
            ),
        ],
        responses={
            status.HTTP_200_OK: ProductDetailSerializer(),
            **BASE_ERRORS,
        },
    ),
    "destroy": extend_schema(
        summary=_("delete a product"),
        description=_("delete a product"),
        parameters=[
            OpenApiParameter(
                name="lookup_value",
                location="path",
                description=_("Product UUID or slug"),
                type=str,
            ),
        ],
        responses={
            status.HTTP_204_NO_CONTENT: {},
            **BASE_ERRORS,
        },
    ),
    "feedbacks": extend_schema(
        summary=_("lists all permitted feedbacks for a product"),
        description=_("lists all permitted feedbacks for a product"),
        parameters=[
            OpenApiParameter(
                name="lookup_value",
                location="path",
                description=_("Product UUID or slug"),
                type=str,
            ),
        ],
        responses={
            status.HTTP_200_OK: FeedbackSimpleSerializer(many=True),
            **BASE_ERRORS,
        },
    ),
    "seo_meta": extend_schema(
        summary=_("SEO Meta snapshot"),
        description=_("returns a snapshot of the product's SEO meta data"),
        parameters=[
            OpenApiParameter(
                name="lookup_value",
                location="path",
                description=_("Product UUID or slug"),
                type=str,
            ),
        ],
        responses={
            status.HTTP_200_OK: SeoSnapshotSerializer(),
            **BASE_ERRORS,
        },
    ),
}

ADDRESS_SCHEMA = {
    "list": extend_schema(
        summary=_("list all addresses"),
        responses={
            status.HTTP_200_OK: AddressSerializer(many=True),
            **BASE_ERRORS,
        },
    ),
    "retrieve": extend_schema(
        summary=_("retrieve a single address"),
        responses={
            status.HTTP_200_OK: AddressSerializer(),
            **BASE_ERRORS,
        },
    ),
    "create": extend_schema(
        summary=_("create a new address"),
        request=AddressCreateSerializer(),
        responses={
            status.HTTP_201_CREATED: AddressSerializer(),
            **BASE_ERRORS,
        },
    ),
    "destroy": extend_schema(
        summary=_("delete an address"),
        responses={
            status.HTTP_204_NO_CONTENT: {},
            **BASE_ERRORS,
        },
    ),
    "update": extend_schema(
        summary=_("update an entire address"),
        request=AddressSerializer(),
        responses={
            status.HTTP_200_OK: AddressSerializer(),
            **BASE_ERRORS,
        },
    ),
    "partial_update": extend_schema(
        summary=_("partially update an address"),
        request=AddressSerializer(),
        responses={
            status.HTTP_200_OK: AddressSerializer(),
            **BASE_ERRORS,
        },
    ),
    "autocomplete": extend_schema(
        summary=_("autocomplete address suggestions"),
        parameters=[
            OpenApiParameter(
                name="q",
                location="query",
                description=_("raw data query string, please append with data from geo-IP endpoint"),
                type=str,
            ),
            OpenApiParameter(
                name="limit",
                location="query",
                description=_("limit the results amount, 1 < limit < 10, default: 5"),
                type=int,
            ),
        ],
        responses={
            status.HTTP_200_OK: AddressSuggestionSerializer(many=True),
            **BASE_ERRORS,
        },
    ),
}

FEEDBACK_SCHEMA = {
    "list": extend_schema(
        summary=_("list all feedbacks (simple view)"),
        responses={status.HTTP_200_OK: FeedbackSimpleSerializer(many=True), **BASE_ERRORS},
    ),
    "retrieve": extend_schema(
        summary=_("retrieve a single feedback (detailed view)"),
        responses={status.HTTP_200_OK: FeedbackDetailSerializer(), **BASE_ERRORS},
    ),
    "create": extend_schema(
        summary=_("create a feedback"),
        responses={status.HTTP_201_CREATED: FeedbackDetailSerializer(), **BASE_ERRORS},
    ),
    "destroy": extend_schema(
        summary=_("delete a feedback"),
        responses={status.HTTP_204_NO_CONTENT: {}, **BASE_ERRORS},
    ),
    "update": extend_schema(
        summary=_("rewrite an existing feedback saving non-editables"),
        responses={status.HTTP_200_OK: FeedbackDetailSerializer(), **BASE_ERRORS},
    ),
    "partial_update": extend_schema(
        summary=_("rewrite some fields of an existing feedback saving non-editables"),
        responses={status.HTTP_200_OK: FeedbackDetailSerializer(), **BASE_ERRORS},
    ),
}

ORDER_PRODUCT_SCHEMA = {
    "list": extend_schema(
        summary=_("list all order–product relations (simple view)"),
        responses={
            status.HTTP_200_OK: OrderProductSimpleSerializer(many=True),
            **BASE_ERRORS,
        },
    ),
    "retrieve": extend_schema(
        summary=_("retrieve a single order–product relation (detailed view)"),
        responses={
            status.HTTP_200_OK: OrderProductDetailSerializer(),
            **BASE_ERRORS,
        },
    ),
    "create": extend_schema(
        summary=_("create a new order–product relation"),
        responses={
            status.HTTP_201_CREATED: OrderProductDetailSerializer(),
            **BASE_ERRORS,
        },
    ),
    "update": extend_schema(
        summary=_("replace an existing order–product relation"),
        responses={
            status.HTTP_200_OK: OrderProductDetailSerializer(),
            **BASE_ERRORS,
        },
    ),
    "partial_update": extend_schema(
        summary=_("partially update an existing order–product relation"),
        responses={
            status.HTTP_200_OK: OrderProductDetailSerializer(),
            **BASE_ERRORS,
        },
    ),
    "destroy": extend_schema(
        summary=_("delete an order–product relation"),
        responses={
            status.HTTP_204_NO_CONTENT: {},
            **BASE_ERRORS,
        },
    ),
    "do_feedback": extend_schema(
        summary=_("add or remove feedback on an order–product relation"),
        request=DoFeedbackSerializer,
        responses={
            status.HTTP_201_CREATED: FeedbackDetailSerializer(),
            status.HTTP_204_NO_CONTENT: {},
            status.HTTP_400_BAD_REQUEST: {},
            status.HTTP_404_NOT_FOUND: {},
            **BASE_ERRORS,
        },
    ),
}
