from abc import ABC, abstractmethod
from datetime import date
from decimal import Decimal

from app.domain.entities.report import CustomReport, FinancialReport
from app.domain.enums import ReportType


class ReportRepository(ABC):
    @abstractmethod
    async def save(self, report: FinancialReport) -> FinancialReport:
        pass

    @abstractmethod
    async def get_by_id(self, report_id: str, company_id: str | None = None) -> FinancialReport | None:
        pass

    @abstractmethod
    async def list_reports(
        self,
        company_id: str,
        report_type: ReportType | None = None,
        from_date: date | None = None,
        to_date: date | None = None,
        skip: int = 0,
        limit: int = 50,
    ) -> list[FinancialReport]:
        pass

    @abstractmethod
    async def get_transaction_report_data(
        self,
        company_id: str,
        *,
        from_date: date,
        to_date: date,
        transaction_type: str | None = None,
        reference_type: str | None = None,
        warehouse_id: str | None = None,
        party: str | None = None,
        created_by_id: str | None = None,
        payment_status: str | None = None,
        min_amount: Decimal | None = None,
        max_amount: Decimal | None = None,
        trend_granularity: str = "daily",
        page: int = 1,
        page_size: int = 10,
        include_rows: bool = True,
        include_charts: bool = True,
    ) -> dict:
        pass

    @abstractmethod
    async def get_department_report_data(
        self,
        company_id: str,
        *,
        from_date: date,
        to_date: date,
        warehouse_id: str | None = None,
        department_id: str | None = None,
        search: str | None = None,
        sort_by: str = "transactions",
        sort_dir: str = "desc",
        page: int = 1,
        page_size: int = 8,
        include_rows: bool = True,
        include_charts: bool = True,
        include_details: bool = False,
        previous_from: date | None = None,
        previous_to: date | None = None,
    ) -> dict:
        pass

    @abstractmethod
    async def create_custom_report(self, report: CustomReport) -> CustomReport:
        pass

    @abstractmethod
    async def get_custom_report(
        self, report_id: str, company_id: str
    ) -> CustomReport | None:
        pass

    @abstractmethod
    async def list_custom_reports(
        self,
        company_id: str,
        *,
        module: str | None = None,
        search: str | None = None,
        skip: int = 0,
        limit: int = 50,
    ) -> list[CustomReport]:
        pass

    @abstractmethod
    async def count_custom_reports(
        self,
        company_id: str,
        *,
        module: str | None = None,
        search: str | None = None,
    ) -> int:
        pass

    @abstractmethod
    async def update_custom_report(
        self, report_id: str, report: CustomReport
    ) -> CustomReport | None:
        pass

    @abstractmethod
    async def delete_custom_report(self, report_id: str, company_id: str) -> bool:
        pass

    @abstractmethod
    async def run_custom_report_data(
        self,
        company_id: str,
        *,
        from_date: date,
        to_date: date,
        transaction_types: list[str] | None = None,
        warehouse_id: str | None = None,
        payment_status: str | None = None,
        party: str | None = None,
        group_by: str = "transaction_type",
        then_by: str | None = None,
        sort_by: str = "total_amount",
        sort_dir: str = "desc",
        page: int = 1,
        page_size: int = 50,
    ) -> dict:
        pass
