# vouchers/services.py

# import requests
# from .models import TokenCache
# from .utils import decrypt_payload
# from django.utils import timezone
# curl -X GET https://send.bulkgv.com/API/v1/gettoken -H "username: ZVBPNPCHVMBUAQTZYOWPLTXVWXWYERDS" -H "password: ]soLj$si!x6IL![KP~rkQ^sXG^hT3yJS" -H "Content-Type: application/json"

USERNAME = "ZVBPNPCHVMBUAQTZYOWPLTXVWXWYERDS"
PASSWORD = "]soLj$si!x6IL![KP~rkQ^sXG^hT3yJS"
BASE_URL = "https://send.bulkgv.net/API/v1"
# BASE_URL = "https://send.bulkgv.com/API/v1"





# vouchers/services.py
import requests
from .utils import decrypt_payload
from .models import TokenCache

# USERNAME = "PCHVMBVBPNPLTXVZWXWYERDS"
# PASSWORD = "]so[KP~rkQ^Lj$G^hT3si!x6IL!sXyJS"
# BASE_URL = "https://send.buglr.net/API/v1"


from .models import TokenCache
from django.utils import timezone

def get_cached_token():
    token_obj = TokenCache.objects.last()
    if token_obj and not token_obj.is_expired():
        return token_obj.token
    return get_token()


def get_token():
    try:
        headers = {
            "Content-Type": "application/json",
            "username": USERNAME,
            "password": PASSWORD
        }
        res = requests.get(f"{BASE_URL}/gettoken", headers=headers)
        print("🔍 Raw Response:", res.status_code, res.text)

        if res.status_code == 200:
            data = res.json()
            print("✅ JSON:", data)

            if data['status'] == 'success' and data['code'] == '0000':
                decrypted = decrypt_payload(data['data'])
                print("🔓 Decrypted Token:", decrypted)

                TokenCache.objects.all().delete()
                TokenCache.objects.create(token=decrypted)
                return decrypted
            else:
                print("⚠️ Status or Code Error:", data.get('desc'))
        else:
            print("❌ HTTP Error:", res.status_code)

    except Exception as e:
        print("💥 Exception during token fetch:", str(e))

    return None


# vouchers/services.py
# vouchers/services.py

import time
import requests
import json

from .utils import encrypt_payload, decrypt_payload
from .models import Brand, VoucherPurchaseHistory
from .services import get_cached_token  # use cached token to reduce load

RETRYABLE_CODES = ['ER047', 'ER1057', 'ER1056', 'ER1006', 'EROIP', '1048']
BASE_URL = "https://send.bulkgv.net/API/v1"
def pull_voucher(brand_product_code, denomination, quantity, order_id, assign_to_user=None):
    from .models import Voucher, UserVoucher  # avoid circular imports
    token = get_cached_token()
    if not token:
        return {"success": False, "reason": "Token fetch failed"}

    payload = {
        "BrandProductCode": brand_product_code,
        "Denomination": denomination,
        "Quantity": quantity,
        "ExternalOrderId": order_id
    }

    encrypted_payload = encrypt_payload(payload)
    headers = {
        "Content-Type": "application/json",
        "token": token
    }
    post_data = {"payload": encrypted_payload}

    retry_count = 0
    max_retries = 2
    wait_time_sec = 120

    while retry_count <= max_retries:
        try:
            response = requests.post(f"{BASE_URL}/pullvoucher", headers=headers, json=post_data, timeout=15)
            print(f"🔁 Attempt {retry_count+1} ➜ Status: {response.status_code}")
            res_json = response.json()

            status = res_json.get("status", "")
            code = res_json.get("code", "")
            desc = res_json.get("desc", "")

            if status == "success" and code in ["0000", "ER048"]:
                data_encrypted = res_json.get("data", "")
                if not data_encrypted:
                    return {"success": False, "reason": "No data in response"}

                decrypted_data = decrypt_payload(data_encrypted)
                voucher_info = decrypted_data['PullVouchers'][0]['Vouchers'][0]
                product_info = decrypted_data['PullVouchers'][0]

                try:
                    brand = Brand.objects.get(product_code=brand_product_code)
                except Brand.DoesNotExist:
                    return {"success": False, "reason": "Brand not found"}

                # Save to Voucher model
                voucher, created = Voucher.objects.get_or_create(
                    voucher_code=voucher_info['VoucherGCcode'],
                    defaults={
                        "voucher_guid": voucher_info['VoucherGuid'],
                        "brand": brand,
                        "value": voucher_info['Value'],
                        "expiry_date": voucher_info['EndDate'],
                        "product_name": product_info['ProductName'],
                        "voucher_name": product_info['VoucherName'],
                    }
                )

                # Assign to user if passed
                if assign_to_user:
                    UserVoucher.objects.create(
                        user=assign_to_user,
                        voucher=voucher,
                        order_id=order_id
                    )

                # Log purchase history
                VoucherPurchaseHistory.objects.create(
                    order_id=order_id,
                    brand=brand,
                    denomination=denomination,
                    quantity=quantity,
                    response=json.dumps(decrypted_data)
                )

                return {
                    "success": True,
                    "data": decrypted_data,
                    "voucher": voucher.voucher_code
                }

            elif status == "error" and code in RETRYABLE_CODES:
                retry_count += 1
                print(f"⚠️ Retryable error ({code}) ➜ {desc} ➜ Retrying in {wait_time_sec} sec...")
                time.sleep(wait_time_sec)

            else:
                return {
                    "success": False,
                    "reason": f"Voucher pull failed",
                    "code": code,
                    "desc": desc
                }

        except requests.exceptions.Timeout:
            retry_count += 1
            print(f"⚠️ Timeout occurred ➜ Retrying in {wait_time_sec} sec...")
            time.sleep(wait_time_sec)

        except Exception as e:
            return {"success": False, "reason": f"Exception: {str(e)}"}

    return {"success": False, "reason": "Max retries reached"}
