# Site Back-End Logic
from hmac import new
from unicodedata import category
from flask import Blueprint, render_template, request, flash, redirect, url_for, send_file
from flask_login import login_user, login_required, logout_user, current_user
from werkzeug.security import generate_password_hash, check_password_hash
from .models import User, Bookmark, Groups
from . import db
import string, secrets
import csv
import subprocess as sp
from . import iconfetch as icof

logic = Blueprint('logic', __name__)

# User Home Profile
@logic.route('/', methods=['GET', 'POST'])
@login_required
def home():
    # generate csv of bookmarks
    def generate_csv():
        header = ['name', 'link', 'group', 'status']
        alphanumeric = string.ascii_letters + string.digits
        ralphanum = ''.join(secrets.choice(alphanumeric) for i in range(16))
        open(f'app/static/generated/{ralphanum}.csv', 'a').close
        with open(f'app/static/generated/{ralphanum}.csv', 'w', encoding='UTF8', newline='') as f:
            writer = csv.writer(f, delimiter=',', quotechar='"')
            writer.writerow(header)
            for bg, bml in bb_dic.items():
                for bm in bml:
                    writer.writerow([bm.name, bm.link, bg, bm.status])
        p1 = sp.run(f'curl --upload-file app/static/generated/{ralphanum}.csv https://transfer.raqnet.org/',
                    shell=True,
                    capture_output=True,
                    text=True
                    )
        # clean up
        p2 = sp.run(f'rm app/static/generated/{ralphanum}.csv', shell=True)
        return redirect(p1.stdout, code=302)

    # initialize dictionary of bookmarks and groups
    # owned groups
    bgroups = Groups.query.filter_by(owner=current_user.id).all()
    # owned bookmarks
    bmarks = Bookmark.query.filter_by(owner=current_user.id).all()

    # populate bookmark dict for show
    bb_dic = dict() # dict of lists
    for bg in bgroups:
        inter_list = list()
        for bm in bmarks:
            if bm.group == bg.group:
                inter_list.append(bm)
        bb_dic[bg.group] = inter_list

    # POST request method
    if request.method == "POST":
        username = request.form.get('username')
        passwd = request.form.get('password')
        passwdc = request.form.get('password_confirm')
        new_pic = request.files.get('profile_image')
        dl_bookml = request.form.get('dl_bookml')

        if username:
            nusern_dbcall = User.query.filter_by(id=current_user.id).first()
            nusern_dbcall.username = username
            db.session.commit()
            flash('Username updated!', category='success')
        elif passwd and passwdc:
            if passwd == passwdc:
                npasswd_dbcall = User.query.filter_by(id=current_user.id).first()
                npasswd_dbcall.password = generate_password_hash(passwdc, method='sha256')
                db.session.commit()
                flash('Password successfully updated', category='success')
            else:
                flash('Passwords must match!', category='error')
        elif new_pic:
            # generate random filename for uploaded file 
            alphanumeric = string.ascii_letters + string.digits
            ralphanum = ''.join(secrets.choice(alphanumeric) for i in range(16))
            new_pic_dbcall = User.query.filter_by(id=current_user.id).first()
            if '.png' in new_pic.filename:
                new_pic.save(f'app/static/uploads/{ralphanum}.png')
                new_pic_dbcall.profile_image = f'{ralphanum}.png'
            elif '.jpg' in new_pic.filename or 'jpeg' in new_pic.filename:
                new_pic.save(f'app/static/uploads/{ralphanum}.jpeg')
                new_pic_dbcall.profile_image = f'{ralphanum}.jpeg'
            db.session.commit()
            flash('Profile Pic updated!', category='success')
        elif dl_bookml:
            return generate_csv()

    return render_template('home.html', user=current_user, bdic=bb_dic)

# Public Bookmarks
@logic.route('/shared', methods=['GET', 'POST'])
@login_required
def shared():

    # owned groups
    bgroups = Groups.query.filter_by(owner=current_user.id).all()
    # owned bookmarks
    bmarks = Bookmark.query.filter_by(owner=current_user.id).all()

    bb_dic = dict() # dict of lists
    for bg in bgroups:
        inter_list = list()
        for bm in bmarks:
            if bm.group == bg.group and bm.status == 'public':
                inter_list.append(bm)
        if len(inter_list) != 0:
            bb_dic[bg.group] = inter_list

    return render_template('shared.html', user=current_user, bdic=bb_dic)

# Create new bookmark
@logic.route('/create', methods=['GET', 'POST'])
@login_required
def create():

    # load bookmark groups
    bgroups = Groups.query.filter_by(owner=current_user.id).all()

    if request.method == 'POST':
        wlink = request.form.get('web_link')
        wname = request.form.get('web_name')
        wgroup = request.form.get('web_group')
        ngroup = request.form.get('new_group')
        wstatus = request.form.get('share_public_private')

        if wlink and wname and wstatus:

            # fetch/check icon
            sitecon = icof.check_icon(wlink)
            if not sitecon:
                sitecon = icof.fetch_icon(wlink)

            # add bookmark to database
            if wgroup == 'cng-555' and ngroup != '':
                wgroup = ngroup
            new_link = Bookmark(owner=current_user.id,
                                status=wstatus,
                                name=wname,
                                group=wgroup,
                                link=wlink,
                                icon=sitecon
                                )
            group_check = Groups.query.filter_by(group=wgroup).first()
            if not group_check:
                new_group = Groups(owner=current_user.id, group=wgroup)
                db.session.add(new_group)
            db.session.add(new_link)
            db.session.commit()
            flash('New Bookmark added!', category='success')

    return render_template('create_bookmark.html', user=current_user, bgroups=bgroups)

# Account management
@logic.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        email = request.form.get('email')
        challenge_passwd = request.form.get('passwd_login')

        user = User.query.filter_by(email=email).first()
        if user:
            if check_password_hash(user.password, challenge_passwd):
                flash('Successful Login!', category='success')
                login_user(user, remember=True)
                return redirect(url_for('logic.home'))
            else:
                flash('Unsucessful Login!', category='error')
        else:
            flash('Unsucessful Login!', category='error')
    
    return render_template('login.html', user=current_user)

@logic.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect(url_for('logic.login'))

@logic.route('/register', methods=['GET', 'POST'])
def register():
    pass_list = list()
    if request.method == 'POST':
        email = request.form.get('email') 
        username = request.form.get('username')
        passwd_1 = request.form.get('passwd_1')
        passwd_2 = request.form.get('passwd_2')

        # Basic User Input Checks
        email_check = User.query.filter_by(email=email).first()
        if len(email) < 1:
            flash('Your Email must be longer than 0 characters.', category='error')
        elif email_check:
            flash('This Email is already taken', category='error')
        else:
            pass_list.append('p')
    
        if len(username) < 1:
            flash('Username must be something', category='error')
        else:
            pass_list.append('p')

        if len(passwd_1) < 8 or len(passwd_2) < 8:
            flash('Your Password must be longer than or equal to 8 characters.', category='error')
        else:
            if passwd_1 != passwd_2:
                flash('Your Passwords must match!', category='error')
            else:
                if len(pass_list) == 2:
                    new_user = User(email=email, 
                                    username=username,
                                    password=generate_password_hash(passwd_2, method='sha256')
                                    )
                    db.session.add(new_user)
                    db.session.commit()
                    flash('Account Registration Successful!', category='success')
                    return redirect(url_for('logic.home'))
                else:
                    flash('Registration Failed', category='error')
    return render_template("register.html", user=current_user)
