# maralonga/views.py - COMPLETO CON FIX ORDINAMENTO

from django.views.generic import TemplateView
from django.http import JsonResponse
from django.shortcuts import render, redirect
from django.conf import settings
from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import csrf_exempt
import paramiko
import json
import re
from datetime import datetime, timedelta
import os
from dateutil.relativedelta import relativedelta


# ==========================================
# CONFIGURAZIONE SEMPLICE
# ==========================================

JSON_PATHS = {
    'online': '/home/minecraft-reader/MCLOG_BACKAND_TEST/OUTPUT/current_online.json',
    'sessions': '/home/minecraft-reader/MCLOG_BACKAND_TEST/OUTPUT/sessions_index.json',
    'sessions_dir': '/home/minecraft-reader/MCLOG_BACKAND_TEST/OUTPUT/sessions/',
    'stats': '/home/minecraft-reader/MCLOG_BACKAND_TEST/OUTPUT/minecraft_stats.json',  # NUOVO
    'command_script': '/home/minecraft-reader/MCLOG_BACKAND_TEST/SCRIPTS/amp_command.sh',
}

# ==========================================
# GESTORE DATI MINIMALE
# ==========================================

class SimpleDataReader:
    def __init__(self):
        self.ssh = None
        self.sftp = None
    
    def connect(self):
        try:
            self.ssh = paramiko.SSHClient()
            self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            self.ssh.connect(
                hostname=settings.REMOTE_HOST,
                username=settings.REMOTE_USER,
                key_filename=settings.SSH_KEY_PATH,
                timeout=5
            )
            self.sftp = self.ssh.open_sftp()
            return True
        except:
            return False
    
    def disconnect(self):
        if self.sftp: self.sftp.close()
        if self.ssh: self.ssh.close()
    
    def read_json(self, path):
        try:
            with self.sftp.file(path, 'r') as f:
                content = f.read().decode('utf-8')
            return json.loads(content) if content.strip() else None
        except:
            return None

# ==========================================
# UTILITY SEMPLICI
# ==========================================

def format_timestamp(timestamp_str):
    """Formatta timestamp per display"""
    try:
        clean = timestamp_str.replace(' CEST', '')
        date_part, time_part = clean.split(' ')
        time_display = ':'.join(time_part.split(':')[:3])  # Solo HH:MM:SS
        return {
            'date': date_part,
            'time': time_display,
            'display': f"{date_part} {time_display}"
        }
    except:
        return {'date': 'N/A', 'time': 'N/A', 'display': timestamp_str}

def calc_duration(start_str, end_str=None):
    """Calcola durata"""
    if not end_str:
        return "In corso..."
    try:
        start = datetime.strptime(start_str.replace(' CEST', ''), '%d-%m-%Y %H:%M:%S:%f')
        end = datetime.strptime(end_str.replace(' CEST', ''), '%d-%m-%Y %H:%M:%S:%f')
        duration = end - start
        total_seconds = int(duration.total_seconds())
        hours = total_seconds // 3600
        minutes = (total_seconds % 3600) // 60
        seconds = total_seconds % 60
        return f"{hours}:{minutes:02d}:{seconds:02d}" if hours > 0 else f"{minutes:02d}:{seconds:02d}"
    except:
        return "N/A"

def get_session_coordinates_count(reader, session_id):
    """Legge il file individuale della sessione per contare le coordinate"""
    try:
        session_file = f"{JSON_PATHS['sessions_dir']}{session_id}.json"
        session_data = reader.read_json(session_file)
        if session_data and 'coordinates' in session_data:
            return len(session_data['coordinates'])
    except:
        pass
    return 0

