from enum import Enum, IntEnum
from typing import Any, Dict


class WellDocumentedIntEnum(IntEnum):
    @classmethod
    def __get_pydantic_json_schema__(cls, _core_schema, handler):
        """Generate JSON schema for Pydantic v2 compatibility."""
        json_schema = handler(_core_schema)
        
        # Add enum descriptions while maintaining proper schema structure
        json_schema['type'] = 'integer'
        json_schema['enum'] = [choice.value for choice in cls]
        
        # Add descriptions as a custom property
        json_schema['x-enum-descriptions'] = [
            f"{choice.name.lower()} = {choice.value}" for choice in cls
        ]
        
        return json_schema

class PaymentCurrencies(str, Enum):
    """PaymentCurrencies"""

    AUD = "aud"
    CAD = "cad"
    DKK = "dkk"
    EUR = "eur"
    HKD = "hkd"
    JPY = "jpy"
    NZD = "nzd"
    NOK = "nok"
    GBP = "gbp"
    ZAR = "zar"
    SEK = "sek"
    CHF = "chf"
    USD = "usd"

class FileTypes(str, Enum):
    """Message Types"""

    PROFILE_AVATAR = "profile_avatar"
    DOCUMENT = "document"
    MERCHANT_DOCUMENT = "merchant_document"
    INVOICE_DOCUMENT = "invoice_document"
    RECEIPT_DOCUMENT = "receipt_document"
    THUMBNAIL = "thumbnail"
    GALLERY = "gallery"
    CONTRACT = "contract"


class FileSizeUnits(Enum):
    BYTES = 1
    KB = 2
    MB = 3
    GB = 4


class PaymentRequestType(str, Enum):
    "payment Request Type"

    INVOICE = "invoice"
    CHECKOUT = "checkout"
    PAYMENT_REQUEST = "payment_request"


class PaymentMethodTypes(str, Enum):
    """Message Status"""

    CARD = "card"
    ACH = "ach"
    WALLET = "wallet"
    UPI = "upi"
    CASH = "cash"
    CHEQUE = "cheque"


class ProductTypes(str, Enum):
    """Product Types"""
    
    SERVICE = "service"  # Maps to 0
    PRODUCT = "product"  # Maps to 1


class ProductFilterTypes(str, Enum):
    """Product Filter Types"""

    COST_PRICE = "cost_price"
    SALE_PRICE = "sale_price"
    TAX = "tax"
    QUANTITY = "quantity"


class FilterOperators(str, Enum):
    """Filter Operators"""

    EQUAL_TO = "equal_to"
    IN_BETWEEN = "in_between"
    IS_GREATER_THAN = "is_greater_than"
    IS_LESS_THAN = "is_less_than"
    IS_AFTER = "is_after"
    IS_BEFORE = "is_before"
    IS_IN_THE_LAST = "is_in_the_last"


class PaymentMethodScopes(str, Enum):
    """Message Status"""

    MERCHANT = "merchant"
    CUSTOMER = "customer"


class AuthorizationRecordTypes(str, Enum):
    SMS = "SMS"
    SIGNATURE = "SIGN"
    CHECKBOX = "CHECKBOX"


class CheckoutStatusTypes(WellDocumentedIntEnum):
    """Payment Request Status"""

    CREATED = 100  # when just created and payment not started
    UPDATED = 101  # if payment request is updated.
    DRAFT = 102  # if payment request is saved as draft
    AWAITING_APPROVAL = 203
    CANCELLED = 700  # if payment req is cancelled by merchant
    EXPIRED = 900  # If the payment request is expired and cannot be used anymore


class InvoiceStatusTypes(WellDocumentedIntEnum):
    """Invoice Status"""

    CREATED = 100  # when just created and payment not started
    UPDATED = 101  # if invoice is updated, after it was submitted.
    DRAFT = 102  # If invoice is saved as draft.
    PENDING = 200  # when invoice is created (before 7 days of payment)
    WAITING = 202
    AWAITING_APPROVAL = 201
    CAPTURED = 203
    PAID = 300  # if payment successfull
    PARTIALLY_PAID = 301  # If payment was made, but more payments are required
    AUTHORIZED = 302  # If the customer has authorised the payment
    FAILED = 400  # if invoice fails for any reason
    OVERDUE = 401  # if invoice due date exceeded, and payment has not been made yet
    CANCELLED = 500  # if invoice is cancelled by merchant


