from flask import Flask, render_template, request, redirect, url_for, session
from functools import wraps
from datetime import datetime, date, timedelta
import io
import os
import json
import qrcode
import base64

folder_config = {}

def require_secret(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        global folder_config 
        if not folder_config:
            with open('folder_config.json') as file:
                folder_config = json.load(file)

        def is_valid(config_item, provided_secret):
            """
            Checks if today's date is <= validity date
            AND if the provided secret matches config_item['secret'].
            """
            folder_validity = config_item['validity']
            # Convert string to a date if necessary:
            if isinstance(folder_validity, str):
                folder_validity = datetime.strptime(folder_validity, '%d.%m.%Y').date()

            # Return whether it's still valid and secrets match:
            return (
                date.today() <= folder_validity and
                provided_secret == config_item['secret']
            )

        # 1) Get secret from query params (if any)
        args_secret = request.args.get('secret')

        # 2) Initialize 'allowed_secrets' in the session if missing
        if 'allowed_secrets' not in session:
            session['allowed_secrets'] = []

        # 3) If a new secret is provided, check if it’s valid, and add to session if so
        if args_secret:
            for config_item in folder_config:
                if is_valid(config_item, args_secret):
                    if args_secret not in session['allowed_secrets']:
                        session['allowed_secrets'].append(args_secret)
                    session.permanent = True  # Make the session permanent

        # 4) Re-check validity of each secret in session['allowed_secrets']
        #    If a secret is no longer valid (or not in config), remove it.
        for secret_in_session in session['allowed_secrets'][:]:
            # Find the current config item with matching secret
            config_item = next(
                (c for c in folder_config if c['secret'] == secret_in_session),
                None
            )
            # If the config item doesn’t exist or is invalid, remove secret
            if config_item is None or not is_valid(config_item, secret_in_session):
                session['allowed_secrets'].remove(secret_in_session)

        # 5) Build session['folders'] fresh from the valid secrets
        session['folders'] = {}
        for secret_in_session in session.get('allowed_secrets', []):
            config_item = next(
                (c for c in folder_config if c['secret'] == secret_in_session),
                None
            )
            if config_item:
                for folder_info in config_item['folders']:
                    session['folders'][folder_info['foldername']] = folder_info['folderpath']

        # 6) If we have folders, proceed; otherwise show index
        if session['folders']:
            # assume since visitor has a valid secret, they are ok with annonymous tracking
            # this is required to track the devices connecting over the same ip address
            if 'device_id' not in session:
                session['device_id'] = os.urandom(32).hex()
            return f(*args, **kwargs)
        else:
            return render_template('index.html')

    return decorated_function

@require_secret
def mylinks():
    allowed_secrets = session.get('allowed_secrets', [])
    host = request.host

    secret_qr_codes = {}
    secret_folders = {}
    secret_valid_to = {}

    # Build a QR code for each secret (using the URL with the secret as query parameter)
    for secret in allowed_secrets:
        url = f"https://{host}?secret={secret}"
        qr = qrcode.QRCode(version=1, box_size=10, border=4)
        qr.add_data(url)
        qr.make(fit=True)
        img = qr.make_image(fill_color="black", back_color="white")
        buffer = io.BytesIO()
        img.save(buffer, format="PNG")
        buffer.seek(0)
        img_base64 = base64.b64encode(buffer.getvalue()).decode('ascii')
        secret_qr_codes[secret] = img_base64

        # Lookup folder info and valid-to date for this secret from the global folder_config.
        config_item = next((c for c in folder_config if c['secret'] == secret), None)
        if config_item:
            secret_folders[secret] = config_item['folders']
            secret_valid_to[secret] = config_item.get('validity', 'Unbekannt')
        else:
            secret_folders[secret] = []
            secret_valid_to[secret] = 'Unbekannt'

    return render_template('mylinks.html',
                           allowed_secrets=allowed_secrets,
                           secret_qr_codes=secret_qr_codes,
                           secret_folders=secret_folders,
                           secret_valid_to=secret_valid_to)


def remove_secret():
    secret_to_remove = request.form.get('secret')
    allowed_secrets = session.get('allowed_secrets', [])
    if secret_to_remove in allowed_secrets:
        allowed_secrets.remove(secret_to_remove)
        session['allowed_secrets'] = allowed_secrets
    return redirect(url_for('mylinks'))

    return render_template('mylinks.html',
                           allowed_secrets=allowed_secrets,
                           secret_qr_codes=secret_qr_codes,
                           secret_folders=secret_folders)