"""Repository interfaces (ports).

Abstract base classes describing the persistence operations the
application layer needs, without committing to Django's ORM. Concrete
implementations live in infrastructure/repositories.py. Every tenant-owned repository is bound
to one organization when constructed, so use cases cannot reach another tenant's rows.
"""
from __future__ import annotations

import abc
import datetime
from typing import Iterable, Optional


class UserRepository(abc.ABC):
    """Account-level persistence (not tenant specific)."""

    @abc.abstractmethod
    def save(self, user) -> None:
        ...


class MemberRepository(abc.ABC):
    """People who belong to the organization this repository is bound to."""

    @abc.abstractmethod
    def get_user(self, user_id: int):
        """The account if it is an active member of the organization, else None."""
        ...

    @abc.abstractmethod
    def list_users(self) -> list:
        """Active members' accounts, ordered by personnel code."""
        ...

class AttendanceRepository(abc.ABC):
    @abc.abstractmethod
    def get_for_day(self, user_id: int, date: datetime.date):
        ...

    @abc.abstractmethod
    def create(self, user_id: int, date: datetime.date, **fields):
        ...

    @abc.abstractmethod
    def save(self, attendance) -> None:
        ...

    @abc.abstractmethod
    def list_for_range(self, user_id: int, start: datetime.date, end: datetime.date):
        ...

    @abc.abstractmethod
    def get_or_create_for_day(self, user_id: int, date: datetime.date):
        ...

    @abc.abstractmethod
    def find_pending_default_checkout(self, before: datetime.date):
        """Rows with check_in set, check_out null, date < before."""
        ...

    @abc.abstractmethod
    def list_for_date(self, date: datetime.date):
        """All attendance rows (any user) for a single calendar date."""
        ...


class HolidayRepository(abc.ABC):
    @abc.abstractmethod
    def list_for_range(self, start: datetime.date, end: datetime.date):
        ...

    @abc.abstractmethod
    def list_all(self):
        ...

    @abc.abstractmethod
    def exists_on_date(self, date: datetime.date) -> bool:
        ...

    @abc.abstractmethod
    def create(self, date: datetime.date, title: str, description: str | None):
        ...

    @abc.abstractmethod
    def delete(self, holiday_id: int) -> None:
        ...


class WorkScheduleRepository(abc.ABC):
    @abc.abstractmethod
    def get_for_date(self, date: datetime.date):
        """The per-day override for this date, or None if none is set."""
        ...

    @abc.abstractmethod
    def get_default(self):
        """The global default schedule (date=None), or None if never set."""
        ...

    @abc.abstractmethod
    def get_effective_for_date(self, date: datetime.date):
        """Per-day override if set, else the global default, else None."""
        ...

    @abc.abstractmethod
    def list_all(self):
        ...

    @abc.abstractmethod
    def set_default(self, standard_check_in, standard_check_out):
        ...

    @abc.abstractmethod
    def set_for_date(self, date: datetime.date, standard_check_in, standard_check_out):
        ...

    @abc.abstractmethod
    def delete_for_date(self, date: datetime.date) -> None:
        ...


class LeaveRequestRepository(abc.ABC):
    @abc.abstractmethod
    def create(self, **fields):
        ...

    @abc.abstractmethod
    def get_by_id(self, leave_id: int):
        ...

    @abc.abstractmethod
    def list_for_user(self, user_id: int):
        ...

    @abc.abstractmethod
    def list_all(self, status: Optional[str] = None):
        ...

    @abc.abstractmethod
    def list_for_user_on_date(self, user_id: int, date: datetime.date):
        ...

    @abc.abstractmethod
    def list_approved_for_user_range(self, user_id: int, start: datetime.date, end: datetime.date):
        ...

    @abc.abstractmethod
    def save(self, leave_request) -> None:
        ...