class PaymentScheduleStatusTypes(str, Enum):
    """payment schedule status"""

    PAID = "paid"
    PAST_DUE = "past_due"
    CURRENT = "current"
    FUTURE = "future"
    UP_NEXT = "up_next"


class TransactionStatusTypes(WellDocumentedIntEnum):
    """transaction Status"""

    PENDING = (
        100  # when transaction has been sent to tilled but no status has been received
    )
    PAID = 200  # when transaction was successful
    CAPTURED = 201
    FAILED = 300  # when transaction has failed
    REFUNDED = 400  # when transaction has been refunded completely
    PARTIALLY_REFUNDED = 401  # when transaction has been refunded partially


class PlanType(str, Enum):
    SPLIT = "split"
    RECURRING = "recurring"


class TemplateTypes(WellDocumentedIntEnum):
    """Template Types"""

    EMAIL = 100
    SMS = 200
    PDF = 300


class TemplateStatusTypes(WellDocumentedIntEnum):
    """Template Status Types"""

    PUBLISHED = 100
    DRAFT = 200


class SiteTemplateKeys(str, Enum):
    """Site Template Keys"""

    EMAIL_ACCOUNT_VERIFICATION = "email_account_verification"
    EMAIL_ACCOUNT_INVITATION = "email_account_invitation"
    EMAIL_REQUEST_PAYMENT_AUTHORIZATION_DECLINED = (
        "email_request_payment_authorization_declined"
    )
    EMAIL_CONTRACT = "email_contract"
    EMAIL_ACCOUNT_TWOFA = "email_account_twofa"
    EMAIL_ACCOUNT_WELCOME = "email_account_welcome"
    EMAIL_ACCOUNT_PASSWORD_RESET_LINK = "email_account_password_reset_link"
    EMAIL_ACCOUNT_PASSWORD_RESET_TOTP = "email_account_password_reset_totp"
    EMAIL_REQUEST_ONETIME_PAYMENT_AUTHORIZATION = (
        "email_request_onetime_payment_authorization"
    )
    EMAIL_DUE_REMINDER = "email_due_reminder"
    EMAIL_REQUEST_SPLIT_PAYMENT_AUTHORIZATION = (
        "email_request_split_payment_authorization"
    )
    EMAIL_TRANSACTION_FAILED = "email_transaction_failed"
    EMAIL_REQUEST_RECURRING_PAYMENT_AUTHORIZATION = (
        "email_request_recurring_payment_authorization"
    )
    EMAIL_REQUEST_ONETIME_PAYMENT_AUTHORIZATION_APPROVER = (
        "email_request_onetime_payment_authorization_approver"
    )
    EMAIL_REQUEST_SPLIT_PAYMENT_AUTHORIZATION_APPROVER = (
        "email_request_split_payment_authorization_approver"
    )
    EMAIL_REQUEST_RECURRING_PAYMENT_AUTHORIZATION_APPROVER = (
        "email_request_recurring_payment_authorization_approver"
    )
    EMAIL_REQUEST_TENDER_AUTHORIZATION = "email_request_tender_authorisation"
    EMAIL_REQUEST_SMS_AUTHORIZATION = "email_request_sms_authorization"
    EMAIL_TRANSACTION_RECEIPT = "email_transaction_receipt"
    EMAIL_REFUND_INITIATED = "email_refund_initiated"
    EMAIL_REFUND_SUCCEEDED = "email_refund_succeeded"
    EMAIL_TILLED_ONBOARD_APPROVED = "email_tilles_onboard_approved"
    EMAIL_TILLED_ONBOARD_REJECTED = "email_tilles_onboard_rejected"
    EMAIL_CHECKOUT_SEND_MESSAGE = "email_checkout_send_message"
    SMS_CHECKOUT_SEND_MESSAGE = "sms_checkout_send_message"
    SMS_REQUEST_ONETIME_PAYMENT_AUTHORIZATION = (
        "sms_request_onetime_payment_authorization"
    )
    SMS_REQUEST_SPLIT_PAYMENT_AUTHORIZATION = "sms_request_split_payment_authorization"
    SMS_REQUEST_RECURRING_PAYMENT_AUTHORIZATION = (
        "sms_request_recurring_payment_authorization"
    )
    SMS_REQUEST_MERCHANT_LOGIN_VERIFICATION_CODE = (
        "sms_request_merchant_login_verification_code"
    )
    SMS_REQUEST_AUTHORIZATION = "sms_request_authorization"
    SMS_TRANSACTION_RECEIPT = "sms_transaction_receipt"
    PDF_PAYMENT_INVOICE = "pdf_payment_invoice"
    PDF_TRANSACTION_RECEIPT = "pdf_transaction_receipt"
    PDF_CONTRACT = "pdf_contract"
    EMAIL_ACCOUNT_APPROVED = "email_account_approved"
    EMAIL_ONBOARDING_PAYMENT_NOTIFICATION = "onboarding_payment_notification"
    EMAIL_ACCOUNT_PASSWORD_RESET_SUCCEEDED = "email_account_password_reset_succeeded"
    SMS_ACCOUNT_PASSWORD_RESET_SUCCEEDED = "sms_account_password_reset_succeeded"
    EMAIL_PAYER_WELCOME_ACCOUNT = "email_payer_welcome_account"
    EMAIL_SCHEDULED_PAYMENT_SUCCEEDED = "email_scheduled_payment_succeeded"
    EMAIL_TRANSACTION_CANCELED = "email_transaction_canceled"
    EMAIL_REQUEST_OVERDUE = "email_request_overdue"
    EMAIL_ACCOUNT_PASSWORD_RESET_LINK_MERCHANT = (
        "email_account_password_reset_link_merchant"
    )
    SMS_CONTRACT = "sms_contract"


