import arrow
import calendar
from api_configs.configs import Config
from datetime import timedelta


class DateTimeLocal:

    def __init__(self, timezone: str = None, is_client: bool = True):
        if timezone and timezone not in Config.SUPPORTED_TIMEZONES:
            raise ValueError(
                f"Unsupported timezone: {timezone}. Must be one of {Config.SUPPORTED_TIMEZONES}"
            )

        self.timezone = Config.SYSTEM_TIMEZONE
        if is_client:
            self.timezone = (timezone or Config.DEFAULT_TIMEZONE).replace("-", "+")

    def find_last_day_of_month(self, date_value):
        today = self.get(date_value).date()
        _, last_day = calendar.monthrange(today.year, today.month)
        return self.get(today.year, today.month, last_day, 23, 59, 59).to(self.timezone)

    def find_first_day_of_month(self, date_value):
        today = self.get(date_value).date()
        return self.get(today.year, today.month, 1).to(self.timezone)

    def get(self, *args):
        return arrow.get(*args).to(str(self.timezone))

    def now(self):
        return arrow.now().to(str(self.timezone))

    def shift(self, date, **kwargs):
        return self.get(date).shift(**kwargs)

    def date(self, date):
        return self.get(date).date()

    def time(self, date):
        return self.get(date).time()

    def string_date(self, date, splitter: str = "-"):
        return str(self.get(date).date()).replace("-", splitter)

    def string_time_only(self, date):
        return self.get(date).format("HH:mm:ss")

    def string_date_only(self, date):
        return self.get(date).format("YYYY-MM-DD")

    def to_timestamp(self, date):
        """Convert datetime to UTC timestamp"""
        return self.get(date).timestamp()

    def from_timestamp(self, timestamp):
        """Convert timestamp to timezone-aware datetime"""
        return arrow.get(timestamp).to(str(self.timezone))

    def is_timezone_aware(self, date):
        """Check if a date is timezone-aware"""
        return self.get(date).tzinfo is not None

    def standardize_timezone(self, date):
        """Ensure date is in the correct timezone"""
        if not self.is_timezone_aware(date):
            return self.get(date).to(str(self.timezone))
        return self.get(date)

    def get_expiry_time(self, **kwargs):
        """Get future time for cache expiry
        Example: get_expiry_time(hours=1, minutes=30)
        """
        return self.now().shift(**kwargs)

    def is_expired(self, timestamp):
        """Check if a timestamp is expired"""
        if not timestamp:
            return True
        return self.from_timestamp(timestamp) < self.now()

    def get_cache_key(self, base_key, *args):
        """Generate a cache key with timezone info
        Example: get_cache_key('user_profile', user_id, 'details')
        """
        components = [str(base_key)]
        components.extend(str(arg) for arg in args)
        components.append(f"tz_{self.timezone}")
        return ":".join(components)

    def format_for_db(self, date):
        """Format date for database storage"""
        return self.get(date).format("YYYY-MM-DD HH:mm:ss.SSSZZ")

    def parse_from_db(self, date_str):
        """Parse date from database format"""
        if not date_str:
            return None
        return self.get(date_str)

    def get_day_boundaries(self, date=None):
        """Get start and end of day in current timezone"""
        dt = self.get(date) if date else self.now()
        start = dt.floor("day")
        end = dt.ceil("day")
        return start, end

    def get_month_boundaries(self, date=None):
        """Get start and end of month in current timezone"""
        dt = self.get(date) if date else self.now()
        start = dt.floor("month")
        end = dt.ceil("month")
        return start, end


client_arrow = DateTimeLocal(is_client=True)
system_arrow = DateTimeLocal(is_client=False)