def process_sessions_chronologically(sessions_index, reader=None):
    """Processa TUTTE le sessioni in ordine cronologico (più recenti prima per END TIME)"""
    processed_sessions = []
    
    if sessions_index and 'sessions' in sessions_index:
        all_sessions = sessions_index['sessions']
        
        # Ordina per END_TIME in modo decrescente (più recenti prima)
        try:
            def get_sort_key(session):
                end_time = session.get('end_time')
                if end_time:
                    return datetime.strptime(end_time.replace(' CEST', ''), '%d-%m-%Y %H:%M:%S:%f')
                else:
                    # Per sessioni in corso, usa una data futura per metterle in cima
                    return datetime.now() + timedelta(days=1)
            
            sorted_sessions = sorted(all_sessions, key=get_sort_key, reverse=True)
        except:
            # Se il parsing fallisce, usa l'ordine originale
            sorted_sessions = all_sessions
        
        # Prendi solo le prime 50 (che sono le più recenti per end_time)
        recent_sessions = sorted_sessions[:50]
        
        for session in recent_sessions:
            start_fmt = format_timestamp(session.get('start_time', ''))
            end_fmt = format_timestamp(session.get('end_time', '')) if session.get('end_time') else None
            
            # Prova prima dall'index, poi dal file individuale
            coordinates_count = len(session.get('coordinates', []))
            if coordinates_count == 0 and reader and session.get('session_id'):
                coordinates_count = get_session_coordinates_count(reader, session.get('session_id'))
            
            processed_sessions.append({
                'session_id': session.get('session_id'),
                'username': session.get('username'),
                'start_time_formatted': start_fmt,
                'end_time_formatted': end_fmt,
                'duration': calc_duration(session.get('start_time'), session.get('end_time')),
                'status': session.get('status', 'completed'),
                'coordinates_count': coordinates_count
            })
    
    return processed_sessions

# ==========================================
# VIEWS STANDARD
# ==========================================

class HomePageView(TemplateView):
    template_name = 'home.html'

class Season1PageView(TemplateView):
    template_name = 'season1.html'

class Season2PageView(TemplateView):
    template_name = 'season2.html'

def mc_login(request):
    if request.method == 'POST':
        password = request.POST.get('password')
        if password == settings.MC_LOG_PASSWORD:
            request.session['mc_authenticated'] = True
            return redirect('mc_access_log')
        else:
            return render(request, 'mclog-login.html', {'error': 'Password errata'})
    return render(request, 'mclog-login.html')

def display_mc_access_log(request):
    """Pagina principale MC log"""
    if not request.session.get('mc_authenticated', False):
        return redirect('mc_login')
    
    reader = SimpleDataReader()
    if not reader.connect():
        return render(request, 'mc-access-log.html', {
            'error': 'Connessione al server fallita'
        })
    
    try:
        # Leggi dati online
        online_data = reader.read_json(JSON_PATHS['online'])
        
        # Leggi sessioni e processale cronologicamente
        sessions_index = reader.read_json(JSON_PATHS['sessions'])
        processed_sessions = process_sessions_chronologically(sessions_index, reader)
        
        # Leggi statistiche giocatori
        player_stats = reader.read_json(JSON_PATHS['stats'])
        
        # Formatta le date nelle statistiche per il template
        if player_stats and 'players' in player_stats:
            for username, stats in player_stats['players'].items():
                if stats.get('last_seen'):
                    try:
                        stats['last_seen'] = datetime.fromisoformat(stats['last_seen'])
                    except:
                        stats['last_seen'] = None
        
        context = {
            'online_data': online_data,
            'sessions': processed_sessions,
            'player_stats': player_stats,  # NUOVO
            'stats_last_update': player_stats.get('generated_at', '').split('T')[0] if player_stats else 'N/A',  # NUOVO
            'last_update': datetime.now().strftime('%d-%m-%Y %H:%M:%S')
        }
        
        return render(request, 'mc-access-log.html', context)
        
    except Exception as e:
        return render(request, 'mc-access-log.html', {
            'error': f'Errore: {str(e)}'
        })
    finally:
        reader.disconnect()


# ==========================================
# API ENDPOINTS MINIMALI
# ==========================================

def get_online_players_api(request):
    """API giocatori online"""
    if not request.session.get('mc_authenticated', False):
        return JsonResponse({'error': 'Not authenticated'}, status=401)
    
    reader = SimpleDataReader()
    if not reader.connect():
        return JsonResponse({'success': False, 'error': 'Connection failed'})
    
    try:
        online_data = reader.read_json(JSON_PATHS['online'])
        return JsonResponse({
            'success': True,
            'online_data': online_data or {'players_online': 0, 'players': []},
            'timestamp': datetime.now().isoformat()
        })
    except Exception as e:
        return JsonResponse({'success': False, 'error': str(e)})
    finally:
        reader.disconnect()