class TransactionCategories(str, Enum):
    """Message Status"""

    CHARGE = "charge"
    DISPUTE = "dispute"
    REFUND = "refund"
    PAYOUT = "payout"
    CAPTURED = "captured"
    FAILED = "failed"


class TransactionTypes(str, Enum):
    """Message Status"""

    SUBSCRIPTION = "subscription"
    PAYMENT_TERMINAL = "payment_terminal"


class RecurringPaymentTimeIntervals(str, Enum):
    """Message Status"""

    FIRST = "first"
    LAST = "last"


class RecurringPaymentAutopayTypes(str, Enum):
    """Message Status"""

    IMMEDIATE = "immediate"
    ON_DATE = "on_date"
    ON_COUNT = "on_count"


class SettingsInputFieldTypes(str, Enum):
    """Message Status"""

    SELECT = "select"
    MULTISELECT = "multiselect"
    INPUT = "input"
    TEXT = "text"
    TEXTAREA = "textarea"
    NUMBER = "number"
    RADIO = "radio"
    CHECKBOX = "checkbox"
    TIMESTAMP = "timestamp"
    FIELD_ARRAY = "field_array"
    DUAL_INPUT = "dual_input"


class ContractsIntervals(str, Enum):
    """Message Status"""

    DAY = "day"
    WEEK = "week"
    MONTH = "month"
    QUARTER = "quarter"
    YEAR = "year"


class ContractStatusTypes(WellDocumentedIntEnum):
    """Contract Status"""

    PENDING = 100  # contarct created
    UPDATED = 101  # if contract is updated.
    DRAFT = 102  # if contract is saved as draft
    AWAITING_APPROVAL = 200  # If contract is pending for approval
    SIGNED = 300  # If the contract has been signed by signer
    UNSIGNED = 301  # if the contract has not been signed yet by signer
    EXPIRED = 900  # If the contract is expired and cannot be used anymore
    CANCELLED = 901  # if the contract has been declined


class ContractTermTypes(str, Enum):
    """Contract Term Types"""

    NO_TERM = "no_term"
    SPECIFIC_TERM = "specific_term"


class AddressTypes(str, Enum):
    """Message Status"""

    RESIDENCE = "residence"
    BILLING = "billing"
    SHIPPING = "shipping"
    BUSINESS = "business"
    LEGAL = "legal"


class ContactTypes(str, Enum):
    """Merchant contact status"""

    USER = "user"
    TRUST = "trust"


