from datetime import datetime
from django.views.decorators.csrf import csrf_exempt
import requests
import base64
from requests.auth import HTTPBasicAuth
from django.http import HttpResponse, JsonResponse
from .models import CustomUser, SMSLog
from django.utils import timezone
import pytz

# @csrf_exempt
def get_access_token():
    client_id = "378691dd4e1d586aa48e5d34569e21f899052b7808c18029415fbd4f0fa225d0"
    client_secret = "3dc8c392a02d183716f4d3adc211e09cb3033bc96560879505a49f55e7dc6d70"
    url = 'https://api.sandbox.kwara.com/oauth/token'
    payload = {
        'grant_type': 'client_credentials',
        'client_id': client_id,
        'client_secret': client_secret,
    }
    response = requests.post(url, data=payload)

    if response.status_code == 200:
        access_token = response.json().get('access_token')
        if access_token:
            return access_token
        else:
            raise ValueError("Access token not found in the response")
    else:
        raise ValueError(f"Failed to fetch access token, status code: {response.status_code}")

# @csrf_exempt
def get_P_access_token():
    client_id = "hW5DhVcUHSb06W45ERIqdXX6D6C9CElC1KXbgkDWomQ"
    client_secret = "3tEroB79viucZc5sg6Fjqf6TpOevyXY_BQg-IaYxxpE"
    url = 'https://api.kwara.com/oauth/token'
    payload = {
        'grant_type': 'client_credentials',
        'client_id': client_id,
        'client_secret': client_secret,
    }
    response = requests.post(url, data=payload)

    if response.status_code == 200:
        access_token = response.json().get('access_token')
        if access_token:
            return access_token
        else:
            raise ValueError("Access token not found in the response")
    else:
        raise ValueError(f"Failed to fetch access token, status code: {response.status_code}")
    
def get_id_access_token():
    client_id = "EFlQP9jHT9riX5YKLeSew6RMGOvZDBN5fWRwyKhKV4I"
    client_secret = "1dUG9D9jUrOhEzbZL4OCVoLdxLvgYh_wcI09EUsqoKI"
    url = "https://api.kwara.com/oauth/token"
    payload = {
        'grant_type': 'client_credentials',
        'client_id': client_id,
        'client_secret': client_secret,
    }
    response = requests.post(url, data=payload)

    if response.status_code == 200:
        access_token = response.json().get('access_token')
        if access_token:
            return access_token
        else:
            raise ValueError("Access token not found in the response")
    else:
        raise ValueError(f"Failed to fetch access token, status code: {response.status_code}")

def get_iprs_access_token():
    consumer_key = "CK_ZTUzM2YxYmM2NGE4"
    consumer_secret = "CS_NTljMThkNmY1N2E5ZjE4NjVl"
    url = "https://api.spinmobile.co/api/analytics/auth/"
    payload = {
        'consumer_key': consumer_key,
        'consumer_secret': consumer_secret,
    }
    response = requests.post(url, data=payload)

    if response.status_code == 200:
        access_token = response.json().get('token')
        if access_token:
            return access_token
        else:
            raise ValueError("Access token not found in the response")
    else:
        raise ValueError(f"Failed to fetch access token, status code: {response.status_code}")

def generate_access_token():

    consumer_key = 'zAKlTtAgnCh9PedrNrsEI5iWR6wFlxJe0RABS2P1Vk3RhWGe'
    consumer_secret = 'lUvBSD4BjiqgdtLJBQGmAX1wANPzryVZnA2XYlotrGXDNcx90wfKDMuojbER52er'
    api_URL = "https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials"

    try:
        r = requests.get(api_URL, auth=HTTPBasicAuth(consumer_key, consumer_secret))
    except:
        r = requests.get(api_URL, auth=HTTPBasicAuth(consumer_key, consumer_secret), verify=False)

    # print(r.text)

    json_response = (
        r.json()
    )  # {'access_token': 'orfE9Dun2qqCpuXsORjcWGzvrAIY', 'expires_in': '3599'}

    my_access_token = json_response["access_token"]

    return my_access_token

