from datetime import date, datetime
from decimal import Decimal
from typing import Any

from pydantic import BaseModel, Field

from app.domain.enums import (
    CustomReportField,
    CustomReportMetric,
    CustomReportModule,
    CustomReportSort,
    DeptReportCompareWith,
    DeptReportSort,
    DeptReportView,
    ReportType,
    TxnReportPaymentStatus,
    TxnReportReferenceType,
    TxnReportTrendGranularity,
    TxnReportType,
)


class ReportLineItemResponse(BaseModel):
    account_id: str | None
    account_code: str
    account_name: str
    account_type: str | None
    debit: Decimal
    credit: Decimal
    balance: Decimal
    metadata: dict[str, Any] = {}


class FinancialReportResponse(BaseModel):
    id: str
    company_id: str
    report_type: ReportType
    report_title: str
    from_date: date | None
    to_date: date | None
    report_date: date
    account_id: str | None
    account_code: str | None
    line_items: list[ReportLineItemResponse]
    totals: dict[str, Decimal]
    generated_at: datetime
    parameters: dict[str, Any]

    model_config = {"from_attributes": True}


class LedgerReportRequest(BaseModel):
    account_id: str
    from_date: date | None = None
    to_date: date | None = None
    save: bool = True


class TrialBalanceRequest(BaseModel):
    as_of_date: date
    save: bool = True


class IncomeStatementRequest(BaseModel):
    from_date: date
    to_date: date
    save: bool = True


class BalanceSheetRequest(BaseModel):
    as_of_date: date
    save: bool = True


class TxnReportKpiResponse(BaseModel):
    current: Decimal
    previous: Decimal
    change_percent: Decimal | None = None

    model_config = {"from_attributes": True}


class TxnReportRowResponse(BaseModel):
    id: str
    txn_date: date
    txn_at: datetime | None = None
    transaction_type: TxnReportType
    reference_no: str
    reference_type: TxnReportReferenceType
    party_id: str | None = None
    party_name: str | None = None
    warehouse_id: str | None = None
    warehouse_name: str | None = None
    total_amount: Decimal
    paid_amount: Decimal
    due_amount: Decimal
    payment_status: TxnReportPaymentStatus
    created_by_id: str | None = None
    created_by_name: str | None = None

    model_config = {"from_attributes": True}


class TxnReportTrendPointResponse(BaseModel):
    date: date
    total_amount: Decimal
    count: int = 0

    model_config = {"from_attributes": True}


class TxnReportSliceResponse(BaseModel):
    key: str
    label: str
    count: int
    total_amount: Decimal
    percent_of_total: Decimal

    model_config = {"from_attributes": True}


class TransactionReportResponse(BaseModel):
    from_date: date
    to_date: date
    previous_from_date: date
    previous_to_date: date
    trend_granularity: TxnReportTrendGranularity = TxnReportTrendGranularity.DAILY
    total_transactions: TxnReportKpiResponse
    total_amount: TxnReportKpiResponse
    total_received: TxnReportKpiResponse
    total_paid: TxnReportKpiResponse
    pending_amount: TxnReportKpiResponse
    rows: list[TxnReportRowResponse] = Field(default_factory=list)
    rows_total: int
    page: int
    page_size: int
    total_pages: int
    trend: list[TxnReportTrendPointResponse] = Field(default_factory=list)
    by_type: list[TxnReportSliceResponse] = Field(default_factory=list)
    by_payment_status: list[TxnReportSliceResponse] = Field(default_factory=list)

    model_config = {"from_attributes": True}


class DeptReportRowResponse(BaseModel):
    department_id: str
    department_code: str | None = None
    department_name: str
    transactions_count: int
    issued_amount: Decimal
    received_amount: Decimal
    net_value: Decimal
    total_value: Decimal
    percent_of_total: Decimal
    change_percent: Decimal | None = None

    model_config = {"from_attributes": True}


class DeptReportDetailRowResponse(BaseModel):
    id: str
    txn_date: date
    direction: str
    reference_no: str
    department_id: str
    department_code: str | None = None
    department_name: str
    warehouse_id: str | None = None
    warehouse_name: str | None = None
    amount: Decimal

    model_config = {"from_attributes": True}


class DeptReportComboPointResponse(BaseModel):
    department_id: str
    department_name: str
    transactions_count: int
    total_amount: Decimal

    model_config = {"from_attributes": True}


class DeptReportIssuedReceivedResponse(BaseModel):
    department_id: str
    department_name: str
    issued_amount: Decimal
    received_amount: Decimal

    model_config = {"from_attributes": True}


