# account/admin_phone_service.py
import json
import re
import requests
from typing import List, Tuple, Set

from utility.authorization import CloudAuthorization

ENV_KEY_TEMPLATE = "PROPERTY_{property_id}_ADMIN_PHONE"
# Thai numbers in CC format: 66 + 8~10 digits (e.g., 66812345678)
CC_PATTERN = re.compile(r"^66\d{8,10}$")

def _sanitize_to_cc(s: str) -> str:
    """Strip non-digits, return only if matches CC format 66XXXXXXXXX."""
    if s is None:
        return ""
    digits = "".join(ch for ch in str(s) if ch.isdigit())
    return digits if CC_PATTERN.match(digits or "") else ""

def _normalize_list_cc(values: List[str]) -> List[str]:
    """Deduplicate + sort a list of CC-format numbers."""
    normalized: Set[str] = set()
    for v in values or []:
        cc = _sanitize_to_cc(v)
        if cc:
            normalized.add(cc)
    return sorted(normalized)

def _read_env_list_from_service_info(info: dict, env_key: str) -> tuple[list[str], bool]:
    """Returns (values, existed)."""
    envs = (
        info.get("spec", {})
            .get("template", {})
            .get("spec", {})
            .get("containers", [{}])[0]
            .get("env", [])
    )
    for e in envs:
        if e.get("name") == env_key:
            raw = (e.get("value") or "").strip()
            if not raw:
                return ([], True)
            try:
                data = json.loads(raw)
                return (data if isinstance(data, list) else [], True)
            except Exception:
                return ([s.strip() for s in raw.split(",") if s.strip()], True)
    return ([], False)

def _set_env_list_in_service_info(info: dict, env_key: str, values_list: List[str]) -> None:
    """Replace env var value in-place with JSON-encoded list."""
    env_json = json.dumps(values_list, ensure_ascii=False)
    containers = (
        info.setdefault("spec", {})
            .setdefault("template", {})
            .setdefault("spec", {})
            .setdefault("containers", [{}])
    )
    container = containers[0]
    envs = container.setdefault("env", [])
    for env in envs:
        if env.get("name") == env_key:
            env["value"] = env_json
            break
    else:
        envs.append({"name": env_key, "value": env_json})

def _put_updated_service(cauth: CloudAuthorization, access_token: str, info: dict):
    headers = {
        "Authorization": f"Bearer {access_token}",
        "Content-Type": "application/json"
    }
    return requests.put(cauth.service_url, headers=headers, json=info)

# ------------------ Public API ------------------

def get_admin_phones(property_id: str) -> tuple[str, list[str], bool]:
    """
    Returns (env_key, phones_in_cc_format_sorted, existed).
    """
    env_key = ENV_KEY_TEMPLATE.format(property_id=property_id)
    cauth = CloudAuthorization()
    token = cauth.get_access_token()
    info = cauth.get_cloud_run_service_info(access_token=token)
    raw, existed = _read_env_list_from_service_info(info, env_key)
    return env_key, _normalize_list_cc(raw), existed

def add_admin_phones(property_id: str, phones: list[str]) -> tuple[str, list[str]]:
    env_key = ENV_KEY_TEMPLATE.format(property_id=property_id)
    cauth = CloudAuthorization()
    token = cauth.get_access_token()
    info = cauth.get_cloud_run_service_info(access_token=token)

    current_raw, _ = _read_env_list_from_service_info(info, env_key)  # may be missing
    current = set(_normalize_list_cc(current_raw))
    incoming = set(_normalize_list_cc(phones))
    if not incoming:
        raise ValueError("no valid phone numbers after normalization (expect 66XXXXXXXXX)")

    final_list = sorted(current | incoming)               # create if missing
    _set_env_list_in_service_info(info, env_key, final_list)
    resp = _put_updated_service(cauth, token, info)
    if resp.status_code != 200:
        raise RuntimeError(f"update env var failed: {resp.status_code} - {resp.text}")
    return env_key, final_list

def replace_admin_phones(property_id: str, phones: list[str]) -> tuple[str, list[str]]:
    env_key = ENV_KEY_TEMPLATE.format(property_id=property_id)
    cauth = CloudAuthorization()
    token = cauth.get_access_token()
    info = cauth.get_cloud_run_service_info(access_token=token)

    incoming = _normalize_list_cc(phones)
    if not incoming:
        raise ValueError("no valid phone numbers after normalization (expect 66XXXXXXXXX)")

    _set_env_list_in_service_info(info, env_key, incoming)  # create if missing
    resp = _put_updated_service(cauth, token, info)
    if resp.status_code != 200:
        raise RuntimeError(f"update env var failed: {resp.status_code} - {resp.text}")
    return env_key, incoming

def remove_admin_phones(property_id: str, phones: list[str]) -> tuple[str, list[str]]:
    env_key = ENV_KEY_TEMPLATE.format(property_id=property_id)
    cauth = CloudAuthorization()
    token = cauth.get_access_token()
    info = cauth.get_cloud_run_service_info(access_token=token)

    current_raw, _ = _read_env_list_from_service_info(info, env_key)  # may be missing
    current = set(_normalize_list_cc(current_raw))
    to_remove = set(_normalize_list_cc(phones))
    if not to_remove:
        raise ValueError("no valid phone numbers after normalization (expect 66XXXXXXXXX)")

    final_list = sorted(p for p in current if p not in to_remove)     # if missing, stays []
    _set_env_list_in_service_info(info, env_key, final_list)          # ensures var exists (empty list)
    resp = _put_updated_service(cauth, token, info)
    if resp.status_code != 200:
        raise RuntimeError(f"update env var failed: {resp.status_code} - {resp.text}")
    return env_key, final_list