import enum
import uuid

from sqlalchemy.dialects.postgresql import UUID as PG_UUID
from sqlalchemy.types import CHAR, TypeDecorator


class GUID(TypeDecorator):
    impl = CHAR
    cache_ok = True

    def load_dialect_impl(self, dialect):
        if dialect.name == "postgresql":
            return dialect.type_descriptor(PG_UUID(as_uuid=True))
        return dialect.type_descriptor(CHAR(36))

    def process_bind_param(self, value, dialect):
        if value is None:
            return value
        if dialect.name == "postgresql":
            return value if isinstance(value, uuid.UUID) else uuid.UUID(str(value))
        return str(value)

    def process_result_value(self, value, dialect):
        if value is None:
            return value
        if isinstance(value, uuid.UUID):
            return value
        return uuid.UUID(str(value))


# --- Foundation enums (Phase 5.1) ---


class AccountType(str, enum.Enum):
    ASSET = "asset"
    LIABILITY = "liability"
    EQUITY = "equity"
    REVENUE = "revenue"
    EXPENSE = "expense"


class AccountCategory(str, enum.Enum):
    CURRENT_ASSET = "current_asset"
    NON_CURRENT_ASSET = "non_current_asset"
    CURRENT_LIABILITY = "current_liability"
    NON_CURRENT_LIABILITY = "non_current_liability"
    EQUITY = "equity"
    OPERATING_REVENUE = "operating_revenue"
    OTHER_REVENUE = "other_revenue"
    OPERATING_EXPENSE = "operating_expense"
    OTHER_EXPENSE = "other_expense"


class AccountStatus(str, enum.Enum):
    ACTIVE = "active"
    INACTIVE = "inactive"
    CLOSED = "closed"


class FiscalPeriodStatus(str, enum.Enum):
    OPEN = "open"
    LOCKED = "locked"
    CLOSED = "closed"
    ARCHIVED = "archived"


class VoucherStatus(str, enum.Enum):
    DRAFT = "draft"
    VALIDATED = "validated"
    POSTED = "posted"
    CANCELLED = "cancelled"
    REVERSED = "reversed"


class JournalStatus(str, enum.Enum):
    DRAFT = "draft"
    POSTED = "posted"
    REVERSED = "reversed"


class PostingStatus(str, enum.Enum):
    PENDING = "pending"
    IN_PROGRESS = "in_progress"
    COMPLETED = "completed"
    FAILED = "failed"


# --- Treasury enums (Phase 5.4) ---


class ChequeStatus(str, enum.Enum):
    ISSUED = "issued"
    RECEIVED = "received"
    DEPOSITED = "deposited"
    CLEARED = "cleared"
    BOUNCED = "bounced"
    TRANSFERRED = "transferred"
    RETURNED = "returned"
    CANCELLED = "cancelled"


class TreasuryTransactionType(str, enum.Enum):
    CASH_RECEIPT = "cash_receipt"
    CASH_PAYMENT = "cash_payment"
    BANK_DEPOSIT = "bank_deposit"
    BANK_WITHDRAWAL = "bank_withdrawal"
    CHEQUE_DEPOSIT = "cheque_deposit"
    CHEQUE_CLEARANCE = "cheque_clearance"
    TRANSFER = "transfer"


class ReconciliationStatus(str, enum.Enum):
    PENDING = "pending"
    IN_PROGRESS = "in_progress"
    COMPLETED = "completed"
    FAILED = "failed"


# --- AR/AP enums (Phase 5.5) ---


class InvoiceStatus(str, enum.Enum):
    DRAFT = "draft"
    ISSUED = "issued"
    PARTIALLY_PAID = "partially_paid"
    PAID = "paid"
    CANCELLED = "cancelled"
    WRITTEN_OFF = "written_off"


class SettlementStatus(str, enum.Enum):
    DRAFT = "draft"
    COMPLETED = "completed"
    REVERSED = "reversed"


# --- Sales accounting enums (Phase 5.6) ---


