from datetime import datetime
from typing import Dict, List, Optional
from src.apps.payment_requests.schemas.split_payment_request import SplitPaymentRequestSchema
from src.apps.payment_requests.schemas.recurring_payment_request import (
    RecurringPaymentRequestSchema,
)
from src.apps.payment_requests.schemas.payment_request_product import (
    PaymentRequestProductSchema,
)
from src.apps.base.schemas.common import AddressSchema
from src.apps.customers.schemas.customer_common import CustomerSchema
from src.apps.files.schemas.file_common import FileResponseSchema
from src.apps.merchants.schemas.merchant_common import MerchantSchema
from src.apps.payment_requests.schemas.payment_method import PaymentMethodSchema
from src.core.utils.enums import (
    PaymentAuthorizationTypes,
    PaymentCurrencies,
    PaymentFrequencies,
    PaymentMethodTypes,
    PaymentRequestStatusTypes,
    TransactionCategories,
    TransactionStatusTypes,
    TransactionSourceTypes,
    PaymentTypes,
)
from pydantic import Field
from src.apps.base.schemas.common import BaseSchema
from src.apps.invoices.schemas.invoice_common import InvoiceSchema
from src.apps.payment_requests.schemas.payment_request_customer import (
    PaymentRequestCustomersSchema,
)


class TransactionLineItemsSchema(BaseSchema):
    title: Optional[str] = Field(description="Name or title of line item")
    description: Optional[str] = Field(description="Description of line item")
    unit_price: float = Field(description="Price of line item")
    quantity: int = Field(description="Quantity of line item")
    tax: Optional[float] = Field(description="Tax amount of the product")
    discount: Optional[float] = Field(description="Discount details")
    discount_type: Optional[str] = Field(description="Discount Type")
    display_order: Optional[int] = Field(description="Display order of this line item")


class TransactionPaymentRequestSchema(BaseSchema):
    id: int = Field(description="Id of PaymentRequest resource")
    amount: Optional[float] = Field(
        description="Amount of PaymentRequest, accepts decimal input"
    )
    payment_frequency: Optional[PaymentFrequencies] = Field(
        description="Frequency of payment, (Split / Recurring / One-time)"
    )
    authorization_type: Optional[PaymentAuthorizationTypes] = Field(
        description="PaymentRequest authorisation type, (Pre-Authorized / Request-Authorization)"
    )
    payment_method: Optional[PaymentMethodTypes] = Field(
        description="Preferred payment method, (Cards/ACH/etc)"
    )
    status: Optional[PaymentRequestStatusTypes] = Field(
        description="Status of payment request, (Pending/Cleared/etc)"
    )
    save_payment_method: Optional[bool] = Field(
        description="Indicates if the chosen payment method needs to be saved"
    )
    allow_tip: Optional[bool] = Field(description="Enables tipping")
    configure_adjustment: Optional[bool] = Field(
        description="Denotes if the payment request can be configured or not"
    )
    tax_type: Optional[str] = Field(description="Tax Type details")
    message: Optional[str] = Field(description="Additional message or comments")
    attachments: Optional[List[FileResponseSchema]] = Field(
        description="Attachments included in the payment request"
    )
    split_config: Optional[List[SplitPaymentRequestSchema]] = Field(
        description="Configuration for split payment request"
    )
    recurring_config: Optional[RecurringPaymentRequestSchema] = Field(
        description="Configuration for recurring payment request"
    )
    payment_methods: Optional[List[PaymentMethodSchema]] = Field(
        description="List of payment methods used in this payment request"
    )
    attachments: Optional[List[FileResponseSchema]] = Field(
        description="Attachments included in the payment request"
    )
    merchant: Optional[MerchantSchema] = Field(
        description="Merchant of this Payment Request"
    )
    reference_id: Optional[str] = Field(description="Third party reference id")
    line_items: Optional[List[TransactionLineItemsSchema]] = Field(
        description="Any transactional items included in the payment request"
    )
    products: Optional[List[PaymentRequestProductSchema]] = Field(
        description="Any transactional items included in the payment request"
    )
    can_edit: Optional[bool] = Field(
        description="Is this payment request editable by the merchant"
    )
    payment_request_literal: Optional[str] = Field(
        description="Payment Request Literal, just a simple 9 digit code to identify the payment request in a human readable way"
    )
    payment_request_id: Optional[str] = Field(
        description="Unique id of payment request, typically has the form 'pr_xxx' "
    )
    payment_request_customers: Optional[List[PaymentRequestCustomersSchema]] = Field(
        description="Customers included in the payment request"
    )
    payment_type: Optional[PaymentTypes] = Field(description="Transaction type")


# Shared properties
class TransactionBase(BaseSchema):
    txn_amount: float = Field(description="Transaction amount value")
    txn_type: Optional[PaymentMethodTypes] = Field(description="Transaction type")
    txn_status: Optional[TransactionStatusTypes] = Field(
        description="Transaction status"
    )
    ocurred_at: Optional[datetime] = Field(
        description="Transaction date and time as unix timestamp"
    )
    txn_id: Optional[str] = Field(
        description="Transaction ID. Do not use this for create or update. This an autgenrated field"
    )
    txn_literal: Optional[str] = Field(
        description="Transaction Literal, just a simple 9 digit code to identify the transaction in a human readable way"
    )
    reference_id: Optional[str] = Field(description="Third party reference id")
    description: Optional[str] = Field(
        description="Brief description of the transaction"
    )
    currency: Optional[PaymentCurrencies] = Field(
        default=PaymentCurrencies.USD, description="Payment currency to be used"
    )
    platform_fee_amount: Optional[int] = Field(
        default=0.0, description="Third party gas fees"
    )
    billing_name: Optional[str] = Field(
        description="Optional name used for billing purpose"
    )
    merchant: Optional[MerchantSchema] = Field(
        description="Merchant of this Transaction account"
    )
    customer: Optional[CustomerSchema] = Field(
        description="Customer of this Transaction account"
    )
    payment_request: Optional[TransactionPaymentRequestSchema] = Field(
        description="Payment Request of this Transaction account"
    )
    payment_method: Optional[PaymentMethodSchema] = Field(
        description="Payment Method of this Transaction account"
    )


class TransactionSchema(TransactionBase):
    id: int = Field(description="Id of Transaction resource")
    category: Optional[TransactionCategories] = Field(
        default=TransactionCategories.CHARGE, description="Transaction category"
    )
    charge_type: Optional[str] = Field(
        description="Type of charge being done. Credit or Debit?"
    )
    additional_info: Optional[Dict] = Field(
        description="Optional key value pair for storing extra data in transaction. The same will be returned in invoices of this transaction."
    )
    # payment_method: Optional[PaymentMethodSchema] = Field(description="Payment Method of this Transaction account")
    status_text: Optional[str] = Field(
        description="Human readable text for the invoice status integer"
    )
    refundable_balance: Optional[float] = Field(
        description="Available refund balance amount for this transaction"
    )
    billing_address: Optional[AddressSchema] = Field(
        description="Address used for billing purpose"
    )
    invoices: Optional[List[InvoiceSchema]] = Field(
        description="Invoice details of the transaction"
    )
    payment_request: Optional[TransactionPaymentRequestSchema] = Field(
        description="Payment Request details of the transaction"
    )
    auth_amount: Optional[float] = Field(
        description="Authorization amount of the transaction"
    )
    # attachments: Optional[List[Dict]] = Field(
    #     description="All attachments of the transaction"
    # )
    txn_source: Optional[TransactionSourceTypes] = Field(description="Transaction type")
