#!/usr/bin/env python3
"""
Script pour logger une session de daily check et mettre à jour les stats.

Usage:
    python log_session.py --cards "CORE-001,ACTION-006,FUTURE-001" --scores "✅,⚠️,❌"

    OU en mode interactif:
    python log_session.py --interactive

Options:
    --cards      : Liste des IDs de cartes (séparées par virgules)
    --scores     : Liste des scores ✅/⚠️/❌ (séparées par virgules)
    --interactive: Mode interactif qui demande les infos
    --dry-run    : Test sans modifier les fichiers
"""

import os
import re
import argparse
from datetime import datetime
from pathlib import Path


# Chemins relatifs au script
SCRIPT_DIR = Path(__file__).parent
BASE_DIR = SCRIPT_DIR.parent
CARD_DB_PATH = BASE_DIR / "card_database.md"
CARDS_DIR = BASE_DIR / "cards"
SESSIONS_LOG = BASE_DIR / "daily_sessions.md"


def parse_card_database():
    """Parse le fichier card_database.md et retourne un dict {card_id: card_info}."""
    with open(CARD_DB_PATH, 'r', encoding='utf-8') as f:
        content = f.read()

    # Trouver la table markdown
    table_pattern = r'\| ID \| Card \| Difficulty.*?\n\|---.*?\n((?:\|.*?\n)+)'
    match = re.search(table_pattern, content, re.DOTALL)

    if not match:
        raise ValueError("Impossible de trouver la table dans card_database.md")

    table_rows = match.group(1).strip().split('\n')

    cards = {}
    for row in table_rows:
        cols = [col.strip() for col in row.split('|')[1:-1]]

        if len(cols) < 8:
            continue

        card_id, card_file, difficulty, frequency, last_review, success_rate, times_failed, critical = cols

        cards[card_id] = {
            'id': card_id,
            'file': card_file,
            'difficulty': difficulty,
            'frequency': frequency,
            'last_review': last_review,
            'success_rate': success_rate,
            'times_failed': int(times_failed) if times_failed.isdigit() else 0,
            'critical': critical == '⚠️'
        }

    return cards


def update_card_file(card_file, score, today_str):
    """Met à jour les stats dans le fichier de carte individuel."""
    card_path = CARDS_DIR / card_file

    with open(card_path, 'r', encoding='utf-8') as f:
        content = f.read()

    # Update Last Review
    content = re.sub(
        r'\*\*Last Review\*\*: .*',
        f'**Last Review**: {today_str}',
        content
    )

    # Update Times Failed
    if score == '❌':
        # Incrémenter Times Failed
        def increment_failed(match):
            current = int(match.group(1)) if match.group(1).isdigit() else 0
            return f'**Times Failed**: {current + 1}'

        content = re.sub(
            r'\*\*Times Failed\*\*: (\d+)',
            increment_failed,
            content
        )

    # Update Success Rate
    # Extraire le success rate actuel
    success_match = re.search(r'\*\*Success Rate\*\*: (.*)', content)
    if success_match:
        current_rate_str = success_match.group(1).strip()

        # Parse le success rate actuel
        if current_rate_str in ['N/A', 'N/A (nouveau)']:
            # Première review
            if score == '✅':
                new_rate = '100% (1/1)'
            elif score == '⚠️':
                new_rate = '50% (0.5/1)'
            else:  # ❌
                new_rate = '0% (0/1)'
        else:
            # Parse "X% (n/total)" ou juste "X%"
            rate_match = re.match(r'(\d+)%\s*\(?([\d.]+)/(\d+)\)?', current_rate_str)
            if rate_match:
                current_percent, successes, total = rate_match.groups()
                successes = float(successes)
                total = int(total)
            else:
                # Fallback: juste un pourcentage
                rate_match = re.match(r'(\d+)%', current_rate_str)
                if rate_match:
                    current_percent = int(rate_match.group(1))
                    # Estimer successes/total basé sur le pourcentage
                    successes = 1 if current_percent >= 50 else 0
                    total = 1
                else:
                    successes = 0
                    total = 0

            # Ajouter la nouvelle review
            total += 1
            if score == '✅':
                successes += 1
            elif score == '⚠️':
                successes += 0.5

            new_percent = int((successes / total) * 100) if total > 0 else 0
            new_rate = f'{new_percent}% ({successes}/{total})'

        content = re.sub(
            r'\*\*Success Rate\*\*: .*',
            f'**Success Rate**: {new_rate}',
            content
        )

    return content