def get_timestamp():
    unformatted_time = datetime.now()
    formatted_time = unformatted_time.strftime("%Y%m%d%H%M%S")

    return formatted_time

def generate_password():

    business_shortCode = '174379'
    passkey = 'bfb279f9aa9bdbcf158e97dd71a467cd2e0c893059b10f78e6b72ada1ed2c919'
    formatted_time = datetime.now().strftime('%Y%m%d%H%M%S')

    data_to_encode = (
        business_shortCode + passkey + formatted_time
    )

    encoded_string = base64.b64encode(data_to_encode.encode())
    # print(encoded_string) b'MjAxOTAyMjQxOTUwNTc='

    decoded_password = encoded_string.decode("utf-8")

    return decoded_password

def get_kwara_access_token():
    client_id = "378691dd4e1d586aa48e5d34569e21f899052b7808c18029415fbd4f0fa225d0"
    client_secret = "3dc8c392a02d183716f4d3adc211e09cb3033bc96560879505a49f55e7dc6d70"
    url = 'https://api.sandbox.kwara.com/oauth/token'
    payload = {
        'grant_type': 'client_credentials',
        'client_id': client_id,
        'client_secret': client_secret,
    }
    response = requests.post(url, data=payload)

    if response.status_code == 200:
        access_token = response.json().get('access_token')
        if access_token:
            return access_token
        else:
            raise ValueError("Access token not found in the response")
    else:
        raise ValueError(f"Failed to fetch access token, status code: {response.status_code}")

def helper_return_fosa_balance(sacco_member_id):
    access_token = get_P_access_token()
    # access_token = get_kwara_access_token()

    url = f"https://api.kwara.com/members/{sacco_member_id}/savings"
    headers = {
        'Authorization': f'Bearer {access_token}',
        'accept': 'application/json',
    }
    try:
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        savings_data = response.json().get('data', [])

        # Extract details of "FOSA Current" or product id "6006"
        fosa_savings = next(
            (s for s in savings_data if s.get('attributes', {}).get('product_name') == "FOSA Current" or s.get('attributes', {}).get('product_id') == "6006"),
            None
        )

        staff_savings = next(
            (s for s in savings_data if s.get('attributes', {}).get('product_name') == "Staff Account" or s.get('attributes', {}).get('product_id') == "6008"),
            None
        )

        if fosa_savings and staff_savings:
            available_balance = staff_savings['attributes'].get('available_balance')
            return available_balance
        elif fosa_savings:
            available_balance = fosa_savings['attributes'].get('available_balance')
            return available_balance
        elif staff_savings:
            available_balance = staff_savings['attributes'].get('available_balance')
            return available_balance
        else:
             return None

    except requests.exceptions.RequestException as e:
        return HttpResponse('Failed to fetch savings details: ' + str(e), content_type="application/json", status=500)

    except requests.exceptions.RequestException as e:
        return None

def helper_return_fosa_account(sacco_member_id):
    access_token = get_P_access_token()
    # access_token = get_kwara_access_token()

    url = f"https://api.kwara.com/members/{sacco_member_id}/savings"
    headers = {
        'Authorization': f'Bearer {access_token}',
        'accept': 'application/json',
    }
    try:
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        savings_data = response.json().get('data', [])

        # Extract details of "FOSA Current" or product id "6006"
        fosa_savings = next(
            (s for s in savings_data if s.get('attributes', {}).get('product_name') == "FOSA Current" or s.get('attributes', {}).get('product_id') == "6006"),
            None
        )

        staff_savings = next(
            (s for s in savings_data if s.get('attributes', {}).get('product_name') == "Staff Account" or s.get('attributes', {}).get('product_id') == "6008"),
            None
        )

        if fosa_savings and staff_savings:
            account_number = staff_savings['id']
            return account_number
        elif fosa_savings:
            account_number = fosa_savings['id']
            return account_number
        elif staff_savings:
            account_number = staff_savings['id']
            return account_number
        else:
             return None

        # if fosa_savings:
        #     account_number = fosa_savings['id'],
        #     return account_number
        # else:
        #     return None

    except requests.exceptions.RequestException as e:
        return None
    
