from typing import Optional, List, Dict
from pydantic import Field, BaseModel
from src.apps.base.schemas.common import BaseSchema
from fastapi import Query
from src.apps.customers.schemas.customer_contact import CustomerContactSchema
from src.apps.customers.schemas.customer_common import CustomerSchema
from src.apps.payment_requests.schemas.payment_request_common import PaymentRequestBase
from datetime import datetime
from src.apps.payment_requests.enums import (
    PaymentCurrencies,
    PaymentRequestStatusTypes,
)
from .recurring_payment_request import RecurringPaymentRequestSchema
from src.apps.payment_requests.schemas.payment_request_customer import (
    PaymentRequestCustomersSchema,
)
from src.apps.files.schemas.file_common import FileResponseSchema
from src.apps.payment_requests.schemas.payment_request_common import PaymentMethodSchema
from src.apps.transactions.schemas.transaction_common import TransactionSchema
from src.apps.merchants.schemas.merchant_common import MerchantSchema


class PaymentRequestAuthorizationsBase(BaseSchema):
    authorization_type: Optional[str] = Field(
        default=None, description="Authorization type of the payment e.g.-sms/sign"
    )
    authorization_date: Optional[datetime] = Field(
        description="Date of the Authorization"
    )
    authorization_value: Optional[str] = Field(description="Value of the authorization")
    is_verified: Optional[bool] = Field(description="is the authorization verified")
    payment_request_id: Optional[int] = Field(description="id of the payment request")
    customer_id: Optional[int] = Field(description="id of the customer")
    payer_id: Optional[int] = Field(description="id of the payer")
    merchant_id: Optional[int] = Field(description="id of the merchant")
    signing_name: Optional[str] = Field(
        description="Signing name for the authorization"
    )
    ip_address: Optional[str] = Field(description="Ip address of the authorization")
    auth_metadata: Optional[Dict] = Field(
        description="Optional key value pair for storing extra data in authorization. The same will be returned in invoices of this authorization."
    )


class AuthorizationPaymentRequestSchema(PaymentRequestBase):
    id: int = Field(description="Id of PaymentRequest resource")
    status: Optional[PaymentRequestStatusTypes] = Field(
        description="Status of payment request"
    )
    status_text: Optional[str] = Field(
        description="Human readable text for the payment request status integer"
    )
    merchant: Optional[MerchantSchema] = Field(description="Merchant details")
    currency: PaymentCurrencies = Field(
        description="Three-letter ISO currency code, in lowercase."
    )
    payment_request_id: Optional[str] = Field(
        description="Unique id of payment request, typically has the form 'pr_xxx' "
    )
    due_date: Optional[datetime] = Field(
        description="Due date and time as unix timestamp"
    )
    billing_date: Optional[datetime] = Field(
        description="Billing date and time as unix timestamp"
    )
    created_at: Optional[datetime] = Field(
        description="Created date and time as unix timestamp"
    )
    payment_redirect_url: Optional[str] = Field(
        description="Redirection url of the payment"
    )
    reference_id: Optional[str] = Field(description="Third party reference id")
    is_authorized: Optional[bool] = Field(
        description="Is this payment request authorized by the customer?"
    )
    can_edit: Optional[bool] = Field(
        description="Is this payment request editable by the merchant"
    )
    payment_split_frequency: Optional[str] = Field(
        description="Payment Split Frequency"
    )
    recurring_config: Optional[RecurringPaymentRequestSchema] = Field(
        description="Configuration for recurring payment request"
    )
    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"
    )
    status_text: Optional[str] = Field(
        description="Human readable text for the payment request status integer"
    )
    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"
    )
    payment_url: Optional[str] = Field(description="Payment url of the payment request")
    attachments: Optional[List[FileResponseSchema]] = Field(
        description="Attachments included in the payment request"
    )
    payment_request_customers: Optional[List[PaymentRequestCustomersSchema]] = Field(
        description="Customers included in the payment request"
    )
    payment_methods: Optional[List[PaymentMethodSchema]] = Field(
        description="List of payment methods used in this payment request"
    )
    transactions: Optional[List[TransactionSchema]] = Field(
        description="Transaction details of this payment request when the payment has been made."
    )