def get_sessions_api(request):
    """API sessioni - ORDINAMENTO CRONOLOGICO CORRETTO"""
    if not request.session.get('mc_authenticated', False):
        return JsonResponse({'error': 'Not authenticated'}, status=401)
    
    reader = SimpleDataReader()
    if not reader.connect():
        return JsonResponse({'success': False, 'error': 'Connection failed'})
    
    try:
        sessions_index = reader.read_json(JSON_PATHS['sessions'])
        processed_sessions = process_sessions_chronologically(sessions_index, reader)
        
        return JsonResponse({
            'success': True,
            'sessions': processed_sessions,
            'timestamp': datetime.now().isoformat()
        })
    except Exception as e:
        return JsonResponse({'success': False, 'error': str(e)})
    finally:
        reader.disconnect()

def get_session_details_api(request, session_id):
    """API dettagli sessione"""
    if not request.session.get('mc_authenticated', False):
        return JsonResponse({'error': 'Not authenticated'}, status=401)
    
    reader = SimpleDataReader()
    if not reader.connect():
        return JsonResponse({'success': False, 'error': 'Connection failed'})
    
    try:
        session_file = f"{JSON_PATHS['sessions_dir']}{session_id}.json"
        session_data = reader.read_json(session_file)
        
        if not session_data:
            return JsonResponse({'success': False, 'error': f'Session {session_id} not found'})
        
        # Formatta coordinate
        formatted_coords = []
        for coord in session_data.get('coordinates', []):
            coord_fmt = format_timestamp(coord.get('timestamp', ''))
            formatted_coords.append({
                'timestamp': coord_fmt['display'],
                'x': coord.get('x'),
                'y': coord.get('y'),
                'z': coord.get('z')
            })
        
        start_fmt = format_timestamp(session_data.get('start_time', ''))
        end_fmt = format_timestamp(session_data.get('end_time', '')) if session_data.get('end_time') else None
        
        return JsonResponse({
            'success': True,
            'session_id': session_data.get('session_id'),
            'username': session_data.get('username'),
            'xuid': session_data.get('xuid'),
            'start_time_formatted': start_fmt,
            'end_time_formatted': end_fmt,
            'duration': calc_duration(session_data.get('start_time'), session_data.get('end_time')),
            'status': session_data.get('status'),
            'coordinates': formatted_coords,
            'coordinates_count': len(formatted_coords)
        })
    except Exception as e:
        return JsonResponse({'success': False, 'error': str(e)})
    finally:
        reader.disconnect()

@csrf_exempt
@require_http_methods(["POST"])
def send_command_api(request):
    """API comandi MC"""
    IMMUNE_PLAYERS = ['Lese88']
    
    if not request.session.get('mc_authenticated', False):
        return JsonResponse({'success': False, 'error': 'Not authenticated'}, status=401)
    
    try:
        data = json.loads(request.body)
        command = data.get('command', '').strip()
        
        if not command:
            return JsonResponse({'success': False, 'error': 'Comando vuoto'})
        
        # Valida comando
        allowed = [
            r'^tp\s+(\w+)\s+4950\s+-63\s+-4950$',  # Ban
            r'^tp\s+(\w+)\s+-620\s+122\s+442$',    # Unban
            r'^say\s+.*$',                         # Say
        ]
        
        if not any(re.match(pattern, command, re.IGNORECASE) for pattern in allowed):
            return JsonResponse({'success': False, 'error': 'Comando non permesso'})
        
        # Valida nome giocatore per tp
        if command.startswith('tp '):
            match = re.match(r'^tp\s+(\w+)\s+.+$', command, re.IGNORECASE)
            if match:
                player_name = match.group(1)
                if not re.match(r'^[a-zA-Z0-9_]{3,16}$', player_name):
                    return JsonResponse({'success': False, 'error': f'Nome non valido: {player_name}'})
                if player_name.lower() in [p.lower() for p in IMMUNE_PLAYERS]:
                    return JsonResponse({'success': False, 'error': f'Giocatore protetto: {player_name}'})
        
        # Esegui comando
        reader = SimpleDataReader()
        if not reader.connect():
            return JsonResponse({'success': False, 'error': 'Connection failed'})
        
        try:
            stdin, stdout, stderr = reader.ssh.exec_command(f'{JSON_PATHS["command_script"]} "{command}"')
            output = stdout.read().decode('utf-8')
            error = stderr.read().decode('utf-8')
            exit_code = stdout.channel.recv_exit_status()
            
            if exit_code == 0:
                return JsonResponse({
                    'success': True,
                    'message': f'Comando eseguito: {command}',
                    'output': output.strip() if output else None
                })
            else:
                return JsonResponse({
                    'success': False,
                    'error': f'Errore: {error.strip() if error else f"Exit code {exit_code}"}'
                })
        finally:
            reader.disconnect()
        
    except json.JSONDecodeError:
        return JsonResponse({'success': False, 'error': 'JSON non valido'})
    except Exception as e:
        return JsonResponse({'success': False, 'error': str(e)})

