from datetime import datetime
from typing import List, Optional, Dict
from pydantic import Field, ConfigDict
from src.apps.payment_requests.schemas.payment_request_product import (
    PaymentRequestProductSchema,
)
from src.apps.payment_requests.schemas.payment_request_customer import (
    PaymentRequestCustomersSchema,
)
from src.apps.files.schemas.file_common import FileResponseSchema
from src.apps.transactions.schemas.transaction_common import TransactionSchema
from src.apps.users.schemas.user_common import UserResponseSchema
from src.apps.merchants.schemas.merchant_common import MerchantSchema
from src.core.utils.enums import (
    PaymentMethodTypes,
    PaymentTypes,
)
from src.apps.payment_requests.enums import (
    PaymentAuthorizationTypes,
    PaymentCurrencies,
    PaymentFrequencies,
    PaymentRequestStatusTypes,
    DiscountTypes,
    SurchargeTypes,
)
from src.apps.base.schemas.common import BaseSchema, AddressSchema
from .payment_method import PaymentMethodSchema
from .recurring_payment_request import RecurringPaymentRequestSchema
from .split_payment_request import SplitPaymentRequestSchema
from src.apps.invoices.schemas.invoice_common import InvoiceSchema
from src.apps.payment_requests.schemas.payment_request_adjustment import (
    PaymentRequestAdjustmentsSchema,
)


class PaymentRequestLineItemBase(BaseSchema):
    model_config = ConfigDict(from_attributes=True)
    
    title: Optional[str] = Field(default=None, description="Name or title of line item")
    description: Optional[str] = Field(default=None, description="Description of line item")
    unit_price: float = Field(description="Price of line item")
    quantity: int = Field(default=1, description="Quantity of line item")
    tax: Optional[float] = Field(default=None, description="Tax amount of the product")
    display_order: Optional[int] = Field(default=None, description="Display order of this line item")
    product_id: Optional[int] = Field(default=None, description="Product id of the line items")
    tax_amount: Optional[float] = Field(
        default=0.00,
        description="Tax amount of the line items"
    )
    discount: Optional[float] = Field(
        default=None,
        description="Discount amount/percentage for line items"
    )
    discount_type: Optional[DiscountTypes] = Field(
        default=None,
        description="Discount type of the line items"
    )
    cost: Optional[float] = Field(default=None, description="Cost amount for line items")
    upcharge: Optional[float] = Field(default=None, description="Upcharge amount for line items")


class PaymentRequestLineItemSchema(PaymentRequestLineItemBase):
    model_config = ConfigDict(from_attributes=True)
    
    id: int = Field(description="Id of Line Item resource")


class PaymentRequestLineItemCreate(PaymentRequestLineItemBase):
    model_config = ConfigDict(from_attributes=True)
    
    tax_id: Optional[str] = Field(default=None, description="Tax it of the line items")


class PaymentRequestLineItemUpdate(PaymentRequestLineItemBase):
    model_config = ConfigDict(from_attributes=True)
    
    tax_id: Optional[str] = Field(default=None, description="Tax it of the line items")
    object_id: Optional[int] = Field(default=None, description="ID of the line item")


# Shared properties
class PaymentRequestBase(BaseSchema):
    model_config = ConfigDict(from_attributes=True)
    
    amount: Optional[float] = Field(
        default=0,
        description="Amount of PaymentRequest, accepts decimal input"
    )
    payment_frequency: Optional[PaymentFrequencies] = Field(
        default=None,
        description="Frequency of payment, (Split / Recurring / One-time)"
    )
    authorization_type: Optional[PaymentAuthorizationTypes] = Field(
        default=None,
        description="PaymentRequest authorisation type, (Pre-Authorized / Request-Authorization)"
    )
    payment_split_frequency: Optional[str] = Field(
        default=None,
        description="Payment Split Frequency"
    )
    reference: Optional[str] = Field(default=None, description="Invoice reference")
    shipping_fee: Optional[float] = Field(
        default=None,
        ge=0, 
        le=99999, 
        description="Shipping fees for the billable items."
    )
    allow_tip: Optional[bool] = Field(default=None, description="Enables tipping")
    is_certified: Optional[bool] = Field(default=None, description="Is payer authorization obtained?")
    configure_adjustment: Optional[bool] = Field(
        default=None,
        description="Denotes if the payment request can be configured or not"
    )
    message: Optional[str] = Field(default=None, description="Additional message or comments")
    description: Optional[str] = Field(default=None, description="Brief description of the payment")
    tax_percent: Optional[float] = Field(
        default=0.0,
        description="Tax percentage, if applicable"
    )
    require_billing_address: Optional[bool] = Field(
        default=None,
        description="Required billing address in payment"
    )
    require_sms_authorization: Optional[bool] = Field(
        default=None,
        description="Required SMS Authorization in payment"
    )
    require_cvv: Optional[bool] = Field(default=None, description="Required cvv in payment")
    require_shipping_address: Optional[bool] = Field(
        default=None,
        description="Required shipping address in payment"
    )
    require_signature_authorization: Optional[bool] = Field(
        default=None,
        description="Required Signature Authorization in payment"
    )
    enable_email: Optional[bool] = Field(
        default=None,
        description="If true, the customer would receive email notifications for this payment request"
    )
    enable_sms: Optional[bool] = Field(
        default=None,
        description="If true, the customer would receive sms notifications for this payment request"
    )
    enable_email_receipt: Optional[bool] = Field(
        default=None,
        description="If true, the customer would receive email notifications on success for this payment request"
    )
    enable_sms_receipt: Optional[bool] = Field(
        default=None,
        description="If true, the customer would receive sms notifications on success for this payment request"
    )
    tax_type: Optional[str] = Field(default=None, description="Tax type")
    invoice_terms: Optional[str] = Field(default=None, description="Invoice Term as a whole HTML string for Pdfs")


