# (c) cavaliba.com - sirene - sms.py

import os
import time
from datetime import datetime, timedelta
import random
import base64
import re

import requests

from django.utils import timezone
from celery import shared_task

from app_home.configuration import get_configuration
from app_home.log import log, DEBUG, INFO, WARNING, ERROR, CRITICAL
import app_home.cache as cache

from .models import SMSJournal




# ------------------------------------------------------------
@shared_task
def task_send_sms(dests, data, aaa=None):
    ''' returns number of sms sent successfully'''

    cache.init()

    if len(data) ==0:
        return 0

    count = 0

    for num in dests:
        result = sirene_send_sms(num, data, aaa=aaa)
        if result:
            count += 1

    return count


# -------------------------------------------------------------
def sms_encode(key, clear):
    enc = []
    for i in range(len(clear)):
        key_c = key[i % len(key)]
        enc_c = chr((ord(clear[i]) + ord(key_c)) % 256)
        enc.append(enc_c)
    return base64.urlsafe_b64encode("".join(enc).encode()).decode()

def sms_decode(key, enc):
    dec = []
    enc = base64.urlsafe_b64decode(enc).decode()
    for i in range(len(enc)):
        key_c = key[i % len(key)]
        dec_c = chr((256 + ord(enc[i]) - ord(key_c)) % 256)
        dec.append(dec_c)
    return "".join(dec)


# ----------------------------------------------------------------------
# Add journal entry

def add_journal(mobile=None, sms=None, aaa=None):

    quota = get_sms_quota(aaa)
    entry = SMSJournal()

    try:
        entry.created_by = aaa["username"]
    except:
        entry.created_by = "n/a"

    entry.mobile = mobile
    entry.quota = quota

    key = get_configuration("env","CAVALIBA_CIPHER_KEY")
    if key:
        entry.content = sms_encode(key, sms)
    else:
        entry.content = "no encryption key, no content."

    entry.save()


def get_sms_quota(aaa=None):

    if 'username' not in aaa:
        return 9999999

    period = timezone.now()-timedelta(days=1)
    sent = SMSJournal.objects.filter(created_by=aaa["username"], created_at__gte=period).count()

    quota = int(get_configuration("sirene", "SMS_QUOTA_PER_DAY"))

    sms_left = max(quota - sent, 0)

    return sms_left

# ----------------------------------------------------------------------
def sirene_send_sms(num, sms, aaa=None):
    ''' returns  True/False ''' 

    if not sms_check_valid_number(num):
        #error(domain="sms.send", data=f"Invalid SMS number {num}", aaa=aaa)
        return False

    mode = get_configuration("sirene","SMS_MODE") 

    # limit to 159 chars max
    sms_cut = sms[:153]
    if len(sms_cut) != len(sms):
        sms_cut += ' (...)'

    if mode == "stdout":
        return sms_mode_stdout(num, sms_cut, aaa=aaa)

    if mode == "folder":       
        return sms_mode_folder(num, sms_cut, aaa=aaa)

    if mode == "clicsecure":       
        return sms_mode_clicsecure(num, sms_cut, aaa=aaa)

    # NEXT : add SMS providers

    return False


# ----------------------------------------------------------------------------
def sms_check_valid_number(num):

    if not re.match(r'^[\d\s+()]+$', num):
        return False

    # if not re.match(r'^^\d{10}$', num):
    #     #print("SMS: incorrect SMS number: ", num)
    #     return False

    return True


# ----------------------------------------------------------------------
def sms_mode_stdout(num, sms, aaa=None):


    print(f"SMS (STDOUT) - {num} - {sms}")

    add_journal(mobile=num, sms=sms, aaa=aaa)
    log(INFO, aaa=aaa, app="sirene", view="sms", action="mode_stdout", status="OK", data=f"{num}")    

    return True


# ----------------------------------------------------------------------
def sms_mode_folder(num, sms, aaa=None):

    # to folder

    now_msec = time.time()
    filename = str(now_msec)
    filename = str(datetime.today().strftime('%Y-%m-%d-%H%M%S'))
    filename += "-"
    alea = int(random.random() * 1000000000)
    filename += str(alea)
    filename += ".json"

    sms_folder = get_configuration("sirene", "SMS_FOLDER")
    path = sms_folder + "/" + filename

    now = timezone.now()
    data = f"'timestamp': '{now}',\n'msec': {now_msec},\n'sms': '{num}',\n'message': '{sms}'\n"
    data = "{\n" + data + " }\n"
    f = open(path, "a")
    f.write(data)
    f.close()

    add_journal(mobile=num, sms=sms, aaa=aaa)
    log(INFO, aaa=aaa, app="sirene", view="sms", action="mode_folder", status="OK", data=f"{num}")    

    return True

# ----------------------------------------------------------------------
def sms_mode_clicsecure(num, sms, aaa=None):

    login    = get_configuration("env", "CAVALIBA_SMS_LOGIN")
    password = get_configuration("env", "CAVALIBA_SMS_PASSWORD")
    url      = get_configuration("env", "CAVALIBA_SMS_URL")



    query = "{}email={}&pass={}&numero={}&message={}".format(
        url,
        login,
        password,
        num,
        sms,
        )
    r = requests.get(query)

    if  r.text in ['80','81','92','94']:
        add_journal(mobile=num, sms=sms, aaa=aaa)
        log(INFO, aaa=aaa, app="sirene", view="sms", action="mode_clicsecure", status="OK", 
            data=f"{num} - clicsecure={r.text}")
        return True
    else:
        log(INFO, aaa=aaa, app="sirene", view="sms", action="mode_clicsecure", status="KO", 
            data=f"{num} - {r.status_code} - clicsecure={r.text}")    
        return False