def server_status_api(request):
    """API status server"""
    try:
        from mcstatus import BedrockServer
        server = BedrockServer.lookup("145.223.85.106:19132")
        status = server.status()
        
        latency_info = {"rating": "Buona", "color": "#f39c12", "icon": "✅"}
        if status.latency < 50:
            latency_info = {"rating": "Eccellente", "color": "#27ae60", "icon": "⚡"}
        elif status.latency > 150:
            latency_info = {"rating": "Lenta", "color": "#e74c3c", "icon": "❌"}
        
        return JsonResponse({
            'online': True,
            'players_online': status.players.online,
            'players_max': status.players.max,
            'version': status.version.name,
            'latency': round(status.latency, 1),
            'latency_rating': latency_info["rating"],
            'latency_color': latency_info["color"],
            'latency_icon': latency_info["icon"],
        })
    except Exception as e:
        return JsonResponse({
            'online': False,
            'error': str(e),
            'players_online': 0,
            'players_max': 0,
        })





### SISTEMA DI PAGINAZIONE ###

# ==========================================
# PAGINAZIONE ARCHIVI
# ==========================================

def get_archive_path_for_page(page):
    """Calcola il path dell'archivio basato sul numero di pagina"""
    BASE_DIR = "/home/minecraft-reader/MCLOG_BACKAND_TEST"
    
    if page == 0:
        # Mese corrente
        return {
            'online': f'{BASE_DIR}/OUTPUT/current_online.json',
            'sessions': f'{BASE_DIR}/OUTPUT/sessions_index.json',
            'sessions_dir': f'{BASE_DIR}/OUTPUT/sessions/',
            'stats': f'{BASE_DIR}/OUTPUT/minecraft_stats.json',
        }
    
    # Calcola il mese dell'archivio
    target_date = datetime.now() - relativedelta(months=page)
    archive_month = target_date.strftime('%Y-%m')
    archive_base = f'{BASE_DIR}/ARCHIVE/{archive_month}/OUTPUT'
    
    # DEBUG
    print(f"🔧 DEBUG get_archive_path_for_page({page}):")
    print(f"🔧 DEBUG target_date: {target_date}")
    print(f"🔧 DEBUG archive_month: {archive_month}")
    print(f"🔧 DEBUG archive_base: {archive_base}")
    
    return {
        'online': f'{archive_base}/current_online.json',
        'sessions': f'{archive_base}/sessions_index.json', 
        'sessions_dir': f'{archive_base}/sessions/',
        'stats': f'{archive_base}/minecraft_stats.json',
    }

