"""NexaOffice release version helper.

Usage:
    python tools/bump_release_version.py
    python tools/bump_release_version.py --write

Rule:
- Version format: vYYYY.MM.DD.NN/NNN
- If today's date differs from APP_VERSION date, next version becomes vYYYY.MM.DD.01
- If today's date is the same, next version increments NN.
"""
from __future__ import annotations

import argparse
import re
from datetime import date, datetime, timezone, timedelta
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent
CONSTANTS = ROOT / "core" / "constants.py"
VERSION_INFO = ROOT / "version_info.txt"
VERSION_RE = re.compile(r'APP_VERSION\s*=\s*"v(\d{4})\.(\d{2})\.(\d{2})\.(\d{2,3})"')


def read_current_version() -> str:
    text = CONSTANTS.read_text(encoding="utf-8")
    match = VERSION_RE.search(text)
    if not match:
        raise RuntimeError("APP_VERSION not found or invalid.")
    return "v" + ".".join(match.groups())


def local_release_date() -> date:
    # NexaOffice currently targets the Indonesia/Asia-Jakarta workflow.
    # Using UTC or server-local time can be one day behind near midnight.
    return datetime.now(timezone(timedelta(hours=7))).date()


def next_version(current: str | None = None, today: date | None = None) -> str:
    today = today or local_release_date()
    current = current or read_current_version()
    match = re.fullmatch(r"v(\d{4})\.(\d{2})\.(\d{2})\.(\d{2,3})", current)
    if not match:
        raise RuntimeError(f"Invalid version: {current}")
    y, m, d, n = match.groups()
    today_prefix = today.strftime("v%Y.%m.%d")
    current_prefix = f"v{y}.{m}.{d}"
    if current_prefix != today_prefix:
        return f"{today_prefix}.01"
    next_seq = int(n) + 1
    return f"{today_prefix}.{next_seq:02d}" if next_seq < 100 else f"{today_prefix}.{next_seq}"


def write_version(new_version: str) -> None:
    y, m, d, n = re.fullmatch(r"v(\d{4})\.(\d{2})\.(\d{2})\.(\d{2,3})", new_version).groups()
    plain = new_version[1:]
    text = CONSTANTS.read_text(encoding="utf-8")
    text = re.sub(r'APP_VERSION\s*=\s*"v\d{4}\.\d{2}\.\d{2}\.\d{2,3}"', f'APP_VERSION = "{new_version}"', text)
    CONSTANTS.write_text(text, encoding="utf-8")

    if VERSION_INFO.exists():
        info = VERSION_INFO.read_text(encoding="utf-8")
        info = re.sub(r"filevers=\(\d{4},\s*\d+,\s*\d+,\s*\d+\)", f"filevers=({int(y)}, {int(m)}, {int(d)}, {int(n)})", info)
        info = re.sub(r"prodvers=\(\d{4},\s*\d+,\s*\d+,\s*\d+\)", f"prodvers=({int(y)}, {int(m)}, {int(d)}, {int(n)})", info)
        info = re.sub(r"\d{4}\.\d{2}\.\d{2}\.\d{2,3}", plain, info)
        VERSION_INFO.write_text(info, encoding="utf-8")


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("--write", action="store_true", help="write the next version into constants.py and version_info.txt")
    parser.add_argument("--date", help="release date override in YYYY-MM-DD format")
    args = parser.parse_args()
    current = read_current_version()
    release_date = date.fromisoformat(args.date) if args.date else local_release_date()
    nxt = next_version(current, release_date)
    print(f"Current: {current}")
    print(f"Next:    {nxt}")
    if args.write:
        write_version(nxt)
        print("Updated constants.py and version_info.txt")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
