#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import logging
import os
from xml.etree import ElementTree as ET
from xml.sax.saxutils import escape

import requests
from flask import Flask, jsonify, request


FARASO_SOAP_ENDPOINT = os.getenv("FARASO_SOAP_ENDPOINT", "https://cp.faraso.org/resellersapi/index.php").strip()
FARASO_NAMESPACE = "https://cp.faraso.org/resellersapi/"
FARASO_API_USER = os.getenv("FARASO_API_USER", "").strip()
FARASO_API_PASS = os.getenv("FARASO_API_PASS", "").strip()
FARASO_BRIDGE_TOKEN = os.getenv("FARASO_BRIDGE_TOKEN", "").strip()
BRIDGE_HOST = os.getenv("FARASO_BRIDGE_HOST", "0.0.0.0").strip()
BRIDGE_PORT = int(os.getenv("FARASO_BRIDGE_PORT", "8080"))


logging.basicConfig(
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    level=logging.INFO,
    handlers=[
        logging.FileHandler("faraso_bridge.log", encoding="utf-8"),
        logging.StreamHandler(),
    ],
)
logger = logging.getLogger("faraso_bridge")
app = Flask(__name__)


def _soap_array(tag, items):
    safe_items = "".join(
        f'<item xsi:type="xsd:string">{escape(str(item or ""))}</item>'
        for item in items
    )
    return (
        f'<{tag} xsi:type="tns:stringArray" SOAP-ENC:arrayType="xsd:string[{len(items)}]">'
        f"{safe_items}</{tag}>"
    )


def _soap_value(tag, value):
    return f'<{tag} xsi:type="xsd:string">{escape(str(value or ""))}</{tag}>'


def faraso_call(method, params):
    if not FARASO_API_USER or not FARASO_API_PASS:
        return {"ok": False, "status": "config_error", "message": "FARASO_API_USER/PASS تنظیم نشده است."}

    body_parts = [
        _soap_value("api_user", FARASO_API_USER),
        _soap_value("api_pass", FARASO_API_PASS),
    ]
    for key, value in (params or {}).items():
        if isinstance(value, list):
            body_parts.append(_soap_array(key, value))
        else:
            body_parts.append(_soap_value(key, value))

    envelope = (
        '<?xml version="1.0" encoding="UTF-8"?>'
        '<SOAP-ENV:Envelope '
        'xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" '
        'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" '
        'xmlns:xsd="http://www.w3.org/2001/XMLSchema" '
        'xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" '
        f'xmlns:tns="{FARASO_NAMESPACE}">'
        '<SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">'
        f'<tns:{method}>{"".join(body_parts)}</tns:{method}>'
        '</SOAP-ENV:Body></SOAP-ENV:Envelope>'
    )
    headers = {
        "Content-Type": "text/xml; charset=utf-8",
        "SOAPAction": f"{FARASO_NAMESPACE}#{method}",
    }

    try:
        response = requests.post(FARASO_SOAP_ENDPOINT, data=envelope.encode("utf-8"), headers=headers, timeout=45)
        response.raise_for_status()
        root = ET.fromstring(response.text)
        response_node = root.find(".//{%s}%sResponse" % (FARASO_NAMESPACE, method))
        if response_node is None:
            fault = root.find(".//faultstring")
            message = fault.text.strip() if fault is not None and fault.text else "پاسخ نامعتبر از فراسو دریافت شد."
            logger.error("Faraso invalid response for %s: %s", method, response.text[:1000])
            return {"ok": False, "status": "error", "message": message}

        result = {}
        for child in list(response_node):
            tag = child.tag.split("}", 1)[-1]
            result[tag] = (child.text or "").strip()

        status_value = str(result.get("status", "")).strip()
        result["ok"] = status_value in {"1", "true", "True", "success", "available"}
        result.setdefault("message", "")
        logger.info("Faraso %s => %s", method, result)
        return result
    except Exception as exc:
        logger.exception("Faraso %s failed", method)
        return {"ok": False, "status": "error", "message": str(exc)}


def _auth_failed():
    return jsonify({"ok": False, "status": "unauthorized", "message": "invalid bridge token"}), 401


def _check_auth():
    if not FARASO_BRIDGE_TOKEN:
        return True
    auth_header = request.headers.get("Authorization", "")
    return auth_header == f"Bearer {FARASO_BRIDGE_TOKEN}"


@app.get("/health")
def health():
    if not _check_auth():
        return _auth_failed()
    info = faraso_call("accountInfo", {})
    return jsonify(
        {
            "ok": info.get("ok", False),
            "bridge": "up",
            "faraso": info,
        }
    )


@app.post("/call")
def call():
    if not _check_auth():
        return _auth_failed()
    payload = request.get_json(silent=True) or {}
    method = str(payload.get("method", "")).strip()
    params = payload.get("params", {}) or {}
    if not method:
        return jsonify({"ok": False, "status": "bad_request", "message": "method is required"}), 400
    result = faraso_call(method, params)
    return jsonify(result)


if __name__ == "__main__":
    logger.info("Starting Faraso bridge on %s:%s", BRIDGE_HOST, BRIDGE_PORT)
    app.run(host=BRIDGE_HOST, port=BRIDGE_PORT)
