"""eSewa ePay v2 integration (sandbox: product code EPAYTEST).

Implements the official flow from developer.esewa.com.np/pages/Epay:
  1. Build a signed form -> browser POSTs it to eSewa's payment page.
  2. eSewa redirects back to success_url with ?data=<base64 JSON>.
  3. We verify the response signature (HMAC-SHA256 over signed_field_names,
     same key), and independently re-check via the status API when in doubt.

Switching to production = replacing the four values in
settings.ESEWA_SETTINGS. Nothing in this module changes.

Signature spec (verified against the official docs):
  message  = "total_amount=110,transaction_uuid=241028,product_code=EPAYTEST"
             (values of signed_field_names, in that exact order)
  signature = base64( HMAC_SHA256(secret_key, message) )
"""
import base64
import hashlib
import hmac
import json

from django.conf import settings


def _cfg():
    return settings.ESEWA_SETTINGS


def _sign(message: str) -> str:
    digest = hmac.new(_cfg()['SECRET_KEY'].encode(), message.encode(), hashlib.sha256).digest()
    return base64.b64encode(digest).decode()


def _fmt_amount(value) -> str:
    """eSewa examples use plain numbers; send integers without decimals,
    otherwise two decimal places."""
    f = float(value)
    return str(int(f)) if f == int(f) else f'{f:.2f}'


def build_esewa_form(payment, success_url, failure_url):
    """All hidden-input fields for the auto-submit form, signature included."""
    total = _fmt_amount(payment.amount)
    signed_field_names = 'total_amount,transaction_uuid,product_code'
    message = (f"total_amount={total},transaction_uuid={payment.transaction_uuid},"
               f"product_code={_cfg()['PRODUCT_CODE']}")
    return {
        'amount': total,
        'tax_amount': '0',
        'total_amount': total,
        'transaction_uuid': payment.transaction_uuid,
        'product_code': _cfg()['PRODUCT_CODE'],
        'product_service_charge': '0',
        'product_delivery_charge': '0',
        'success_url': success_url,
        'failure_url': failure_url,
        'signed_field_names': signed_field_names,
        'signature': _sign(message),
    }


def esewa_form_url():
    return _cfg()['FORM_URL']


def decode_callback(data_b64: str):
    """Decode the base64 JSON eSewa appends to success_url as ?data=..."""
    try:
        padded = data_b64 + '=' * (-len(data_b64) % 4)
        return json.loads(base64.b64decode(padded).decode())
    except Exception:
        return None


def verify_callback_signature(decoded: dict) -> bool:
    """Recompute the HMAC over signed_field_names (in their given order)."""
    try:
        field_names = [f.strip() for f in decoded['signed_field_names'].split(',')]
        message = ','.join(f"{name}={decoded[name]}" for name in field_names
                           if name != 'signature')
        return hmac.compare_digest(_sign(message), decoded.get('signature', ''))
    except Exception:
        return False


def check_status(payment, timeout=15):
    """Server-to-server enquiry - the authoritative answer when the redirect
    is missing or its signature can't be trusted. Returns the parsed JSON
    (contains 'status' and 'ref_id') or None on network failure."""
    import requests
    try:
        resp = requests.get(
            _cfg()['STATUS_CHECK_URL'],
            params={
                'product_code': _cfg()['PRODUCT_CODE'],
                'total_amount': _fmt_amount(payment.amount),
                'transaction_uuid': payment.transaction_uuid,
            },
            timeout=timeout,
        )
        return resp.json()
    except Exception:
        return None
