"""
Ephemeral state: "this chat is currently expected to reply with a referral
link for that group".

Set right after the bot is added to a group and its admin is asked for a
referral link (core/handlers.handle_bot_added_to_group). The *reply chat*
is wherever we actually managed to ask — the admin's private chat if the DM
went through, or the group itself if it didn't — so the next matching text
from the right person, in that same chat, is picked up as the link.

Backed by a small JSON file (same pattern as services/group_links.py)
rather than an in-process dict, so it survives across Passenger/Flask worker
processes.
"""

import json
import os
import threading
import time

from .. import config

_lock = threading.Lock()
_TABLE = "referral_wait_state"

# If the admin never sends a link, don't let the request linger forever.
_TTL_SECONDS = 15 * 60


def _path() -> str:
    return os.path.join(config.DATA_DIR, f"{_TABLE}.json")


def _load() -> dict:
    path = _path()
    if not os.path.exists(path):
        return {}
    with open(path, "r", encoding="utf-8") as fh:
        try:
            return json.load(fh)
        except json.JSONDecodeError:
            return {}


def _save(data: dict) -> None:
    os.makedirs(config.DATA_DIR, exist_ok=True)
    with open(_path(), "w", encoding="utf-8") as fh:
        json.dump(data, fh, ensure_ascii=False, indent=2)


def mark_awaiting_link(reply_chat_id, admin_user_id, group_chat_id, group_title) -> None:
    """Call right after the admin is asked, in `reply_chat_id`, for a link."""
    if reply_chat_id is None:
        return
    with _lock:
        data = _load()
        data[str(reply_chat_id)] = {
            "admin_user_id": admin_user_id,
            "group_chat_id": group_chat_id,
            "group_title": group_title,
            "ts": time.time(),
        }
        _save(data)


def get_pending(reply_chat_id, sender_user_id):
    """
    Return the pending {"admin_user_id", "group_chat_id", "group_title"} entry
    if `reply_chat_id` is currently waiting on a link from `sender_user_id`,
    otherwise None (including an expired entry, which is dropped).
    """
    if reply_chat_id is None:
        return None
    with _lock:
        data = _load()
        entry = data.get(str(reply_chat_id))
        if entry is None:
            return None
        if (time.time() - entry.get("ts", 0)) > _TTL_SECONDS:
            data.pop(str(reply_chat_id), None)
            _save(data)
            return None
    if entry.get("admin_user_id") != sender_user_id:
        return None
    return entry


def clear(reply_chat_id) -> None:
    if reply_chat_id is None:
        return
    with _lock:
        data = _load()
        if data.pop(str(reply_chat_id), None) is not None:
            _save(data)