def get_available_archive_pages():
    """Trova quante pagine di archivio sono disponibili"""
    BASE_DIR = "/home/minecraft-reader/MCLOG_BACKAND_TEST"
    archive_dir = f"{BASE_DIR}/ARCHIVE"
    
    available_pages = [0]
    
    reader = SimpleDataReader()
    if not reader.connect():
        return available_pages
    
    try:
        items = reader.sftp.listdir(archive_dir)
        print(f"🔧 DEBUG: Archive contents: {items}")
        
        for item in items:
            item_path = f"{archive_dir}/{item}"
            stat = reader.sftp.stat(item_path)
            if stat.st_mode & 0o040000:  # è una directory
                print(f"🔧 DEBUG: Found directory: {item}")
                
                # AGGIUNGI QUESTA PARTE - la logica di calcolo mesi
                try:
                    datetime.strptime(item, '%Y-%m')
                    print(f"🔧 DEBUG: Valid date format: {item}")
                    
                    # Calcola quanti mesi fa
                    archive_date = datetime.strptime(item, '%Y-%m')
                    current_date = datetime.now().replace(day=1, hour=0, minute=0, second=0, microsecond=0)
                    months_diff = (current_date.year - archive_date.year) * 12 + (current_date.month - archive_date.month)
                    
                    print(f"🔧 DEBUG: Months diff: {months_diff}")
                    
                    if months_diff > 0 and months_diff <= 6:
                        available_pages.append(months_diff)
                        print(f"🔧 DEBUG: Added page {months_diff}")
                    
                except ValueError as e:
                    print(f"🔧 DEBUG: Invalid date: {e}")
        
    except Exception as e:
        print(f"🔧 DEBUG: SFTP error: {e}")
    finally:
        reader.disconnect()
    
    print(f"🔧 DEBUG: Final available pages: {sorted(available_pages)}")
    return sorted(available_pages)


def get_month_info_for_page(page):
    """Restituisce info leggibile del mese per una pagina"""
    if page == 0:
        return {
            'page': 0,
            'display': 'Corrente',
            'month': datetime.now().strftime('%B %Y'),
            'is_current': True
        }
    
    target_date = datetime.now() - relativedelta(months=page)
    return {
        'page': page,
        'display': f'{page} mesi fa',
        'month': target_date.strftime('%B %Y'),
        'is_current': False
    }

# ==========================================
# API ENDPOINT
# ==========================================

def get_archived_data_api(request, page=0):
    """API per ottenere dati di una pagina specifica"""
    if not request.session.get('mc_authenticated', False):
        return JsonResponse({'error': 'Not authenticated'}, status=401)
    
    try:
        page = int(page)
        if page < 0 or page > 6:
            return JsonResponse({'success': False, 'error': 'Page out of range (0-6)'})
        
        # Verifica che la pagina sia disponibile
        available_pages = get_available_archive_pages()
        if page not in available_pages:
            return JsonResponse({'success': False, 'error': f'Page {page} not available'})
        
        # Ottieni path per questa pagina
        paths = get_archive_path_for_page(page)
        print(f"🔧 DEBUG: Paths for page {page}:")
        for key, path in paths.items():
            print(f"🔧 DEBUG:   {key}: {path}")
        
        reader = SimpleDataReader()
        if not reader.connect():
            return JsonResponse({'success': False, 'error': 'Connection failed'})
        
        try:
            # Leggi dati online
            print(f"🔧 DEBUG: Reading online data from: {paths['online']}")
            online_data = reader.read_json(paths['online'])
            print(f"🔧 DEBUG: Online data loaded: {bool(online_data)}")
            if online_data:
                print(f"🔧 DEBUG: Online count: {online_data.get('online_count', 'N/A')}")
            
            # Leggi sessioni
            print(f"🔧 DEBUG: Reading sessions from: {paths['sessions']}")
            sessions_index = reader.read_json(paths['sessions'])
            print(f"🔧 DEBUG: Sessions index loaded: {bool(sessions_index)}")
            if sessions_index:
                sessions_list = sessions_index.get('sessions', [])
                print(f"🔧 DEBUG: Sessions in index: {len(sessions_list)}")
                if sessions_list:
                    print(f"🔧 DEBUG: First session example: {sessions_list[0].get('session_id', 'NO_ID')}")
            else:
                print(f"🔧 DEBUG: Sessions index is None/empty")
            
            # Processa sessioni con debug
            print(f"🔧 DEBUG: Processing sessions with sessions_dir: {paths['sessions_dir']}")
            processed_sessions = process_sessions_chronologically(sessions_index, reader, paths['sessions_dir'])
            print(f"🔧 DEBUG: Processed sessions count: {len(processed_sessions)}")
            if processed_sessions:
                print(f"🔧 DEBUG: First processed session: {processed_sessions[0].get('session_id', 'NO_ID')}")
            
            # Leggi statistiche
            print(f"🔧 DEBUG: Reading stats from: {paths['stats']}")
            player_stats = reader.read_json(paths['stats'])
            print(f"🔧 DEBUG: Player stats loaded: {bool(player_stats)}")
            if player_stats:
                players_count = len(player_stats.get('players', {}))
                print(f"🔧 DEBUG: Players in stats: {players_count}")
            
            # Formatta date nelle statistiche
            if player_stats and 'players' in player_stats:
                for username, stats in player_stats['players'].items():
                    if stats.get('last_seen'):
                        try:
                            stats['last_seen'] = datetime.fromisoformat(stats['last_seen'])
                        except:
                            stats['last_seen'] = None
            
            # Info del mese
            month_info = get_month_info_for_page(page)
            print(f"🔧 DEBUG: Month info: {month_info}")
            
            result = {
                'success': True,
                'page': page,
                'month_info': month_info,
                'online_data': online_data or {'online_count': 0, 'players': []},
                'sessions': processed_sessions,
                'player_stats': player_stats,
                'stats_last_update': player_stats.get('generated_at', '').split('T')[0] if player_stats else 'N/A',
                'timestamp': datetime.now().isoformat()
            }
            
            print(f"🔧 DEBUG: Final result sessions count: {len(result['sessions'])}")
            print(f"🔧 DEBUG: Final result stats available: {bool(result['player_stats'])}")
            
            return JsonResponse(result)
            
        finally:
            reader.disconnect()
            
    except Exception as e:
        print(f"🔧 DEBUG: Exception in get_archived_data_api: {str(e)}")
        import traceback
        traceback.print_exc()
        return JsonResponse({'success': False, 'error': str(e)})
    
    
