"""
FingerLock – Gestion du schéma de déverrouillage (pavé numérique 3x3)
"""
import hashlib
import json
import sys
from pathlib import Path
from pynput import keyboard as kb

# Grille 3x3
GRID = """
  ┌───┬───┬───┐
  │ 7 │ 8 │ 9 │
  ├───┼───┼───┤
  │ 4 │ 5 │ 6 │
  ├───┼───┼───┤
  │ 1 │ 2 │ 3 │
  └───┴───┴───┘
"""

VALID_KEYS = {'1','2','3','4','5','6','7','8','9',
              'kp_1','kp_2','kp_3','kp_4','kp_5',
              'kp_6','kp_7','kp_8','kp_9'}

def _normalize_key(key) -> str:
    """Normalise la touche vers un chiffre 1-9"""
    try:
        # Touche normale
        c = key.char
        if c in '123456789':
            return c
    except AttributeError:
        # Pavé numérique
        name = str(key).replace("Key.", "")
        mapping = {
            'kp_1': '1', 'kp_2': '2', 'kp_3': '3',
            'kp_4': '4', 'kp_5': '5', 'kp_6': '6',
            'kp_7': '7', 'kp_8': '8', 'kp_9': '9',
        }
        if name in mapping:
            return mapping[name]
    return None


def _hash_pattern(pattern: list) -> str:
    """Hash le schéma pour stockage sécurisé"""
    raw = "-".join(pattern)
    return hashlib.sha256(raw.encode()).hexdigest()


def _draw_grid_with_pattern(pattern: list):
    """Affiche la grille avec le schéma en cours"""
    positions = {
        '7': (0,0), '8': (0,1), '9': (0,2),
        '4': (1,0), '5': (1,1), '6': (1,2),
        '1': (2,0), '2': (2,1), '3': (2,2),
    }
    
    # Créer la grille
    grid = [['   ' for _ in range(3)] for _ in range(3)]
    
    for i, key in enumerate(pattern):
        if key in positions:
            r, c = positions[key]
            grid[r][c] = f' {key} '
    
    print(f"\n  ┌───┬───┬───┐")
    rows = ['7 8 9', '4 5 6', '1 2 3']
    for r_idx, row in enumerate(rows):
        keys = row.split()
        line = "  │"
        for k in keys:
            if k in pattern:
                line += f" {k} │"
            else:
                line += " · │"
        print(line)
        if r_idx < 2:
            print(f"  ├───┼───┼───┤")
    print(f"  └───┴───┴───┘")


def capture_pattern(prompt: str, min_points: int = 3) -> list:
    """
    Capture un schéma via le pavé numérique.
    Entrée = valider, Backspace = effacer dernier point, Echap = annuler
    """
    pattern = []
    done = False
    cancelled = False

    print(f"\n  {prompt}")
    print(f"  Utilisez le pavé numérique (1-9)")
    print(f"  Entrée = valider | Backspace = effacer | Echap = annuler")
    _draw_grid_with_pattern(pattern)
    print(f"  Schéma : (vide)")

    def on_press(key):
        nonlocal done, cancelled

        digit = _normalize_key(key)

        if digit:
            if digit not in pattern:  # Pas de doublon
                pattern.append(digit)
                _draw_grid_with_pattern(pattern)
                print(f"  Schéma : {' → '.join(pattern)}")
            else:
                print(f"  ⚠️  Point {digit} déjà utilisé !")

        elif key == kb.Key.backspace:
            if pattern:
                removed = pattern.pop()
                _draw_grid_with_pattern(pattern)
                print(f"  Schéma : {' → '.join(pattern) if pattern else '(vide)'}")

        elif key == kb.Key.enter:
            if len(pattern) < min_points:
                print(f"  ❌ Minimum {min_points} points requis ! ({len(pattern)} actuellement)")
            else:
                done = True
                return False  # Arrêter le listener

        elif key == kb.Key.esc:
            cancelled = True
            return False

    with kb.Listener(on_press=on_press) as listener:
        listener.join()

    if cancelled:
        return None
    return pattern


def setup_pattern(config_dir: Path) -> dict:
    """
    Configuration initiale du schéma.
    Retourne le schéma hashé et le délai.
    """
    print("\n  🔐 Configuration du schéma de déverrouillage\n")
    print(GRID)
    print("  La grille correspond au pavé numérique de votre clavier.")

    while True:
        # Étape 1 : Dessiner le schéma
        pattern = capture_pattern("Dessinez votre schéma :", min_points=3)
        if pattern is None:
            print("\n  ❌ Configuration annulée.\n")
            sys.exit(0)

        print(f"\n  ✅ Schéma enregistré : {' → '.join(pattern)}")

        # Étape 2 : Confirmer le schéma
        print("\n  🔄 Confirmez votre schéma :")
        confirm = capture_pattern("Redessinez le même schéma :", min_points=3)
        if confirm is None:
            print("\n  ❌ Configuration annulée.\n")
            sys.exit(0)

        if pattern == confirm:
            print("\n  ✅ Schéma confirmé !\n")
            break
        else:
            print("\n  ❌ Schémas différents ! Recommencez.\n")

    # Étape 3 : Délai d'inactivité
    while True:
        try:
            delay_input = input("  ⏱️  Délai d'inactivité avant verrouillage (secondes) [10] : ").strip()
            delay = int(delay_input) if delay_input else 10
            if delay < 1:
                print("  ❌ Le délai doit être au moins 1 seconde\n")
                continue
            break
        except ValueError:
            print("  ❌ Veuillez entrer un nombre entier\n")

    print(f"\n  ✅ Délai configuré : {delay} secondes\n")

    return {
        "pattern_hash": _hash_pattern(pattern),
        "lock_delay_seconds": delay,
        "platform_lock": "auto",
        "log_path": str(config_dir / "fingerlock.log"),
    }


def verify_pattern(stored_hash: str, max_attempts: int = 3) -> bool:
    """
    Demande à l'utilisateur de dessiner son schéma.
    Retourne True si correct, False sinon.
    """
    print("\n  🔒 Système verrouillé")
    print(GRID)
    print("  Dessinez votre schéma pour déverrouiller :\n")

    for attempt in range(1, max_attempts + 1):
        pattern = capture_pattern(
            f"  Tentative {attempt}/{max_attempts} :",
            min_points=3
        )

        if pattern is None:
            continue

        if _hash_pattern(pattern) == stored_hash:
            print("\n  ✅ Schéma correct ! Système déverrouillé.\n")
            return True
        else:
            remaining = max_attempts - attempt
            if remaining > 0:
                print(f"\n  ❌ Schéma incorrect ! {remaining} tentative(s) restante(s).\n")
            else:
                print(f"\n  ❌ Trop de tentatives incorrectes !\n")

    return False