def update_card_database(cards_dict, today_str):
    """Met à jour la table dans card_database.md avec les nouvelles stats."""
    with open(CARD_DB_PATH, 'r', encoding='utf-8') as f:
        content = f.read()

    # Pour chaque carte, update sa ligne dans la table
    for card_id, card_info in cards_dict.items():
        # Trouver la ligne correspondante
        row_pattern = rf'\| {re.escape(card_id)} \| ([^\n]+)'
        match = re.search(row_pattern, content)

        if match:
            old_row = match.group(0)

            # Reconstruire la nouvelle ligne
            critical_symbol = '⚠️' if card_info['critical'] else ''
            new_row = (
                f"| {card_id} | {card_info['file']} | {card_info['difficulty']} | "
                f"{card_info['frequency']} | {card_info['last_review']} | "
                f"{card_info['success_rate']} | {card_info['times_failed']} | {critical_symbol} |"
            )

            content = content.replace(old_row, new_row)

    # Update "Dernière mise à jour"
    content = re.sub(
        r'\*\*Dernière mise à jour\*\* : \d{2}/\d{2}/\d{4}',
        f'**Dernière mise à jour** : {today_str}',
        content
    )

    return content


def calculate_streak(sessions_content):
    """Calcule le streak actuel basé sur le fichier daily_sessions.md."""
    # Trouver toutes les sessions
    session_pattern = r'### (\d{4}-\d{2}-\d{2})'
    dates = re.findall(session_pattern, sessions_content)

    if not dates:
        return 1  # Première session

    # Convertir en datetime
    session_dates = []
    for date_str in dates:
        try:
            session_dates.append(datetime.strptime(date_str, '%Y-%m-%d'))
        except ValueError:
            continue

    if not session_dates:
        return 1

    # Trier par date décroissante
    session_dates.sort(reverse=True)

    today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)

    # Calculer le streak
    streak = 1  # Aujourd'hui compte
    last_date = today

    for session_date in session_dates:
        session_date = session_date.replace(hour=0, minute=0, second=0, microsecond=0)

        # Check si c'est le jour précédent
        if (last_date - session_date).days == 1:
            streak += 1
            last_date = session_date
        elif session_date == last_date:
            # Même jour, ignorer
            continue
        else:
            # Gap détecté, arrêter
            break

    return streak


def log_session(card_ids, scores, responses=None, feedback_notes=None, dry_run=False):
    """
    Log une session complète et met à jour toutes les stats.

    Args:
        card_ids: Liste des IDs de cartes (ex: ['CORE-001', 'ACTION-006'])
        scores: Liste des scores (ex: ['✅', '⚠️', '❌'])
        responses: (Optionnel) Liste des réponses données
        feedback_notes: (Optionnel) Liste des feedbacks
        dry_run: Si True, affiche ce qui serait fait sans modifier les fichiers
    """
    if len(card_ids) != len(scores):
        raise ValueError(f"Nombre de cartes ({len(card_ids)}) != nombre de scores ({len(scores)})")

    # Valider les scores
    valid_scores = ['✅', '⚠️', '❌']
    for score in scores:
        if score not in valid_scores:
            raise ValueError(f"Score invalide: {score}. Utilise ✅, ⚠️ ou ❌")

    today = datetime.now()
    today_str = today.strftime('%d/%m/%Y')
    today_iso = today.strftime('%Y-%m-%d')

    # Parse card database
    cards_dict = parse_card_database()

    # Vérifier que toutes les cartes existent
    for card_id in card_ids:
        if card_id not in cards_dict:
            raise ValueError(f"Carte inconnue: {card_id}")

    print(f"📝 LOGGING SESSION - {today_str}")
    print("=" * 60)

    # Update chaque carte
    updated_cards = {}
    for i, (card_id, score) in enumerate(zip(card_ids, scores)):
        card = cards_dict[card_id]
        print(f"\n🎯 Carte {i+1}: {card_id} → {score}")

        # Update le fichier de carte individuel
        if not dry_run:
            updated_content = update_card_file(card['file'], score, today_str)
            card_path = CARDS_DIR / card['file']
            with open(card_path, 'w', encoding='utf-8') as f:
                f.write(updated_content)
            print(f"   ✅ Fichier {card['file']} mis à jour")
        else:
            print(f"   [DRY RUN] Mettrait à jour {card['file']}")

        # Re-parse le fichier pour obtenir les nouvelles stats
        if not dry_run:
            with open(CARDS_DIR / card['file'], 'r', encoding='utf-8') as f:
                new_content = f.read()

            # Extraire les nouvelles stats
            success_match = re.search(r'\*\*Success Rate\*\*: (.*)', new_content)
            failed_match = re.search(r'\*\*Times Failed\*\*: (\d+)', new_content)

            card['success_rate'] = success_match.group(1).strip() if success_match else card['success_rate']
            card['times_failed'] = int(failed_match.group(1)) if failed_match else card['times_failed']
            card['last_review'] = today_str

            updated_cards[card_id] = card
        else:
            print(f"   [DRY RUN] Stats seraient mises à jour")

    # Update card_database.md
    if not dry_run:
        db_content = update_card_database(updated_cards, today_str)
        with open(CARD_DB_PATH, 'w', encoding='utf-8') as f:
            f.write(db_content)
        print(f"\n✅ card_database.md mis à jour")
    else:
        print(f"\n[DRY RUN] card_database.md serait mis à jour")

    # Calculer le score total
    score_values = {'✅': 1, '⚠️': 0.5, '❌': 0}
    total_score = sum(score_values[s] for s in scores)
    max_score = len(scores)

    # Calculer le streak
    if not dry_run:
        with open(SESSIONS_LOG, 'r', encoding='utf-8') as f:
            sessions_content = f.read()
        streak = calculate_streak(sessions_content)
    else:
        streak = 1

    # Créer l'entrée de log pour daily_sessions.md
    log_entry = f"""
### {today_iso} [Time Unknown]

**Triggered by** : User (manual "daily check")
**Duration** : ~5 minutes

**Questions Asked** :
"""

    for i, (card_id, score) in enumerate(zip(card_ids, scores), 1):
        card = cards_dict[card_id]

        # Charger la question depuis le fichier
        with open(CARDS_DIR / card['file'], 'r', encoding='utf-8') as f:
            content = f.read()
        question_match = re.search(r'## Question\s*\n\s*\n(.*?)\n\s*\n---', content, re.DOTALL)
        question = question_match.group(1).strip() if question_match else "Question non trouvée"

        response = responses[i-1] if responses and i-1 < len(responses) else "[Non enregistrée]"
        feedback = feedback_notes[i-1] if feedback_notes and i-1 < len(feedback_notes) else "[Généré automatiquement]"

        log_entry += f"""{i}. [{card_id}] {question} → Score: {score}
   - Ta réponse : "{response}"
   - Feedback : {feedback}

"""

    log_entry += f"""**Total Score** : {total_score}/{max_score}
**Streak** : {streak} jour{'s' if streak > 1 else ''}
**Notes** : Session loggée automatiquement via log_session.py
**Action Items** :
- [À compléter manuellement si nécessaire]

---

"""

    # Append au fichier de sessions
    if not dry_run:
        with open(SESSIONS_LOG, 'a', encoding='utf-8') as f:
            f.write(log_entry)
        print(f"✅ Session loggée dans daily_sessions.md")
    else:
        print(f"[DRY RUN] Session serait loggée dans daily_sessions.md")

    print("=" * 60)
    print(f"✅ SESSION COMPLÈTE")
    print(f"Score: {total_score}/{max_score}")
    print(f"Streak: {streak} jour{'s' if streak > 1 else ''}")

    return {
        'score': f"{total_score}/{max_score}",
        'streak': streak,
        'cards_updated': len(card_ids)
    }


