"""کمک‌توابع تقویم شمسی — پورت‌شده از core/jalali.py دسکتاپ.

تفاوت با نسخه دسکتاپ: چون اینجا دیتابیس (Postgres/SQLite از طریق SQLAlchemy) مستقیماً
آبجکت‌های date/datetime پایتون رو ذخیره می‌کنه (نه رشته‌ی ISO مثل SQLite خام دسکتاپ)،
توابع این‌جا روی date/datetime کار می‌کنن نه رشته.
"""
from datetime import date, datetime, timedelta

import jdatetime

_FA_DIGITS = str.maketrans("0123456789", "۰۱۲۳۴۵۶۷۸۹")

WEEKDAY_NAMES_FA = ["شنبه", "یکشنبه", "دوشنبه", "سه‌شنبه", "چهارشنبه", "پنجشنبه", "جمعه"]


def to_fa_digits(text) -> str:
    return str(text).translate(_FA_DIGITS)


def to_jalali_str(value, with_time: bool = False) -> str:
    """date/datetime میلادی -> رشته نمایشی شمسی."""
    if value is None:
        return "-"
    if isinstance(value, datetime):
        d = value.date()
    elif isinstance(value, date):
        d = value
    else:
        return str(value)

    j = jdatetime.date.fromgregorian(date=d)
    txt = f"{j.year:04d}/{j.month:02d}/{j.day:02d}"
    if with_time and isinstance(value, datetime):
        txt += f" - {value.strftime('%H:%M')}"
    return to_fa_digits(txt)


def jalali_str_to_gregorian_date(jalali_str: str) -> date:
    """'1403/04/30' شمسی -> date میلادی."""
    jalali_str = jalali_str.translate(str.maketrans("۰۱۲۳۴۵۶۷۸۹", "0123456789")).strip()
    parts = jalali_str.replace("-", "/").split("/")
    y, m, d = int(parts[0]), int(parts[1]), int(parts[2])
    return jdatetime.date(y, m, d).togregorian()


def today_jalali_display() -> str:
    j = jdatetime.date.today()
    weekday_fa = WEEKDAY_NAMES_FA[j.weekday()]
    return to_fa_digits(f"{weekday_fa} {j.day} {j.j_months_fa[j.month - 1]} {j.year}")


def days_ago(n: int) -> date:
    return date.today() - timedelta(days=n)


def days_ahead(n: int) -> date:
    return date.today() + timedelta(days=n)


def start_of_week() -> date:
    """شروع هفته میلادی معادل شنبه (استاندارد هفته ایرانی)."""
    today = date.today()
    offset = (today.weekday() + 2) % 7  # weekday(): Monday=0 ... Saturday=5
    return today - timedelta(days=offset)


def end_of_week() -> date:
    return start_of_week() + timedelta(days=6)


def next_week_range():
    end_this_week = end_of_week()
    start_next = end_this_week + timedelta(days=1)
    end_next = start_next + timedelta(days=6)
    return start_next, end_next
