import logging
import requests
from pypos.core.utils.config_utils import read_endpoint_config
from pypos.core.utils.http_retry import post_with_retry
from pypos.core.utils.device_utils import get_device_id

LOGGER = logging.getLogger(__name__)


def _build_endpoint_url(config, key, fallback_key=""):
    base_url = str((config or {}).get("api_base_url") or "").rstrip("/")
    endpoint = str((config or {}).get(key) or "").strip()
    if not endpoint and fallback_key:
        endpoint = str((config or {}).get(fallback_key) or "").strip()
    if endpoint and not endpoint.startswith("/"):
        endpoint = "/" + endpoint
    if not base_url or not endpoint:
        return ""
    return f"{base_url}{endpoint}"


def get_branch_list():
    branch_rows = get_branch_rows()
    branches = []
    for branch in branch_rows:
        nama = branch.get("nama")
        branch_id = branch.get("id")
        if nama is None or branch_id is None:
            continue
        branches.append((nama, branch_id))
    return branches


def _extract_branch_rows(response_payload):
    if not isinstance(response_payload, dict):
        return []
    data_block = response_payload.get("data")
    if isinstance(data_block, dict):
        rows = data_block.get("per_cabang")
        if isinstance(rows, list):
            return rows
    rows = response_payload.get("per_cabang")
    if isinstance(rows, list):
        return rows
    return []


def get_branch_rows(toko_id=None):
    config = read_endpoint_config() or {}
    url_primary = _build_endpoint_url(config, "ep_branch_lookup")
    url_fallback = _build_endpoint_url(config, "ep_datas")
    if not url_primary and not url_fallback:
        LOGGER.warning("Endpoint sinkron cabang belum valid (api_base_url/ep_branch_lookup kosong).")
        return []

    device_id = get_device_id()
    payload_primary = {"machine_id": device_id}
    if toko_id is not None and str(toko_id).strip():
        payload_primary["toko_id"] = str(toko_id).strip()

    payload_fallback = {
        "date_last[per_cabang]": "1990-01-01 23:59:59",
        "date_last[per_cabang_device]": "1990-01-01 23:59:59",
        "machine_id": device_id,
        "cabang_id": "none",
    }

    headers = {
        "Content-Type": "application/x-www-form-urlencoded"
    }

    def _fetch_rows(url, payload):
        if not url:
            return [], 0
        try:
            response = post_with_retry(
                url,
                data=payload,
                headers=headers,
                timeout=int(config.get("request_timeout", 10) or 10),
            )
            status_code = int(response.status_code or 0)
            if status_code != 200:
                return [], status_code
            data = response.json()
            return _extract_branch_rows(data), status_code
        except (requests.exceptions.RequestException, ValueError, TypeError, RuntimeError) as exc:
            response = getattr(exc, "response", None)
            status_code = int(getattr(response, "status_code", 0) or 0)
            return [], status_code

    try:
        branches, status_primary = _fetch_rows(url_primary, payload_primary)
        if not branches and status_primary != 200 and url_fallback and url_fallback != url_primary:
            branches, _ = _fetch_rows(url_fallback, payload_fallback)
        if not branches and status_primary and status_primary != 200:
            LOGGER.warning("API cabang mengembalikan status %s", status_primary)

        filtered = []
        expected_toko = str(toko_id).strip() if toko_id is not None else ""
        for branch in branches:
            if not isinstance(branch, dict):
                continue
            nama = branch.get("nama")
            branch_id = branch.get("id")
            if nama is None or branch_id is None:
                continue
            if expected_toko:
                branch_toko = str(branch.get("toko_id") or "").strip()
                if branch_toko and branch_toko != expected_toko:
                    continue
            filtered.append(dict(branch))
        return filtered
    except (requests.exceptions.RequestException, RuntimeError, ValueError, TypeError) as e:
        LOGGER.warning("Gagal mengambil daftar cabang: %s", e)
        return []