class BusinessCategories(str, Enum):
    ACCT = "ACCT"
    ART = "ART"
    BEAUTY = "BEAUTY"
    CATERING = "CATERING"
    CHARITY = "CHARITY"
    CLEANING = "CLEANING"
    CONSULTANT = "CONSULTANT"
    CONTRACTOR = "CONTRACTOR"
    DENTIST = "DENTIST"
    EDU = "EDU"
    FOOD = "FOOD"
    LANDSCAPING = "LANDSCAPING"
    LEGAL = "LEGAL"
    MEDICAL_PRACT = "MEDICAL_PRACT"
    MEDICAL_SERV = "MEDICAL_SERV"
    MEMBERSHIP = "MEMBERSHIP"
    MISC_FOOD_STORES = "MISC_FOOD_STORES"
    MISC_MERCH = "MISC_MERCH"
    MISC_SERV = "MISC_SERV"
    MUSIC = "MUSIC"
    PC = "PC"
    PHOTO_FILM = "PHOTO_FILM"
    PROF_SERV = "PROF_SERV"
    REAL_ESTATE = "REAL_ESTATE"
    RECREATION = "RECREATION"
    REPAIR = "REPAIR"
    RESTO = "RESTO"
    RETAIL = "RETAIL"
    TAXI = "TAXI"
    VET = "VET"
    WEB_DEV = "WEB_DEV"
    WEB_HOSTING = "WEB_HOSTING"


class BusinessLocales(str, Enum):
    EN_US = "en_US"
    EN_CA = "en_CA"
    FR_CA = "fr_CA"
    EN_GB = "en_GB"


class BusinessRegions(str, Enum):
    US = "US"
    CA = "CA"


class BusinessYearlyTransactionVolumeTypes(str, Enum):
    LOW = "LOW"
    MEDIUM = "MEDIUM"
    HIGH = "HIGH"
    VERY_HIGH = "VERY_HIGH"


class BusinessTypes(str, Enum):
    CHARITY = "CHARITY"
    CIC = "CIC"
    CORP = "CORP"
    LTD = "LTD"
    LLC = "LLC"
    LLP = "LLP"
    NPCORP = "NPCORP"
    PARTNERSHP = "PARTNERSHP"
    PLC = "PLC"
    GOV = "GOV"
    SOLEPROP = "SOLEPROP"
    TRUST = "TRUST"


class DBSortTypes(str, Enum):
    ASCENDING = "asc"
    DESCENDING = "desc"


class DefaultUserRoles(str, Enum):
    OWNER = "owner"
    MANAGER = "manager"
    STAFF = "staff"


class UserAccessLevels(str, Enum):
    SUPERADMIN = "superadmin"
    ADMIN = "admin"
    USER = "user"


class DefaultCustomerRoles(str, Enum):
    OWNER = "owner"


class LogLevels(str, Enum):
    INFO = "info"
    DEBUG = "debug"
    WARNING = "warning"
    ERROR = "error"
    CRITICAL = "critical"
    ACTION_NEEDED = "action_needed"


class ReminderScheduleStatusTypes(str, Enum):
    """Reminder schedule status"""

    DATE = "date"
    RIGHT_NOW = "right_now"
    DAILY_UNTIL_PAID = "daily_until_paid"
    WEEKLY_UNTIL_PAID = "weekly_until_paid"
    EVERY_BUSINESS_DAY_UNTIL_PAID = "every_business_day_until_paid"
    EVERY_THIRD_DAY_UNTIL_PAID = "every_third_day_until_paid"
    EVERY_FIFTH_DAY_UNTIL_PAID = "every_fifth_day_until_paid"


class AccountsBulkActions(str, Enum):
    """Customer account status"""

    activate = "activate"
    deactivate = "deactivate"
    remove = "remove"


class LateFeeTypes(str, Enum):
    """Late Fee Types"""

    PERCENTAGE = "percentage"
    AMOUNT = "amount"


class MerchantBulkActions(str, Enum):
    """Customer account status"""

    ACTIVATE = "activate"
    DEACTIVATE = "deactivate"
    REMOVE = "remove"
    APPROVE = "approve"


class PlansStatusTypes(WellDocumentedIntEnum):
    """Plans Status"""

    CREATED = 100  # plan created
    UPDATED = 101  # if plan is updated.
    DRAFT = 102  # if plan is saved as draft
    PENDING = 300  # if plan is saved as pending


class LimitationType(str, Enum):
    USER_LIMIT = "USER_LIMIT"
    TRANSACTION_SIZE_LIMIT = "TRANSACTION_SIZE_LIMIT"


class TransactionSourceTypes(str, Enum):
    """TransactionSourceTypes"""

    HPP = "hpp"
    API = "api"
    TERMINAL = "terminal"


