from datetime import datetime
from typing import List, Optional, Dict
from src.apps.customers.schemas.customer_contact import (
    CustomerContactSchema,
)
from src.apps.customers.schemas.customer_common import CustomerListSchema
from src.apps.files.schemas.file_common import FileResponseSchema
from apps.merchants.schemas.merchant_common import MerchantSchema
from src.apps.payment_requests.schemas.payment_method import PaymentMethodSchema
from src.core.utils.enums import (
    InvoiceStatusTypes,
    PaymentMethodTypes,
)
from src.apps.payment_requests.enums import (
    PaymentAuthorizationTypes,
    PaymentFrequencies,
    PaymentRequestStatusTypes,
    PaymentCurrencies,
    SurchargeTypes,
)
from src.apps.payment_requests.schemas.payment_request_adjustment import (
    PaymentRequestAdjustmentsSchema,
)
from src.apps.payment_requests.schemas.recurring_payment_request import (
    RecurringPaymentRequestSchema,
)
from src.apps.payment_requests.schemas.split_payment_request import (
    SplitPaymentRequestSchema,
)
from src.apps.payment_requests.schemas.payment_request_customer import (
    PaymentRequestCustomersSchema,
)
from pydantic import Field, ConfigDict
from src.apps.base.schemas.common import BaseSchema
from src.apps.invoices.schemas.invoice_adjustment import InvoiceAdjustmentsSchema


class InvoicePaymentRequestLineItemSchema(BaseSchema):
    model_config = ConfigDict(from_attributes=True)
    
    id: int = Field(description="Id of Line item resource")
    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")
    product_id: Optional[int] = Field(default=None, description="Product id of the line items")
    cost: Optional[float] = Field(default=None, description="Cost value")
    upcharge: Optional[float] = Field(default=None, description="Upcharge value")


class InvoicePaymentRequestSchema(BaseSchema):
    model_config = ConfigDict(from_attributes=True)
    
    id: int = Field(description="Id of PaymentRequest resource")
    amount: Optional[float] = Field(
        default=None,
        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_method: Optional[PaymentMethodTypes] = Field(
        default=None,
        description="Preferred payment method, (Cards/ACH/etc)"
    )
    tax_type_text: Optional[str] = Field(
        default=None,
        description="Human readable text for the invoice status integer"
    )
    status: Optional[PaymentRequestStatusTypes] = Field(
        default=None,
        description="Status of payment request, (Pending/Cleared/etc)"
    )
    save_payment_method: Optional[bool] = Field(
        default=None,
        description="Indicates if the chosen payment method needs to be saved"
    )
    allow_tip: Optional[bool] = Field(default=None, description="Enables tipping")
    configure_adjustment: Optional[bool] = Field(
        default=None,
        description="Denotes if the payment request can be configured or not"
    )
    payment_request_adjustment: Optional[PaymentRequestAdjustmentsSchema] = Field(
        default=None,
        description="payment request Adjustment"
    )
    message: Optional[str] = Field(default=None, description="Additional message or comments")
    attachments: Optional[List[FileResponseSchema]] = Field(
        default=None,
        description="Attachments included in the payment request"
    )
    payment_methods: Optional[List[PaymentMethodSchema]] = Field(
        default=None,
        description="List of payment methods used in this payment request"
    )
    reference_id: Optional[str] = Field(default=None, description="Third party reference id")
    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"
    )
    payment_request_id: Optional[str] = Field(
        default=None,
        description="Unique id of payment request, typically has the form 'pr_xxx' "
    )
    shipping_fee: Optional[float] = Field(
        default=None,
        description="Shipping fees for the billable items."
    )
    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_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"
    )
    require_cvv: Optional[bool] = Field(default=None, description="Required cvv in payment")
    split_config: Optional[List[SplitPaymentRequestSchema]] = Field(
        default=None,
        description="Split config of the payment request"
    )
    recurring_config: Optional[RecurringPaymentRequestSchema] = Field(
        default=None,
        description="Split config of the payment request"
    )
    currency: PaymentCurrencies = Field(
        description="Three-letter ISO currency code, in lowercase."
    )
    payment_request_customers: Optional[List[PaymentRequestCustomersSchema]] = Field(
        default=None,
        description="Customers included in the payment request"
    )