class DepartmentReportResponse(BaseModel):
    from_date: date
    to_date: date
    previous_from_date: date
    previous_to_date: date
    report_view: DeptReportView = DeptReportView.SUMMARY
    compare_with: DeptReportCompareWith = DeptReportCompareWith.PREVIOUS_PERIOD
    total_departments: TxnReportKpiResponse
    total_transactions: TxnReportKpiResponse
    total_value: TxnReportKpiResponse
    total_issued: TxnReportKpiResponse
    total_received: TxnReportKpiResponse
    rows: list[DeptReportRowResponse] = Field(default_factory=list)
    details: list[DeptReportDetailRowResponse] = Field(default_factory=list)
    rows_total: int
    page: int
    page_size: int
    total_pages: int
    top_by_value: list[TxnReportSliceResponse] = Field(default_factory=list)
    by_department: list[DeptReportComboPointResponse] = Field(default_factory=list)
    issued_vs_received: list[DeptReportIssuedReceivedResponse] = Field(
        default_factory=list
    )
    contribution: list[TxnReportSliceResponse] = Field(default_factory=list)

    model_config = {"from_attributes": True}


class CustomReportConfigSchema(BaseModel):
    module: CustomReportModule = CustomReportModule.TRANSACTIONS
    fields: list[CustomReportField] = Field(default_factory=list)
    metrics: list[CustomReportMetric] = Field(default_factory=list)
    from_date: date | None = None
    to_date: date | None = None
    transaction_types: list[TxnReportType] = Field(default_factory=list)
    warehouse_id: str | None = None
    department_id: str | None = None
    payment_status: TxnReportPaymentStatus | None = None
    party: str | None = None
    group_by: CustomReportField = CustomReportField.TRANSACTION_TYPE
    then_by: CustomReportField | None = None
    sort_by: CustomReportSort = CustomReportSort.TOTAL_AMOUNT
    sort_dir: str = "desc"

    model_config = {"from_attributes": True}


class CustomReportCreate(BaseModel):
    name: str = Field(..., min_length=1, max_length=200)
    description: str | None = Field(None, max_length=500)
    configuration: CustomReportConfigSchema
    is_template: bool = False


class CustomReportUpdate(BaseModel):
    name: str | None = Field(None, min_length=1, max_length=200)
    description: str | None = Field(None, max_length=500)
    configuration: CustomReportConfigSchema | None = None
    is_template: bool | None = None


class CustomReportResponse(BaseModel):
    id: str
    company_id: str
    name: str
    module: CustomReportModule
    description: str | None = None
    configuration: CustomReportConfigSchema
    is_template: bool = False
    created_by: str | None = None
    created_at: datetime
    updated_at: datetime

    model_config = {"from_attributes": True}


class CustomReportRunRequest(BaseModel):
    configuration: CustomReportConfigSchema
    page: int = Field(1, ge=1)
    page_size: int = Field(50, ge=1, le=500)


class CustomReportResultRowResponse(BaseModel):
    group_key: str
    group_label: str
    then_key: str | None = None
    then_label: str | None = None
    total_transactions: int
    total_quantity: Decimal
    total_amount: Decimal
    avg_amount: Decimal

    model_config = {"from_attributes": True}


class CustomReportTotalsResponse(BaseModel):
    total_transactions: int
    total_quantity: Decimal
    total_amount: Decimal
    avg_amount: Decimal

    model_config = {"from_attributes": True}


class CustomReportResultResponse(BaseModel):
    module: CustomReportModule
    configuration: CustomReportConfigSchema
    rows: list[CustomReportResultRowResponse] = Field(default_factory=list)
    totals: CustomReportTotalsResponse
    rows_total: int
    page: int
    page_size: int
    total_pages: int
    trend: list[TxnReportTrendPointResponse] = Field(default_factory=list)
    top_parties: list[TxnReportSliceResponse] = Field(default_factory=list)
    by_type: list[TxnReportSliceResponse] = Field(default_factory=list)
    by_payment_status: list[TxnReportSliceResponse] = Field(default_factory=list)

    model_config = {"from_attributes": True}


class CustomReportFieldMeta(BaseModel):
    key: str
    label: str
    groupable: bool = True


class CustomReportMetricMeta(BaseModel):
    key: str
    label: str


class CustomReportTemplateMeta(BaseModel):
    key: str
    name: str
    description: str
    configuration: CustomReportConfigSchema

    model_config = {"from_attributes": True}


class CustomReportMetaResponse(BaseModel):
    modules: list[dict[str, str]]
    fields: list[CustomReportFieldMeta]
    metrics: list[CustomReportMetricMeta]
    templates: list[CustomReportTemplateMeta]

    model_config = {"from_attributes": True}
