import requests
from pymemri.data.itembase import Edge
from pymemri.plugin.schema import Account, PluginRun
from pymemri.pod.client import PodClient
import flask
import multiprocessing
from flask import render_template, make_response
from time import sleep
import os
from pymemri.plugin.states import RUN_USER_ACTION_NEEDED, RUN_USER_ACTION_COMPLETED
from pymemri.plugin.pluginbase import POD_PLUGIN_DNS_ENV, PluginBase
from pymemri.cvu.utils import get_default_cvu

app = flask.Flask(__name__, template_folder='template')
qr_code_dict = None

QR_CODE_KEY = "qr_code"


@app.route('/qr')
def index():
    global qr_code_dict
    qr_code_data = qr_code_dict[QR_CODE_KEY]
    done = qr_code_dict.get("authenticated", False)
    if done:
        res = render_template("success.html")
    else:
        res =  render_template('images.html', chart_output=qr_code_data)

    response = make_response(res)
    response.headers.add('Access-Control-Allow-Origin', '*')
    return response

def run_app(qr_dict, host="0.0.0.0", port=8080):
    global qr_code_dict
    qr_code_dict = qr_dict
    app.run(host=host, port=port)

@app.before_first_request
def _run_on_start():
    print("ABC")

def send_email(plugin_run, client, full_user_auth_url):
    # To make auth possible without email, attach url to pluginrun.
    plugin_run.authUrl = full_user_auth_url
    
    # Gather email
    plugin_run.status = RUN_USER_ACTION_NEEDED
    email_cvu = get_default_cvu("request_email.cvu")
    client.bulk_action(
        create_items=[email_cvu], 
        create_edges=[Edge(plugin_run, email_cvu, "view")]
    )
    client.update_item(plugin_run)

	# Poll until status == "ready"
    print("Polling for email...")
    while plugin_run.status != RUN_USER_ACTION_COMPLETED:
        sleep(1)
        plugin_run = client.get(plugin_run.id)

    # send email
    print("Sending email...")
    try:
        to = plugin_run.account[0].authEmail
        if to is None:
            raise ValueError("no auth email")
        client.send_email(to, subject="The link to your qr code", body=full_user_auth_url)
        email_sent = True
    except Exception as e:
        email_sent = False
        print(f"failed to send email:\n{e}")  
    
    # depending on whether email was a success, either show qr link, or message that link was sent to email
    if not email_sent:
        # NOTE Theres currently no documented way to delete edges, so client will have to pick the last added cvu.
        client.bulk_action(delete_items=[email_cvu])
        cvu = get_default_cvu("qr_code_auth.cvu")
        client.create(cvu)
        plugin_run.add_edge("view", cvu)
        client.create_edge(plugin_run.get_edges("view")[0])
        plugin_run.status = RUN_USER_ACTION_NEEDED
        plugin_run.authUrl = full_user_auth_url
        client.update_item(plugin_run)

def run_qr_flow(_qr_code_data, client: PodClient, plugin_run: PluginRun):
    manager = multiprocessing.Manager()
    process_dict = manager.dict()
    process_dict["qr_code"] = _qr_code_data
    process_dict["authenticated"] = False
    # assert client.update_item(plugin_run)
    host = "0.0.0.0"
    port = 8080
    user_host = os.environ.get(POD_PLUGIN_DNS_ENV, f"http://0.0.0.0:{port}")
    full_user_auth_url = f"{user_host}/qr"
    process = multiprocessing.Process(target=run_app, args=(process_dict,),
                                      kwargs={"host": host, "port": port}, daemon=True)
    process.start()

    # give time to start
    ready = False
    while not ready:
        ready = requests.get(f"http://{host}:{port}/qr").status_code in [200, 201]
        sleep(0.2)

    print(f"GO TO {full_user_auth_url} and scan the code")

    process_email = multiprocessing.Process(target=send_email, args=(plugin_run, client, full_user_auth_url), daemon=True)
    process_email.start()
    
    return process, process_dict

if __name__ == "__main__":
    # this is here for testing purposes, no function in production
    qr_code_data ="data:image/svg+xml;base64, "
    qr_code_dict = dict()
    qr_code_dict[QR_CODE_KEY] = qr_code_data
    client = PodClient()
    plugin_run = PluginRun()
    host = "0.0.0.0"
    port = 8080
    process = multiprocessing.Process(target=run_app, args=(qr_code_dict,),
                                    kwargs={"host": host, "port": port}, daemon=True)
    process.start()
    # process = run_qr_flow(qr_code_data, client, plugin_run)
    i=0
    while i<100:
        print(requests.get(f"http://{host}:{port}/qr"))
        i+=1
        sleep(1)
        print("waiting")
    