# Shared properties
class InvoiceBase(BaseSchema):
    model_config = ConfigDict(from_attributes=True)
    
    amount: float = Field(description="Invoice due amount value", default=0)
    paid_amount: Optional[float] = Field(default=None, description="Invoice paid amount value")
    paid_date: Optional[datetime] = Field(
        default=None,
        description="Paid date and time as unix timestamp"
    )
    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"
    )
    next_due_date: Optional[datetime] = Field(
        default=None,
        description="Next due date and time as unix timestamp, only applicable for recurring payments"
    )
    tax_fee: Optional[int] = Field(default=0.0, description="Tax fees, if applicable")
    shipping_fee: Optional[int] = Field(
        default=0.0, description="Shipping fees, if applicable"
    )
    additional_fee: Optional[int] = Field(
        default=0.0, description="Additional fees, if applicable"
    )
    tip: Optional[int] = Field(default=0.0, description="Tax fees, if applicable")
    charge: Optional[int] = Field(default=0.0, description="Tax fees, if applicable")
    status: Optional[InvoiceStatusTypes] = Field(default=None, description="Invoice status")
    comments: Optional[str] = Field(default=None, description="Invoice comments")
    reference: Optional[str] = Field(default=None, description="Invoice reference")
    invoice_id: Optional[str] = Field(
        default=None,
        description="Invoice unique ID. Do not use this for create or update. This an autgenrated field"
    )
    merchant: Optional[MerchantSchema] = Field(default=None, description="Merchant of this Invoice")
    customer: Optional[CustomerListSchema] = Field(
        default=None,
        description="Customer of this Invoice"
    )
    payment_request: Optional[InvoicePaymentRequestSchema] = Field(
        default=None,
        description="Payment Request of this Invoice"
    )
    created_at: Optional[datetime] = Field(
        default=None,
        description="Created date and time as unix timestamp"
    )
    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"
    )
    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"
    )
    following: Optional[bool] = Field(default=None, description="Is following invoice")


class InvoiceSchema(InvoiceBase):
    model_config = ConfigDict(from_attributes=True)
    
    id: int = Field(description="Id of Invoice resource")
    invoice_literal: Optional[str] = Field(
        default=None,
        description="Invoice Literal, just a simple 9 digit code to identify the invoice in a human readable way"
    )
    download_url: Optional[str] = Field(default=None, description="Download url of the invoice")
    payment_url: Optional[str] = Field(default=None, description="Payment url of the invoice")
    status_text: Optional[str] = Field(
        default=None,
        description="Human readable text for the invoice status integer"
    )
    can_edit: Optional[bool] = Field(
        default=None,
        description="Is this payment request editable by the merchant"
    )
    payment_adjustment: Optional[PaymentRequestAdjustmentsSchema] = Field(
        default=None,
        description="Payment Adjustment"
    )
    adjustment: Optional[InvoiceAdjustmentsSchema] = Field(
        default=None,
        description="Invoice Adjustment"
    )
    line_items: Optional[List[InvoicePaymentRequestLineItemSchema]] = Field(
        default=None,
        description="Line items of this invoice"
    )
    product_details: Optional[List[Dict]] = Field(
        default=None,
        description="Connected product details list used for printing the packing slip"
    )
    payer: Optional[CustomerContactSchema] = Field(default=None, description="Payer of this invoice")
    approver: Optional[CustomerContactSchema] = Field(
        default=None,
        description="Approver of this invoice"
    )
    total_discount: Optional[float] = Field(default=None, description="Total discount of the invoice")
    surcharge_final_amount: Optional[float] = Field(
        default=None,
        description="surcharge details of the invoice"
    )
    days_until_due: Optional[int] = Field(default=None, description="Day until due invoice")
    due_amount: Optional[int] = Field(default=None, description="Total due amount")
    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"
    )


class InvoiceListSchema(InvoiceBase):
    model_config = ConfigDict(from_attributes=True)
    
    id: int = Field(description="Id of Invoice resource")
    invoice_literal: Optional[str] = Field(
        default=None,
        description="Invoice Literal, just a simple 9 digit code to identify the invoice in a human readable way"
    )
    download_url: Optional[str] = Field(default=None, description="Download url of the invoice")
    payment_url: Optional[str] = Field(default=None, description="Payment url of the invoice")
    status_text: Optional[str] = Field(
        default=None,
        description="Human readable text for the invoice status integer"
    )
    can_edit: Optional[bool] = Field(
        default=None,
        description="Is this payment request editable by the merchant"
    )
    payment_adjustment: Optional[PaymentRequestAdjustmentsSchema] = Field(
        default=None,
        description="Payment Adjustment"
    )
    customer: Optional[CustomerListSchema] = Field(
        default=None,
        description="Customer of this Invoice"
    )
    line_items: Optional[List[InvoicePaymentRequestLineItemSchema]] = Field(
        default=None,
        description="Line items of this invoice"
    )
    product_details: Optional[List[Dict]] = Field(
        default=None,
        description="Connected product details list used for printing the packing slip"
    )
    payer: Optional[CustomerContactSchema] = Field(default=None, description="Payer of this invoice")
    approver: Optional[CustomerContactSchema] = Field(
        default=None,
        description="Approver of this invoice"
    )
    total_discount: Optional[float] = Field(default=None, description="Total discount of the invoice")
    surcharge_final_amount: Optional[float] = Field(
        default=None,
        description="surcharge details of the invoice"
    )
    days_until_due: Optional[int] = Field(default=None, description="Day until due invoice")
    due_amount: Optional[int] = Field(default=None, description="Total due amount")