def helper_fosa_withdrawal(amount, sacco_member_id, fosa_account):
    # print("Saco member id")

    # print(sacco_member_id)

    fosa_details = helper_return_fosa_details(sacco_member_id=sacco_member_id)
    # print("fosa_details")
    # print(fosa_details)
    user = CustomUser.objects.get(sacco_user_id=sacco_member_id)

    # print("account number")
    # print(fosa_account)
    # # print(fosa_details.get("account_number"))
    # print(user.phone)

    access_token = get_P_access_token()
    # access_token = get_kwara_access_token()

    url = "https://api.kwara.com/savings_transactions"

    payload = { "data": { "attributes": {
        "type": "WITHDRAWAL",
        "savings_id": fosa_account,
        "amount": amount,
        "phone_number": user.phone,
        "authorization_hold_id": "9fbadd7e-3a9f-4215-85c6-eff64a1c47a5",
        "bank_branch": "Central",
        "notes": "Withdraw from FOSA",
        "payment_method": "cash",
        "manual_journal_entry": True,
        "idempotency_key": "9fbadd7e-3a9f-4215-85c6-eff64a1c47a5",
    } } }
    headers = {
        "accept": "application/json",
        "Authorization": f"Bearer {access_token}"
    }

    response = requests.post(url, json=payload, headers=headers)

    return JsonResponse(response.json(), status=response.status_code)


def helper_return_fosa_details(sacco_member_id):
    access_token = get_P_access_token()
    # access_token = get_kwara_access_token()

    url = f"https://api.kwara.com/members/{sacco_member_id}/savings"
    headers = {
        'Authorization': f'Bearer {access_token}',
        'accept': 'application/json',
    }
    try:
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        savings_data = response.json().get('data', [])

        # Extract details of "FOSA Current" or product id "6006"
        fosa_savings = next(
            (s for s in savings_data if s.get('attributes', {}).get('product_name') == "FOSA Current" or s.get('attributes', {}).get('product_id') == "6006"),
            None
        )

        staff_savings = next(
            (s for s in savings_data if s.get('attributes', {}).get('product_name') == "Staff Account" or s.get('attributes', {}).get('product_id') == "6008"),
            None
        )

        if fosa_savings and staff_savings:
                return JsonResponse({
                    'account_number': staff_savings['id'],
                    'available_balance': staff_savings['attributes'].get('available_balance'),
                }, status=200)
        elif fosa_savings:
                return JsonResponse({
                    'account_number': fosa_savings['id'],
                    'available_balance': fosa_savings['attributes'].get('available_balance'),
                }, status=200)
        elif staff_savings:
                return JsonResponse({
                    'account_number': staff_savings['id'],
                    'available_balance': staff_savings['attributes'].get('available_balance'),
                }, status=200)
        else:
                return JsonResponse({
                    'message': 'Login successful, but no FOSA or Staff savings account found',
                }, status=200)

    except requests.exceptions.RequestException as e:
                return JsonResponse({'error': 'Failed to fetch savings details: ' + str(e)}, status=500)