class RevenueRecognitionMethod(str, enum.Enum):
    IMMEDIATE = "immediate"
    DEFERRED = "deferred"
    PARTIAL = "partial"
    MILESTONE = "milestone"


class SalesDocumentType(str, enum.Enum):
    INVOICE = "invoice"
    RETURN = "return"
    CREDIT_NOTE = "credit_note"
    DEBIT_NOTE = "debit_note"
    PAYMENT = "payment"
    DISCOUNT = "discount"


# --- Purchase/Inventory enums (Phase 5.7) ---


class InventoryValuationMethod(str, enum.Enum):
    FIFO = "fifo"
    WEIGHTED_AVERAGE = "weighted_average"
    MOVING_AVERAGE = "moving_average"
    SPECIFIC_IDENTIFICATION = "specific_identification"
    STANDARD_COST = "standard_cost"


class PurchaseDocumentType(str, enum.Enum):
    GOODS_RECEIPT = "goods_receipt"
    SUPPLIER_INVOICE = "supplier_invoice"
    PURCHASE_RETURN = "purchase_return"
    COST_ADJUSTMENT = "cost_adjustment"


class InventoryDocumentType(str, enum.Enum):
    RECEIPT = "receipt"
    ISSUE = "issue"
    TRANSFER = "transfer"
    ADJUSTMENT = "adjustment"
    WRITE_OFF = "write_off"


# --- Fixed Assets enums (Phase 5.8) ---


class AssetStatus(str, enum.Enum):
    DRAFT = "draft"
    ACTIVE = "active"
    DEPRECIATING = "depreciating"
    FULLY_DEPRECIATED = "fully_depreciated"
    DISPOSED = "disposed"
    RETIRED = "retired"


class DepreciationMethod(str, enum.Enum):
    STRAIGHT_LINE = "straight_line"
    DECLINING_BALANCE = "declining_balance"
    DOUBLE_DECLINING = "double_declining"
    UNITS_OF_PRODUCTION = "units_of_production"


# --- Payroll enums (Phase 5.9) ---


class EmploymentStatus(str, enum.Enum):
    ACTIVE = "active"
    ON_LEAVE = "on_leave"
    TERMINATED = "terminated"
    SUSPENDED = "suspended"


class PayrollPeriodStatus(str, enum.Enum):
    OPEN = "open"
    PROCESSING = "processing"
    APPROVED = "approved"
    LOCKED = "locked"
    PAID = "paid"
    CLOSED = "closed"


class PayrollStatus(str, enum.Enum):
    DRAFT = "draft"
    CALCULATED = "calculated"
    APPROVED = "approved"
    PAID = "paid"
    REVERSED = "reversed"


# --- Reporting enums (Phase 5.10) ---


class ReportType(str, enum.Enum):
    TRIAL_BALANCE = "trial_balance"
    GENERAL_LEDGER = "general_ledger"
    BALANCE_SHEET = "balance_sheet"
    INCOME_STATEMENT = "income_statement"
    CASH_FLOW = "cash_flow"
    EQUITY_STATEMENT = "equity_statement"
    CUSTOM = "custom"


class ReportStatus(str, enum.Enum):
    GENERATING = "generating"
    GENERATED = "generated"
    FAILED = "failed"
    ARCHIVED = "archived"


class ReportExportFormat(str, enum.Enum):
    PDF = "pdf"
    EXCEL = "excel"
    CSV = "csv"
    JSON = "json"


# --- Compliance enums (Phase 5.11) ---


class ApprovalStatus(str, enum.Enum):
    PENDING = "pending"
    APPROVED = "approved"
    REJECTED = "rejected"
    CANCELLED = "cancelled"


class RiskLevel(str, enum.Enum):
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"
    CRITICAL = "critical"


class PolicyViolationSeverity(str, enum.Enum):
    INFO = "info"
    WARNING = "warning"
    ERROR = "error"
    CRITICAL = "critical"
