import re
from decimal import Decimal
from http import HTTPStatus
from typing import Annotated, Literal

from aws_lambda_powertools.event_handler.api_gateway import Router
from aws_lambda_powertools.event_handler.openapi.params import Body
from layercake.dynamodb import DynamoDBPersistenceLayer
from layercake.extra_types import CnpjStr, CpfStr, NameStr
from pydantic import (
    UUID4,
    BaseModel,
    ConfigDict,
    EmailStr,
    field_validator,
    model_validator,
)

from api_gateway import JSONResponse
from boto3clients import dynamodb_client
from config import ORDER_TABLE

router = Router()
dyn = DynamoDBPersistenceLayer(ORDER_TABLE, dynamodb_client)


class User(BaseModel):
    id: UUID4 | str
    name: NameStr


class Address(BaseModel):
    model_config = ConfigDict(str_strip_whitespace=True)

    postcode: str
    address1: str
    address2: str | None = None
    neighborhood: str
    city: str
    state: str

    @field_validator('postcode')
    @classmethod
    def ensure_numbers(cls, v: str) -> str:
        return re.sub(r'\D', '', v)


class Item(BaseModel):
    id: UUID4
    name: str
    unit_price: Decimal
    quantity: int = 1


class Checkout(BaseModel):
    model_config = ConfigDict(str_strip_whitespace=True)

    name: str
    email: EmailStr
    address: Address
    payment_method: Literal['PIX', 'CREDIT_CARD', 'BANK_SLIP', 'MANUAL']
    items: tuple[Item, ...]
    user: User | None = None
    org_id: UUID4 | str | None = None
    user_id: UUID4 | str | None = None
    cnpj: CnpjStr | None = None
    cpf: CpfStr | None = None

    @model_validator(mode='after')
    def verify_fields(self):
        if not any([self.cnpj, self.cpf]):
            raise ValueError('cnpj or cpf is required')

        if self.cnpj is not None:
            if self.org_id is None:
                raise ValueError('org_id is missing')

            if self.user is None:
                raise ValueError('user is missing')

        if self.cpf is not None and self.user_id is None:
            raise ValueError('user_id is missing')

        return self


@router.post('/')
def checkout(body: Annotated[Checkout, Body()]):
    return JSONResponse(status_code=HTTPStatus.CREATED)