def helper_send_sms(phone, message, department=None):
    # url = "https://sms.textsms.co.ke/api/services/sendsms/"
    # url = "https://quicksms.advantasms.com/api/services/sendsms/"
    url = "https://quicksms.advantasms.com/api/services/sendotp"

    headers = {
        'Accept': 'application/json'
    }
    # payload = { 
    #     "apikey":"3a1d904f5558759f119889e3fd1a9d00", 
    #     "partnerID":"11778", 
    #     "message":f"{message}", 
    #     "shortcode":"TextSMS", 
    #     "mobile":f"{phone}" 
    # }
    payload = {
        "apikey":"627ec9e3f8a43b7259f216566d58f54d",
        "partnerID":"12143",
        "message":f"{message}",
        "shortcode":"KBSACCO",
        "mobile":f"{phone}"
    }
    try:
        response = requests.post(url=url, headers=headers,json=payload)
        # return response.json()
        response_data = response.json()

        # Log the SMS response in the database
        SMSLog.objects.create(
            phone=phone,
            message=message,
            response_status=str(response_data.get("responses", [{}])[0].get("response-code", "Unknown")),
            response_message=str(response_data),
            department=department,
        )

        return response_data

    except requests.RequestException as e:
        # Log failed SMS attempt
        SMSLog.objects.create(
            phone=phone,
            message=message,
            response_status="FAILED",
            response_message=str(e),
            department=department,
        )
        return {"error": "Failed to send SMS"}

def helper_send_guarantor_sms(phone, message):
    if type(phone) == str:
        phone = phone.lstrip("+")
        """
        we have to handle phone number correctly here
        """
    # url = "https://quicksms.advantasms.com/api/services/sendsms/"
    url = "https://quicksms.advantasms.com/api/services/sendotp"

    headers = {
        'Accept': 'application/json'
    }

    utc = timezone.now() 
    eat_tz = pytz.timezone('Africa/Nairobi')  # EAT is UTC+3
    eat_time = utc.astimezone(eat_tz)
    time_sent = eat_time.strftime('%Y-%m-%d %H:%M:%S %Z')

    payload = {
        "apikey":"627ec9e3f8a43b7259f216566d58f54d",
        "partnerID":"12143",
        "message":f"{message}\n{time_sent}",
        "shortcode":"21737",
        "mobile":f"{phone}"
    }
    # response = requests.post(url=url, headers=headers,json=payload)
    # return response.json()
    try:
        response = requests.post(url=url, headers=headers,json=payload)
        # return response.json()
        response_data = response.json()

        # Log the SMS response in the database
        SMSLog.objects.create(
            phone=phone,
            message=message,
            response_status=str(response_data.get("responses", [{}])[0].get("response-code", "Unknown")),
            response_message=str(response_data),
            department="Loans & Credit",
        )
        return response_data

    except requests.RequestException as e:
        # Log failed SMS attempt
        SMSLog.objects.create(
            phone=phone,
            message=message,
            response_status="FAILED",
            response_message=str(e),
            department="Loans & Credit",
        )
        return {"error": "Failed to send SMS"}

def generate_mpesa_live_access_token():

    consumer_key = 'mhhBJ83EtbKAZPPLCvzDgxYRjPVBfyQc3lEt7gtmBRZhBfg5'
    consumer_secret = '0HkWGCfgmJHDjT18XcE1XPipG4J0ctr3kRrAhtXh65w6fGdxJEGDFGN03b9kbM3Y'
    api_URL = "https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials"

    try:
        r = requests.get(api_URL, auth=HTTPBasicAuth(consumer_key, consumer_secret))
    except:
        r = requests.get(api_URL, auth=HTTPBasicAuth(consumer_key, consumer_secret), verify=False)

    # print(r.text)

    json_response = (
        r.json()
    )  # {'access_token': 'orfE9Dun2qqCpuXsORjcWGzvrAIY', 'expires_in': '3599'}

    my_access_token = json_response["access_token"]
    # print(my_access_token)

    return my_access_token

def generate_kbs_mpesa_live_access_token():

    consumer_key = 'meGyZMIe69vAC2a033yZuSKNV3vXPkFu'
    consumer_secret = 'IuNUxkjyGquGaclu'
    api_URL = "https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials"

    try:
        r = requests.get(api_URL, auth=HTTPBasicAuth(consumer_key, consumer_secret))
    except:
        r = requests.get(api_URL, auth=HTTPBasicAuth(consumer_key, consumer_secret), verify=False)

    # print(r.text)

    json_response = (
        r.json()
    )  # {'access_token': 'orfE9Dun2qqCpuXsORjcWGzvrAIY', 'expires_in': '3599'}

    my_access_token = json_response["access_token"]
    # print(my_access_token)

    return my_access_token