class ListAuthorizationPaymentRequestSchema(PaymentRequestBase):
    id: int = Field(description="Id of PaymentRequest resource")
    status: Optional[PaymentRequestStatusTypes] = Field(
        description="Status of payment request"
    )
    merchant: Optional[MerchantSchema] = Field(description="Merchant Details")
    status_text: Optional[str] = Field(
        description="Human readable text for the payment request status integer"
    )
    currency: PaymentCurrencies = Field(
        description="Three-letter ISO currency code, in lowercase."
    )
    payment_request_id: Optional[str] = Field(
        description="Unique id of payment request, typically has the form 'pr_xxx' "
    )
    due_date: Optional[datetime] = Field(
        description="Due date and time as unix timestamp"
    )
    billing_date: Optional[datetime] = Field(
        description="Billing date and time as unix timestamp"
    )
    is_authorized: Optional[bool] = Field(
        description="Is this payment request authorized by the customer?"
    )
    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"
    )
    status_text: Optional[str] = Field(
        description="Human readable text for the payment request status integer"
    )
    created_at: Optional[datetime] = Field(
        description="Created date and time as unix timestamp"
    )


class PaymentRequestAuthorizationsSchema(PaymentRequestAuthorizationsBase):
    id: int = Field(description="Id of Payment Request Product resource")
    authorization_literal: Optional[str] = Field(description="Literal of Authorization")
    authorization_id: Optional[str] = Field(description="Unique id of Authorization")
    payer: Optional[CustomerContactSchema] = Field(
        description="Payer details of the Authorizaion"
    )
    customer: Optional[CustomerSchema] = Field(
        description="Customer details of the Authorizaion"
    )
    payment_request: Optional[AuthorizationPaymentRequestSchema] = Field(
        description="Payment Request details of the Authorizaion"
    )
    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."
    )
    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"
    )


class ListPaymentRequestAuthorizationsSchema(PaymentRequestAuthorizationsBase):
    id: int = Field(description="Id of Payment Request Product resource")
    authorization_literal: Optional[str] = Field(description="Literal of Authorization")
    authorization_id: Optional[str] = Field(description="Unique id of Authorization")
    payer: Optional[CustomerContactSchema] = Field(
        description="Payer details of the Authorizaion"
    )
    customer: Optional[CustomerSchema] = Field(
        description="Customer details of the Authorizaion"
    )
    payment_request: Optional[ListAuthorizationPaymentRequestSchema] = Field(
        description="Payment Request details of the Authorizaion"
    )
    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"
    )


class PaymentRequestAuthorizationsCreate(PaymentRequestAuthorizationsBase):
    pass


class PaymentRequestAuthorizationsUpdate(PaymentRequestAuthorizationsBase):
    object_id: Optional[int] = Field(description="ID of the item")


class AuthorizationFilterSchema(BaseModel):
    search: Optional[str] = Query(
        default=None,
        description="Search by authorization type,customer name, payer name",
    )
    authorization_type: Optional[str] = Query(
        default=None, description="Authorization type of the payment request"
    )
    customer_id: Optional[str] = Query(
        default=None, description="Payer id of the payment request"
    )
    payer_id: Optional[str] = Query(
        default=None, description="Payer id of the payment request"
    )
    payment_request_id: Optional[str] = Query(
        default=None, description="Payment Request id"
    )
    ip_address: Optional[str] = Query(
        default=None, description="IP Address of the authorization"
    )
    invoice_id: Optional[str] = Query(default=None, description="Invoice ID")
    status: Optional[str] = Query(default=None, description="status")
    payment_frequency: Optional[str] = Query(default=None, description="Frequency Type")