class PaymentRequestSchema(PaymentRequestBase):
    model_config = ConfigDict(from_attributes=True)
    
    id: int = Field(description="Id of PaymentRequest resource")
    status: Optional[PaymentRequestStatusTypes] = Field(
        default=None,
        description="Status of payment request"
    )
    status_text: Optional[str] = Field(
        default=None,
        description="Human readable text for the payment request status integer"
    )
    tax_type_text: Optional[str] = Field(
        default=None,
        description="Human readable text for the invoice status integer"
    )
    currency: PaymentCurrencies = Field(
        description="Three-letter ISO currency code, in lowercase."
    )
    payment_request_id: Optional[str] = Field(
        default=None,
        description="Unique id of payment request, typically has the form 'pr_xxx' "
    )
    due_date: Optional[datetime] = Field(
        default=None,
        description="Due date and time as unix timestamp"
    )
    billing_date: Optional[datetime] = Field(
        default=None,
        description="Billing date and time as unix timestamp"
    )
    created_at: Optional[datetime] = Field(
        default=None,
        description="Created date and time as unix timestamp"
    )
    shipping_address: Optional[AddressSchema] = Field(
        default=None,
        description="Shipping Address of the payment request"
    )
    split_config: Optional[List[SplitPaymentRequestSchema]] = Field(
        default=None,
        description="Configuration for split payment request"
    )
    payment_request_adjustment: Optional[PaymentRequestAdjustmentsSchema] = Field(
        default=None,
        description="payment request Adjustment"
    )
    recurring_config: Optional[RecurringPaymentRequestSchema] = Field(
        default=None,
        description="Configuration for recurring payment request"
    )
    line_items: Optional[List[PaymentRequestLineItemSchema]] = Field(
        default=None,
        description="Any transactional items included in the payment request"
    )
    products: Optional[List[PaymentRequestProductSchema]] = Field(
        default=None,
        description="Any products included in the payment request"
    )
    payment_request_customers: Optional[List[PaymentRequestCustomersSchema]] = Field(
        default=None,
        description="Customers included in the payment request"
    )
    attachments: Optional[List[FileResponseSchema]] = Field(
        default=None,
        description="Attachments included in the payment request"
    )
    merchant: Optional[MerchantSchema] = Field(
        default=None,
        description="Merchant of this Payment Request"
    )
    created_by: Optional[UserResponseSchema] = Field(
        default=None,
        description="Creator of this Payment Request"
    )
    payment_methods: Optional[List[PaymentMethodSchema]] = Field(
        default=None,
        description="List of payment methods used in this payment request"
    )
    payment_redirect_url: Optional[str] = Field(
        default=None,
        description="Redirection url of the payment"
    )
    transactions: Optional[List[TransactionSchema]] = Field(
        default=None,
        description="Transaction details of this payment request when the payment has been made."
    )
    payment_schedule: Optional[List[Dict]] = Field(
        default=None,
        description="Payment Schedules for the payment request"
    )
    reference_id: Optional[str] = Field(default=None, description="Third party reference id")
    is_authorized: Optional[bool] = Field(
        default=None,
        description="Is this payment request authorized by the customer?"
    )
    can_edit: Optional[bool] = Field(
        default=None,
        description="Is this payment request editable by the merchant"
    )
    payment_request_literal: Optional[str] = Field(
        default=None,
        description="Payment Request Literal, just a simple 9 digit code to identify the payment request in a human readable way"
    )
    is_email_enabled: Optional[bool] = Field(
        default=None,
        description="If true, the customer would receive email notifications for this payment request"
    )
    is_sms_enabled: Optional[bool] = Field(
        default=None,
        description="If true, the customer would receive sms notifications for this payment request"
    )
    has_remaining_payments: Optional[bool] = Field(
        default=None,
        description="If true, the payment request has remaining payments to be fetched from customer"
    )
    updated_at: Optional[datetime] = Field(
        default=None,
        description="Updated date and time as unix timestamp"
    )
    deleted_at: Optional[datetime] = Field(
        default=None,
        description="Deleted date and time as unix timestamp"
    )
    invoice: Optional[InvoiceSchema] = Field(
        default=None,
        description="Invoioce details of the payment request"
    )
    payment_url: Optional[str] = Field(default=None, description="Payment url of the payment request")
    is_surcharge_enabled: Optional[bool] = Field(
        default=None,
        description="Surcharge enabled for cost adjustment"
    )
    surcharge_type: Optional[SurchargeTypes] = Field(
        default=None,
        description="Surcharge type inclusive/exclusive"
    )
    payment_type: Optional[PaymentTypes] = Field(
        default=None,
        description="Surcharge type receive_payment/send_payment"
    )


class PaymentScheduleSchema(BaseSchema):
    model_config = ConfigDict(from_attributes=True)
    
    due_date: datetime = Field(description="Due date for the payment")
    due_amount: float = Field(description="Due amount for the payment")
