from datetime import datetime
from typing import Optional
from pydantic import BaseModel, Field
from src.apps.base.schemas.common import AddressCreateRequestSchema, AddressSchema, BaseSchema
from src.apps.base.schemas.common import BaseSchema
from src.core.utils.enums import PaymentMethodScopes, PaymentMethodTypes
from src.apps.payment_requests.enums import SplitPaymentTypes
from src.apps.customers.schemas.customer_common import CustomerSchema


class PaymentMethodCardBase(BaseSchema):
    reference_id: Optional[str] = Field(description="Third party reference id")
    is_default: Optional[bool] = Field(
        description="Is this card default for this customer?"
    )
    card_number: Optional[str] = Field(description="last 4 digits of card number")
    # brand: Optional[PaymentCardBrand] = Field(description="Brand of card, Visa / Mastercard etc")
    brand: Optional[str] = Field(description="Brand of card, Visa / Mastercard etc")
    cvv: Optional[str] = Field(description="Card CVV")
    funding: Optional[str] = Field(description="Type of card - Credit/Debit")
    expire_month: Optional[str] = Field(description="Card expiry month")
    expire_year: Optional[str] = Field(description="Card expiry year")
    method: Optional[str] = Field(description="Method of the payment e.g. card/ach")
    pay_split_type: Optional[str] = Field(
        description="Payment Method Split Type for the card percentage/amount"
    )
    pay_split_value: Optional[float] = Field(
        description="Payment Method Split value for the Type"
    )
    created_at: Optional[datetime] = Field(
        description="Created date and time as unix timestamp"
    )
    last_used_at: Optional[datetime] = Field(
        description="Last used date and time as unix timestamp"
    )


class PaymentMethodCardSchema(PaymentMethodCardBase):
    id: Optional[int] = Field(description="Id of PaymentMethodCardSchema resource")


class PaymentMethodCardCreate(PaymentMethodCardBase):
    pass


class PaymentMethodCardUpdate(PaymentMethodCardSchema):
    pass


class PaymentMethodACHBase(BaseSchema):
    reference_id: Optional[str] = Field(description="Third party reference id")
    is_default: Optional[bool] = Field(
        description="Is this ach method default for this customer?"
    )
    account_number: Optional[str] = Field(description="Account number of customer")
    routing_number: Optional[str] = Field(description="Routing number of customer")
    account_name: Optional[str] = Field(description="Account holder name")
    bank_name: Optional[str] = Field(description="Bank name")
    owner_type: Optional[str] = Field(description="Type of account owner")
    account_type: Optional[str] = Field(
        description="Type of account, Savings / Current / etc"
    )
    created_at: Optional[datetime] = Field(
        description="Created date and time as unix timestamp"
    )
    last_used_at: Optional[datetime] = Field(
        description="Last used date and time as unix timestamp"
    )


class PaymentMethodACHSchema(PaymentMethodACHBase):
    id: Optional[int] = Field(description="Id of PaymentMethodACHSchema resource")


class PaymentMethodACHCreate(PaymentMethodACHBase):
    pass


class PaymentMethodACHUpdate(PaymentMethodACHSchema):
    pass


class PaymentMethodChequeBase(BaseSchema):
    cheque_number: Optional[str] = Field(description="Cheque number of customer")
    created_at: Optional[datetime] = Field(
        description="Created date and time as unix timestamp"
    )


class PaymentMethodChequeSchema(PaymentMethodChequeBase):
    id: Optional[int] = Field(description="ID of PaymentMethodChequeSchema resource")


class PaymentMethodChequeCreate(PaymentMethodChequeBase):
    pass


class PaymentMethodChequeUpdate(PaymentMethodChequeSchema):
    pass


# Shared properties
class PaymentMethodBase(BaseSchema):
    method: Optional[PaymentMethodTypes] = Field(
        description="Type of payment method used"
    )


class PaymentSplitTenderSchema(PaymentMethodBase):
    pay_split_value: float = Field(description="Split Tender Value")
    pay_split_type: str = Field(description="Split Tender Type")
    payment_method_token: str = Field(description="Split Payment Token")
    payment_split_calculated_value: float = Field(
        description="Calculated value of the payment split tender"
    )


class PartialPaymentRequestConfigBase(BaseSchema):
    defined_by: str = Field(description="Partial Payment Defined by")
    partial_payment_type: str = Field(
        description="Partial Payment Type percentage/amount"
    )
    partial_payment_value: float = Field(description="Partial Payment Value")
    due_date: datetime = Field(description="Due date of the payment")


class PartialPaymentRequestConfigCreateSchema(PartialPaymentRequestConfigBase):
    calculated_value: Optional[float] = Field(
        description="Calculated Value of the payment"
    )


class PartialPaymentRequestConfigSchema(PartialPaymentRequestConfigBase):
    id: int = Field(description="Id of the config")
    payment_request_id: Optional[int] = Field(description="Payment Request Id")
    created_at: Optional[datetime] = Field(
        description="Created date and time as unix timestamp"
    )
    updated_at: Optional[datetime] = Field(
        description="Updated date and time as unix timestamp"
    )
    deleted_at: Optional[datetime] = Field(
        description="Deleted date and time as unix timestamp"
    )


