# apps/aroflo_connector_app/features/timesheets/service.py

from __future__ import annotations

from dataclasses import dataclass
from datetime import date, timedelta
from typing import Any, Dict, List, Optional

from apps.aroflo_connector_app.core.client import AroFloClient


@dataclass
class TimesheetFilters:
    """
    Filtros de alto nivel para el endpoint de timesheets.

    Todos son opcionales. Si NO pasas filtros de fecha, AroFlo aplica
    su WHERE por defecto:
      AND workdate > DATEADD(d, -30, GETUTCDATE())
    """

    timesheetid: Optional[str] = None
    taskid: Optional[str] = None
    userid: Optional[str] = None
    type: Optional[str] = None  # Productive | Non-Productive | Expense
    workdate_from: Optional[date] = None
    workdate_to: Optional[date] = None


class TimesheetService:
    """
    Servicio para leer timesheets desde AroFlo (zona READ ONLY).
    """

    def __init__(self, client: AroFloClient) -> None:
        self.client = client

    # ------------------------------------------------------------------
    # Helpers internos
    # ------------------------------------------------------------------
    def _build_where_clause(self, filters: TimesheetFilters | None) -> Optional[str]:
        """
        Construye el WHERE SQL para AroFlo a partir de los filtros de fechas.
        Solo metemos en el WHERE lo que realmente es fecha/ID interno.
        El resto (userid, type, etc.) viaja como extra_params.
        """
        if not filters:
            return None

        clauses: List[str] = []

        if filters.timesheetid:
            clauses.append(f"timesheetid = '{filters.timesheetid}'")

        if filters.taskid:
            clauses.append(f"taskid = '{filters.taskid}'")

        # Fechas
        if filters.workdate_from:
            clauses.append(
                f"workdate >= '{filters.workdate_from.strftime('%Y-%m-%d')}'"
            )

        if filters.workdate_to:
            clauses.append(
                f"workdate <= '{filters.workdate_to.strftime('%Y-%m-%d')}'"
            )

        if not clauses:
            return None

        return " AND ".join(clauses)

    def _build_extra_params(self, filters: TimesheetFilters | None) -> Dict[str, Any]:
        """
        Filtros que van como querystring directo en VarString (no en WHERE).
        Ejemplo típico según la API:
          - userid
          - type (Productive / Non-Productive / Expense)
        """
        if not filters:
            return {}

        extra: Dict[str, Any] = {}

        if filters.userid:
            extra["userid"] = filters.userid
        if filters.type:
            extra["type"] = filters.type

        # Si en el futuro AroFlo define más filtros directos, se agregan aquí.
        return extra

    # ------------------------------------------------------------------
    # Métodos públicos
    # ------------------------------------------------------------------
    def list_timesheets(
        self,
        filters: TimesheetFilters | None = None,
        page: int = 1,
        order_by: str = "workdate",
        include_raw_response: bool = False,
    ) -> Dict[str, Any]:
        """
        Devuelve la página de timesheets desde AroFlo.

        :param filters: filtros opcionales (TimesheetFilters)
        :param page: página a consultar (1 por defecto)
        :param order_by: campo de orden (por defecto 'workdate')
        :param include_raw_response: si True, devuelve la respuesta completa
                                     de la zona. Si False, solo zoneresponse["timesheets"].
        """
        where_clause = self._build_where_clause(filters)
        extra_params = self._build_extra_params(filters)

        response = self.client.request(
            zone="timesheets",
            page=page,
            where=where_clause,
            order=order_by,
            extra_params=extra_params,
            method="GET",
        )

        if include_raw_response:
            return response

        zone = response.get("zoneresponse", {})
        timesheets = zone.get("timesheets", [])

        return {
            "timesheets": timesheets,
            "pagenumber": int(zone.get("pagenumber", "1")),
            "currentpageresults": int(zone.get("currentpageresults", "0")),
            "maxpageresults": int(zone.get("maxpageresults", "0")),
        }

    def list_recent(
        self,
        days: int = 30,
        page: int = 1,
        type: Optional[str] = None,
        userid: Optional[str] = None,
    ) -> Dict[str, Any]:
        """
        Helper de conveniencia: últimos N días, con filtros simples.
        """
        today = date.today()
        from_date = today - timedelta(days=days)

        filters = TimesheetFilters(
            workdate_from=from_date,
            workdate_to=today,
            type=type,
            userid=userid,
        )

        return self.list_timesheets(filters=filters, page=page)
