# The Mia! Accounting Flask Project.
# Author: imacat@mail.imacat.idv.tw (imacat), 2023/3/4

#  Copyright (c) 2023 imacat.
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.
"""The period chooser.

This file is largely taken from the NanoParma ERP project, first written in
2021/9/16 by imacat (imacat@nanoparma.com).

"""
import typing as t
from datetime import date

from accounting.models import Transaction
from .period import Period, ThisMonth, LastMonth, SinceLastMonth, ThisYear, \
    LastYear, Today, Yesterday, AllTime, TemplatePeriod, YearPeriod


class PeriodChooser:
    """The period chooser."""

    def __init__(self, get_url: t.Callable[[Period], str]):
        """Constructs a period chooser.

        :param get_url: The callback to return the URL of the current report in
            a period.
        """
        self.__get_url: t.Callable[[Period], str] = get_url
        """The callback to return the URL of the current report in a period."""

        # Shortcut periods
        self.this_month_url: str = get_url(ThisMonth())
        """The URL for this month."""
        self.last_month_url: str = get_url(LastMonth())
        """The URL for last month."""
        self.since_last_month_url: str = get_url(SinceLastMonth())
        """The URL since last mint."""
        self.this_year_url: str = get_url(ThisYear())
        """The URL for this year."""
        self.last_year_url: str = get_url(LastYear())
        """The URL for last year."""
        self.today_url: str = get_url(Today())
        """The URL for today."""
        self.yesterday_url: str = get_url(Yesterday())
        """The URL for yesterday."""
        self.all_url: str = get_url(AllTime())
        """The URL for all period."""
        self.url_template: str = get_url(TemplatePeriod())
        """The URL template."""

        first: Transaction | None \
            = Transaction.query.order_by(Transaction.date).first()
        start: date | None = None if first is None else first.date

        # Attributes
        self.data_start: date | None = start
        """The start of the data."""
        self.has_data: bool = start is not None
        """Whether there is any data."""
        self.has_last_month: bool = False
        """Where there is data in last month."""
        self.has_last_year: bool = False
        """Whether there is data in last year."""
        self.has_yesterday: bool = False
        """Whether there is data in yesterday."""
        self.available_years: list[int] = []
        """The available years."""

        if self.has_data is not None:
            today: date = date.today()
            self.has_last_month = start < date(today.year, today.month, 1)
            self.has_last_year = start.year < today.year
            self.has_yesterday = start < today
            if start.year < today.year - 1:
                self.available_years \
                    = reversed(range(start.year, today.year - 1))

    def year_url(self, year: int) -> str:
        """Returns the period URL of a year.

        :param year: The year
        :return: The period URL of the year.
        """
        return self.__get_url(YearPeriod(year))