def get_pagination_info_api(request):
    """API per ottenere info paginazione (quali pagine sono disponibili)"""
    if not request.session.get('mc_authenticated', False):
        return JsonResponse({'error': 'Not authenticated'}, status=401)
    
    try:
        available_pages = get_available_archive_pages()
        pages_info = []
        
        for page in range(7):  # 0-6
            if page in available_pages:
                pages_info.append({
                    'page': page,
                    'available': True,
                    'info': get_month_info_for_page(page)
                })
            else:
                pages_info.append({
                    'page': page,
                    'available': False,
                    'info': None
                })
        
        return JsonResponse({
            'success': True,
            'available_pages': available_pages,
            'pages_info': pages_info
        })
        
    except Exception as e:
        return JsonResponse({'success': False, 'error': str(e)})

# ==========================================
# AGGIORNA FUNZIONE ESISTENTE
# ==========================================

def process_sessions_chronologically(sessions_index, reader=None, sessions_dir_override=None):
    """
    Versione aggiornata che supporta path personalizzato per sessioni
    """
    processed_sessions = []
    
    if sessions_index and 'sessions' in sessions_index:
        all_sessions = sessions_index['sessions']
        
        # Ordina per END_TIME in modo decrescente
        try:
            def get_sort_key(session):
                end_time = session.get('end_time')
                if end_time:
                    return datetime.strptime(end_time.replace(' CEST', ''), '%d-%m-%Y %H:%M:%S:%f')
                else:
                    return datetime.now() + timedelta(days=1)
            
            sorted_sessions = sorted(all_sessions, key=get_sort_key, reverse=True)
        except:
            sorted_sessions = all_sessions
        
        recent_sessions = sorted_sessions[:50]
        
        for session in recent_sessions:
            start_fmt = format_timestamp(session.get('start_time', ''))
            end_fmt = format_timestamp(session.get('end_time', '')) if session.get('end_time') else None
            
            # Usa path personalizzato se fornito
            coordinates_count = len(session.get('coordinates', []))
            if coordinates_count == 0 and reader and session.get('session_id'):
                if sessions_dir_override:
                    session_file = f"{sessions_dir_override}{session.get('session_id')}.json"
                    session_data = reader.read_json(session_file)
                    if session_data and 'coordinates' in session_data:
                        coordinates_count = len(session_data['coordinates'])
                else:
                    coordinates_count = get_session_coordinates_count(reader, session.get('session_id'))
            
            processed_sessions.append({
                'session_id': session.get('session_id'),
                'username': session.get('username'),
                'start_time_formatted': start_fmt,
                'end_time_formatted': end_fmt,
                'duration': calc_duration(session.get('start_time'), session.get('end_time')),
                'status': session.get('status', 'completed'),
                'coordinates_count': coordinates_count
            })
    
    return processed_sessions

### END SISTEMA DI PAGINAZIONE ###