class PaymentTypes(str, Enum):
    """PaymentTypes"""

    RECEIVE_PAYMENT = "receive_payment"
    SEND_PAYMENT = "send_payment"


class EmailTemplateIcons(str, Enum):
    """Message Status"""

    RESET_PASSWORD_ICON = "/assets/images/email/email_password_link.png"
    REFUND_ICON = "/assets/images/email/email_refund_cion.png"
    FAILED_ICON = "/assets/images/email/email_decline.png"
    INVOICE_ICON = "/assets/images/email/email_invoice_icon.png"
    RECEIVE_ICON = "/assets/images/email/email_check_icon.png"
    PAYER_WELCOME_ICON = "/assets/images/email/user_check.png"
    OWNER_LOGO = "/assets/images/email/email_logo_footer_flux.png"
    SUCCESS_PASSWORD_ICON = "/assets/images/email/email_password_success.png"
    SUBSCRIPTION_RENEWAL_ICON = "/assets/images/backend2.png"
    OVERDUE_ICON = "/assets/images/email/email_cal_cion.png"
    CARD_DOT_ICON = "/assets/images/email/email_card_dot.png"


class ExemptedRoutes(Enum):
    UPLOAD_MANY = "upload-many"
    WEBHOOK = "/webhook/*"
    TEMPLATES = "/templates/*"
    ATTCHMENTS = "attachments"
    AUTHORIZE = "authorize"
    UPLOAD_ONE = "upload-one"


class APIRoutes(Enum):
    """API route prefixes."""
    
    USERS = "/users"
    PRODUCTS = "/products"
    CUSTOMERS = "/customers"
    HEALTH = "/health"
    PAYMENT_REQUESTS = "/payment-requests"
    SITE_MASTER = "/site-master"
    NOTES = "/notes"


class HTTPStatusCodes(Enum):
    """Common HTTP status codes."""
    
    OK = 200
    CREATED = 201
    NO_CONTENT = 204
    BAD_REQUEST = 400
    UNAUTHORIZED = 401
    FORBIDDEN = 403
    NOT_FOUND = 404
    CONFLICT = 409
    UNPROCESSABLE_ENTITY = 422
    INTERNAL_SERVER_ERROR = 500


class UserRoles(Enum):
    """User role definitions."""
    
    ADMIN = "admin"
    USER = "user"
    MODERATOR = "moderator"
    GUEST = "guest"


class PaginationDefaults(Enum):
    """Pagination constants."""
    
    DEFAULT_PAGE_SIZE = 20
    MAX_PAGE_SIZE = 100
    MIN_PAGE_SIZE = 1


class ResponseMessages(Enum):
    """Standard response messages."""
    
    SUCCESS = "Operation completed successfully"
    CREATED = "Resource created successfully"
    UPDATED = "Resource updated successfully"
    DELETED = "Resource deleted successfully"
    NOT_FOUND = "Resource not found"
    UNAUTHORIZED = "Authentication required"
    FORBIDDEN = "Access denied"
    BAD_REQUEST = "Invalid request data"
    INTERNAL_ERROR = "Internal server error"


class MODULES(str, Enum):
    """Module names for permission system."""
    
    USER = "user"
    CUSTOMER = "customer"
    MERCHANT = "merchant"
    PAYMENT_REQUEST = "payment_request"
    PAYMENT_METHOD = "payment_method"
    TRANSACTION = "transaction"
    INVOICE = "invoice"
    PRODUCT = "product"
    PRODUCT_CATEGORY = "product_category"
    RECEIPT = "receipt"
    CONTRACT = "contract"
    SETTINGS = "settings"
    FILES = "files"
    AUTH = "auth"


class OPERATIONS(str, Enum):
    """Operation types for permission system."""
    
    CREATE = "create"
    READ = "read"
    UPDATE = "update"
    DELETE = "delete"
    LIST = "list"
    ACTIVATE = "activate"
    DEACTIVATE = "deactivate"
    APPROVE = "approve"
    REJECT = "reject"
    PROCESS = "process"
    CANCEL = "cancel"
    REFUND = "refund"
    AUTHORIZE = "authorize"
    VIEW = "view"
    MANAGE = "manage"


# Legacy constants for backward compatibility
DEFAULT_PER_PAGE = PaginationDefaults.DEFAULT_PAGE_SIZE.value
MAX_PER_PAGE = PaginationDefaults.MAX_PAGE_SIZE.value