def helper_return_member_phone_number(member_id):
    access_token = get_P_access_token()
    # access_token = get_access_token()

    url = f'https://api.kwara.com/members/{member_id}'
    headers = {
        'Authorization': f'Bearer {access_token}',
        'accept': 'application/json',
    }
    try:
        response = requests.get(url, headers=headers)
        response.raise_for_status()  # Raise an error for bad status codes
        data = response.json()  # Get the full response as JSON
        # Extract the phone number from the response data
        phone_number = data.get('data', {}).get('attributes', {}).get('phone_number', '')
        # Return only the phone number in the response
        return phone_number
    except requests.RequestException as e:
            return JsonResponse({'error': str(e)}, status=500)
    
def helper_fetch_balances(sacco_member_id):
    access_token = get_P_access_token()
    # access_token = get_kwara_access_token()

    url = f"https://api.kwara.com/members/{sacco_member_id}/savings"
    headers = {
        'Authorization': f'Bearer {access_token}',
        'accept': 'application/json',
    }

    try:
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        savings_data = response.json().get('data', [])

        # Initialize balances
        balances = {
            "fosa_balance": None,
            "share_capital_balance": None,
            "main_savings_balance": None
        }

        # Loop through savings data and extract balances
        for savings in savings_data:
            product_id = savings.get('attributes', {}).get('product_id')
            product_name = savings.get('attributes', {}).get('product_name')
            available_balance = savings.get('attributes', {}).get('available_balance', 0)

            # Check for FOSA Current (normal user or staff)
            if product_id in ["6006", "6008"] or product_name in ["FOSA Current", "Staff Account"]:
                balances["fosa_balance"] = available_balance

            # Check for Share Capital
            if product_id == "6011" or product_name == "Share Capital":
                balances["share_capital_balance"] = available_balance

            # Check for Main Savings
            if product_id == "6001" or product_name == "Main Savings":
                balances["main_savings_balance"] = available_balance

        return balances

    except requests.exceptions.RequestException as e:
        return {"error": f"Failed to fetch savings details: {str(e)}"}
    
def helper_return_share_capital_balance(sacco_member_id):
    url = f"https://api.kwara.com/members/{sacco_member_id}/savings"
    dormantUrl = f"https://api.kwara.com/members/{sacco_member_id}/savings?filter[state]=DORMANT"
    access_token = get_P_access_token()
    # access_token = get_kwara_access_token()
    headers = {
        'Authorization': f'Bearer {access_token}',
        'accept': 'application/json',
    }

    response = requests.get(url, headers=headers)
    DormantResponse = requests.get(dormantUrl, headers=headers)
    response.raise_for_status()
    DormantResponse.raise_for_status()
    savings_data = response.json().get('data', [])
    Dormant_savings_data = DormantResponse.json().get('data', [])

    share_capital = next(
                    (s for s in savings_data if s.get('attributes', {}).get('product_name') == "Share Capital" or s.get('attributes', {}).get('product_id') == "6011"),
                    None
    )

    if not share_capital:
                    share_capital = next(
                        (s for s in Dormant_savings_data if s.get('attributes', {}).get('product_name') == "Share Capital" or s.get('attributes', {}).get('product_id') == "6011"),
                        None
    )

    # If no savings found, check for dormant savings
    # if not savings_data:
    #     dormant_url = f"https://api.sandbox.kwara.com/members/{sacco_member_id}/savings?filter[state]=DORMANT"
    #     savings_data = fetch_savings(dormant_url)

    # # Extract details of "Share Capital" or product ID "6011"
    # if savings_data:
    #     share_capital_savings = next(
    #         (s for s in savings_data if s.get('attributes', {}).get('product_name') == "Share Capital" or s.get('attributes', {}).get('product_id') == "6011"),
    #         None
    #     )
    if share_capital:
        return share_capital['attributes'].get('available_balance')
    else:
        return None