def interactive_mode():
    """Mode interactif pour logger une session."""
    print("=" * 60)
    print("📝 MODE INTERACTIF - LOG SESSION")
    print("=" * 60)

    # Demander les IDs de cartes
    cards_input = input("\n🎯 IDs des cartes (séparées par virgules, ex: CORE-001,ACTION-006): ")
    card_ids = [c.strip() for c in cards_input.split(',')]

    # Demander les scores
    scores_input = input(f"📊 Scores pour {len(card_ids)} cartes (✅/⚠️/❌, séparés par virgules): ")
    scores = [s.strip() for s in scores_input.split(',')]

    if len(card_ids) != len(scores):
        print(f"❌ ERREUR: {len(card_ids)} cartes mais {len(scores)} scores")
        return

    # Confirm
    print(f"\n📋 RÉCAPITULATIF:")
    for card_id, score in zip(card_ids, scores):
        print(f"   {card_id} → {score}")

    confirm = input("\n✅ Confirmer et logger ? (y/n): ")
    if confirm.lower() != 'y':
        print("❌ Annulé")
        return

    # Log
    log_session(card_ids, scores)


def main():
    parser = argparse.ArgumentParser(description='Log une session de daily check')
    parser.add_argument('--cards', type=str, help='IDs de cartes séparées par virgules')
    parser.add_argument('--scores', type=str, help='Scores (✅/⚠️/❌) séparés par virgules')
    parser.add_argument('--interactive', action='store_true', help='Mode interactif')
    parser.add_argument('--dry-run', action='store_true', help='Test sans modifier les fichiers')

    args = parser.parse_args()

    try:
        if args.interactive:
            interactive_mode()
        elif args.cards and args.scores:
            card_ids = [c.strip() for c in args.cards.split(',')]
            scores = [s.strip() for s in args.scores.split(',')]
            log_session(card_ids, scores, dry_run=args.dry_run)
        else:
            parser.print_help()
            print("\n💡 Astuce: Utilise --interactive pour un usage facile")

    except Exception as e:
        print(f"❌ ERREUR: {e}")
        import traceback
        traceback.print_exc()
        import sys
        sys.exit(1)


if __name__ == '__main__':
    import sys
    main()