class PartialPaymentRequestConfigUpdateSchema(PartialPaymentRequestConfigBase):
    # object_id: Optional[int] = Field(description="Id of the config")
    defined_by: Optional[str] = Field(description="Partial Payment Defined by")
    partial_payment_type: Optional[str] = Field(
        description="Partial Payment Type percentage/amount"
    )
    due_date: Optional[datetime] = Field(description="Due date of the payment")
    partial_payment_value: Optional[float] = Field(description="Partial Payment Value")
    calculated_value: Optional[float] = Field(
        description="Calculated Value of the payment"
    )


class PaymentMethodSchema(PaymentMethodBase):
    id: int = Field(description="Id of PaymentMethod resource")
    is_connected: Optional[bool] = Field(
        description="Is this payment method connected to customer?"
    )
    payment_method_id: Optional[str] = Field(
        description="Unique id of the payment method, typically has the form pm_xxx"
    )
    scope: Optional[PaymentMethodScopes] = Field(
        description="Scope of this payment method's usage"
    )
    card_details: Optional[PaymentMethodCardSchema] = Field(
        description="Card details used for this payment method"
    )
    ach_details: Optional[PaymentMethodACHSchema] = Field(
        description="ACH details used for this payment method"
    )
    cheque_details: Optional[PaymentMethodChequeSchema] = Field(
        description="Cheque Details used for this payment Method"
    )
    created_at: Optional[datetime] = Field(
        description="Created date and time as unix timestamp"
    )
    updated_at: Optional[datetime] = Field(
        description="Updated date and time as unix timestamp"
    )
    deleted_at: Optional[datetime] = Field(
        description="Deleted date and time as unix timestamp"
    )
    customer: Optional[CustomerSchema] = Field(
        description="Customer of this PaymentMethod"
    )
    reference_id: Optional[str] = Field(description="Third party reference id")
    is_default: Optional[bool] = Field(
        description="Is this payment method default method of customer?"
    )
    is_deletable: Optional[bool] = Field(
        description="Is this payment method deletable?"
    )
    in_use: Optional[bool] = Field(
        description="Is this payment method is use for a payment request?"
    )
    billing_address: Optional[AddressSchema] = Field(
        description="Billing address associated with this payment method"
    )
    pay_split_type: Optional[str] = Field(
        description="Split Tender payment Type e.g. percentage/amount"
    )
    pay_split_value: Optional[float] = Field(description="Split Tender Payment Value")
    last_used_at: Optional[datetime] = Field(
        description="Last used date and time as unix timestamp"
    )


class PaymentMethodCreateRequestSchema(PaymentMethodBase):
    in_use: Optional[bool] = Field(
        description="Is this payment method is use for a payment request?"
    )
    card_details: Optional[PaymentMethodCardSchema] = Field(
        description="Card details used for this payment method"
    )
    ach_details: Optional[PaymentMethodACHSchema] = Field(
        description="ACH details used for this payment method"
    )
    cheque_details: Optional[PaymentMethodChequeSchema] = Field(
        description="ACH details used for this payment method"
    )


class PaymentRequestMethodSchema(BaseSchema):
    payment_method: PaymentMethodTypes = Field(
        description="Preferred payment method, (Card/ACH/Cash/Cheque)"
    )
    payment_method_token: Optional[str] = Field(
        description="Payment method token of the card"
    )
    pay_method_type: Optional[SplitPaymentTypes] = Field(
        description="Payment method split type, (percentage/amount)"
    )
    pay_method_value: Optional[float] = Field(
        description="Payment method split value according tp payment method split type"
    )
    calculated_value: Optional[float] = Field(
        description="Calcualted split value of the current method"
    )
    tokenization_provider: Optional[str] = Field(
        description="Payment method token type"
    )


class PaymentMethodUpdateRequestSchema(PaymentMethodBase):
    in_use: Optional[bool] = Field(
        description="Is this payment method is use for a payment request?"
    )
    is_connected: Optional[bool] = Field(
        description="Is this payment method connected to customer?"
    )


class CustomerPaymentMethodUpdateRequestSchema(BaseModel):
    is_default: Optional[bool] = Field(
        description="Is this payment method default for this customer?"
    )
    expire_month: Optional[str] = Field(description="Card expiry month")
    expire_year: Optional[str] = Field(description="Card expiry year")

class MerchantPaymentMethodSchema(BaseSchema):
    id: Optional[int] = Field(description="Id of PaymentMethod resource")
    method: Optional[str] = Field(description="Method of the payment e.g. card/ach")
    is_connected: Optional[bool] = Field(
        description="Is this payment method connected to customer?"
    )
    in_use: Optional[bool] = Field(
        description="Is this payment method is use for a payment request?"
    )
    card_details_id: Optional[int] = Field(
        description="Unique id of the card details"
    )
    ach_details_id: Optional[int] = Field(
        description="Unique id of the ACH details"
    )
    billing_address_id: Optional[int] = Field(
        description="Unique id of the billing address"
    )
    merchant_id: Optional[int] = Field(
        description="Unique id of the Merchant"
    )
    
    created_at: Optional[datetime] = Field(
        description="Created date and time as unix timestamp"
    )
    updated_at: Optional[datetime] = Field(
        description="Updated date and time as unix timestamp"
    )
    deleted_at: Optional[datetime] = Field(
        description="Deleted date and time as unix timestamp"
    )
    
class MerchantPaymentMethodCreateSchema(MerchantPaymentMethodSchema):
    pass


class MerchantPaymentMethodUpdateSchema(MerchantPaymentMethodSchema):
    pass
