=== TETRAQ PROJECT BACKUP ===

=== PROJECT STRUCTURE (LIB & ASSETS) ===
assets/.DS_Store
assets/audio/sfx/cyber_box.wav
assets/audio/sfx/cyber_line.wav
assets/audio/sfx/doodle_box.wav
assets/audio/sfx/doodle_line.wav
assets/audio/sfx/minimal_box.wav
assets/audio/sfx/minimal_line.wav
assets/icon/icona_master.png
assets/images/.DS_Store
assets/images/doodle_bg.jpg
assets/images/doodle_bg1.jpg
assets/images/icona_big.jpeg
assets/images/wood_bg.jpg
lib/.DS_Store
lib/core/app_colors.dart
lib/core/constants.dart
lib/core/theme_manager.dart
lib/firebase_options.dart
lib/l10n/app_en.arb
lib/l10n/app_it.arb
lib/logic/ai_engine.dart
lib/logic/game_controller.dart
lib/main.dart
lib/models/game_board.dart
lib/models/player_info.dart
lib/services/audio_service.dart
lib/services/firebase_service.dart
lib/services/multiplayer_service.dart
lib/services/storage_service.dart
lib/ui/game/board_painter.dart
lib/ui/game/game_screen.dart
lib/ui/game/score_board.dart
lib/ui/home/history_screen.dart
lib/ui/home/home_screen.dart
lib/ui/multiplayer/lobby_screen.dart
lib/ui/settings/settings_screen.dart
lib/widgets/custom_button.dart
lib/widgets/custom_settings_button.dart
lib/widgets/game_over_dialog.dart

=== pubspec.yaml ===
name: tetraq
description: A new Flutter project.
publish_to: 'none'
version: 1.0.0+4
environment:
  sdk: ^3.10.7

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.8

  # I nostri "Superpoteri"
  provider: ^6.1.2             # Per gestire lo stato (Temi, Punteggi)
  shared_preferences: ^2.5.4   # Per salvare opzioni e record sul telefono
  audioplayers: ^5.2.1         # Per la musica e gli effetti sonori
  intl: ^0.20.2                # Necessario per le traduzioni
  flutter_localizations:       # Il sistema multilingua ufficiale
    sdk: flutter
  firebase_core: ^4.4.0
  cloud_firestore: ^6.1.2
  share_plus: ^12.0.1
  app_links: ^7.0.0

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^6.0.0
  flutter_launcher_icons: ^0.13.1

flutter:
  uses-material-design: true

  # Abilita la generazione automatica delle traduzioni
  generate: true

  # Dichiariamo le cartelle dove metteremo immagini e suoni
  assets:
    - assets/images/
    - assets/audio/bgm/
    - assets/audio/sfx/
    - assets/images/

flutter_icons:
  android: "ic_launcher"
  ios: true
  macos:
    generate: true
  image_path: "assets/icon/icona_master.png"
  min_sdk_android: 21 # Serve per compatibilità con Android recenti
=== MAC OS CONFIG: Info.plist ===
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>LSApplicationCategoryType</key>
    <string>public.app-category.puzzle-games</string>
    <key>CFBundleDevelopmentRegion</key>
    <string>$(DEVELOPMENT_LANGUAGE)</string>
    <key>CFBundleExecutable</key>
    <string>$(EXECUTABLE_NAME)</string>
    <key>CFBundleIconFile</key>
    <string></string>
    <key>CFBundleIdentifier</key>
    <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundleName</key>
    <string>$(PRODUCT_NAME)</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleShortVersionString</key>
    <string>$(FLUTTER_BUILD_NAME)</string>
    <key>CFBundleVersion</key>
    <string>$(FLUTTER_BUILD_NUMBER)</string>
    <key>LSMinimumSystemVersion</key>
    <string>$(MACOSX_DEPLOYMENT_TARGET)</string>
    <key>NSHumanReadableCopyright</key>
    <string>$(PRODUCT_COPYRIGHT)</string>
    <key>NSMainNibFile</key>
    <string>MainMenu</string>
    <key>NSPrincipalClass</key>
    <string>NSApplication</string>
</dict>
</plist>
=== MAC OS CONFIG: DebugProfile.entitlements ===
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.app-sandbox</key>
    <true/>
    <key>com.apple.security.cs.allow-jit</key>
    <true/>
    <key>com.apple.security.network.client</key>
    <true/>
    <key>com.apple.security.network.server</key>
    <true/>
</dict>
</plist>
=== IOS CONFIG: Info.plist ===
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>$(DEVELOPMENT_LANGUAGE)</string>
	<key>CFBundleDisplayName</key>
	<string>Tetraq</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>tetraq</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>$(FLUTTER_BUILD_NAME)</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>$(FLUTTER_BUILD_NUMBER)</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>UILaunchStoryboardName</key>
	<string>LaunchScreen</string>
	<key>UIMainStoryboardFile</key>
	<string>Main</string>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UISupportedInterfaceOrientations~ipad</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationPortraitUpsideDown</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>CADisableMinimumFrameDurationOnPhone</key>
	<true/>
	<key>UIApplicationSupportsIndirectInputEvents</key>
	<true/>
</dict>
</plist>

=== ANDROID CONFIG: AndroidManifest.xml ===
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:label="tetraq"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:taskAffinity=""
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <meta-data
                android:name="io.flutter.embedding.android.NormalTheme"
                android:resource="@style/NormalTheme"
                />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="tetraq" android:host="join" />
            </intent-filter>
        </activity>
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
    <queries>
        <intent>
            <action android:name="android.intent.action.PROCESS_TEXT"/>
            <data android:mimeType="text/plain"/>
        </intent>
    </queries>
</manifest>
=== ANDROID CONFIG: build.gradle.kts (app) ===
plugins {
    id("com.android.application")
    // START: FlutterFire Configuration
    id("com.google.gms.google-services")
    // END: FlutterFire Configuration
    id("kotlin-android")
    // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
    id("dev.flutter.flutter-gradle-plugin")
}

android {
    namespace = "com.sanza.tetraq"
    compileSdk = flutter.compileSdkVersion
    ndkVersion = flutter.ndkVersion

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
        targetCompatibility = JavaVersion.VERSION_17
    }

    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_17.toString()
    }

    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId = "com.sanza.tetraq"
        // You can update the following values to match your application needs.
        // For more information, see: https://flutter.dev/to/review-gradle-config.
        minSdk = flutter.minSdkVersion
        targetSdk = flutter.targetSdkVersion
        versionCode = flutter.versionCode
        versionName = flutter.versionName
    }

    buildTypes {
        release {
            // TODO: Add your own signing config for the release build.
            // Signing with the debug keys for now, so `flutter run --release` works.
            signingConfig = signingConfigs.getByName("debug")
        }
    }
}

flutter {
    source = "../.."
}

=== SOURCE CODE (lib/) ===

// ===========================================================================
// FILE: lib/core/app_colors.dart
// ===========================================================================

import 'package:flutter/material.dart';

enum AppThemeType { minimal, doodle, cyberpunk, wood }

class ThemeColors {
  final Color background;
  final Color gridLine;
  final Color playerRed;
  final Color playerBlue;
  final Color text;

  const ThemeColors({
    required this.background,
    required this.gridLine,
    required this.playerRed,
    required this.playerBlue,
    required this.text,
  });
}

class AppColors {
  static const ThemeColors minimal = ThemeColors(
    background: Color(0xFFF5F7FA), gridLine: Color(0xFFCFD8DC),
    playerRed: Color(0xFFE53935), playerBlue: Color(0xFF1E88E5), text: Color(0xFF263238),
  );

  static const ThemeColors doodle = ThemeColors(
    background: Color(0xFFFFF9E6), gridLine: Color(0xFFB0BEC5),
    playerRed: Color(0xFFD32F2F), playerBlue: Color(0xFF1565C0), text: Color(0xFF37474F),
  );

  // --- TEMA CYBERPUNK AGGIORNATO ---
  static const ThemeColors cyberpunk = ThemeColors(
    background: Color(0xFF0A001A), // Sfondo notte profonda
    gridLine: Color(0xFF6200EA),   // Viola scuro elettrico (non fa confusione con le mosse)
    playerRed: Color(0xFFFF007F),  // Rosa Neon (invariato)
    playerBlue: Color(0xFF69F0AE), // Verde Fluo brillante! (Green Accent)
    text: Color(0xFFFFFFFF),
  );

  // --- TEMA LEGNO POTENZIATO ---
  static const ThemeColors wood = ThemeColors(
    background: Color(0xFF905D3B), // Marrone caldo e ricco (vero legno)
    gridLine: Color(0xFF4A301E),   // Marrone scurissimo per i solchi
    playerRed: Color(0xFFE53935),  // Rosso acceso per i fiammiferi
    playerBlue: Color(0xFF29B6F6), // Azzurro acceso per i fiammiferi
    text: Color(0xFFFBE9E7),       // Panna chiaro per contrastare lo scuro
  );

  static ThemeColors getTheme(AppThemeType type) {
    switch (type) {
      case AppThemeType.minimal: return minimal;
      case AppThemeType.doodle: return doodle;
      case AppThemeType.cyberpunk: return cyberpunk;
      case AppThemeType.wood: return wood;
    }
  }
}
// ===========================================================================
// FILE: lib/core/constants.dart
// ===========================================================================

class Constants {
  // Chiavi per salvare i dati sul telefono
  static const String prefThemeKey = 'selected_theme';
  static const String prefLanguageKey = 'selected_language';
  static const String prefBoardSizeKey = 'board_size';

  // Impostazioni della scacchiera a rombo - RAGGI INCREMENTATI
  static const int minBoardRadius = 2; // Ex Normale, ora è Piccola
  static const int maxBoardRadius = 5; // Formato MAX, enorme
  static const int defaultBoardRadius = 3; // Ora il default è più grande
}
// ===========================================================================
// FILE: lib/core/theme_manager.dart
// ===========================================================================

import 'package:flutter/material.dart';
import 'app_colors.dart';
import '../services/storage_service.dart';

class ThemeManager extends ChangeNotifier {
  late AppThemeType _currentThemeType;

  ThemeManager() {
    // Quando l'app parte, legge il tema dalla memoria!
    _currentThemeType = AppThemeType.values[StorageService.instance.savedThemeIndex];
  }

  AppThemeType get currentThemeType => _currentThemeType;
  ThemeColors get currentColors => AppColors.getTheme(_currentThemeType);

  void setTheme(AppThemeType type) {
    _currentThemeType = type;
    StorageService.instance.saveTheme(type); // Salva la scelta nel "disco fisso"
    notifyListeners();
  }
}
// ===========================================================================
// FILE: lib/firebase_options.dart
// ===========================================================================

// File generated by FlutterFire CLI.
// ignore_for_file: type=lint
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
    show defaultTargetPlatform, kIsWeb, TargetPlatform;

/// Default [FirebaseOptions] for use with your Firebase apps.
///
/// Example:
/// ```dart
/// import 'firebase_options.dart';
/// // ...
/// await Firebase.initializeApp(
///   options: DefaultFirebaseOptions.currentPlatform,
/// );
/// ```
class DefaultFirebaseOptions {
  static FirebaseOptions get currentPlatform {
    if (kIsWeb) {
      throw UnsupportedError(
        'DefaultFirebaseOptions have not been configured for web - '
        'you can reconfigure this by running the FlutterFire CLI again.',
      );
    }
    switch (defaultTargetPlatform) {
      case TargetPlatform.android:
        return android;
      case TargetPlatform.iOS:
        return ios;
      case TargetPlatform.macOS:
        return macos;
      case TargetPlatform.windows:
        throw UnsupportedError(
          'DefaultFirebaseOptions have not been configured for windows - '
          'you can reconfigure this by running the FlutterFire CLI again.',
        );
      case TargetPlatform.linux:
        throw UnsupportedError(
          'DefaultFirebaseOptions have not been configured for linux - '
          'you can reconfigure this by running the FlutterFire CLI again.',
        );
      default:
        throw UnsupportedError(
          'DefaultFirebaseOptions are not supported for this platform.',
        );
    }
  }

  static const FirebaseOptions android = FirebaseOptions(
    apiKey: 'AIzaSyBsXO595xVITDPrRnXrW8HPQLOe7Rz4Gg4',
    appId: '1:705460445314:android:4d35fef29cfd63727b949b',
    messagingSenderId: '705460445314',
    projectId: 'tetraq-32a4a',
    storageBucket: 'tetraq-32a4a.firebasestorage.app',
  );

  static const FirebaseOptions ios = FirebaseOptions(
    apiKey: 'AIzaSyB77j18Jgeb9gBAEwp-uyOQvr4m-RJ_rAE',
    appId: '1:705460445314:ios:da11cbca5d1f6bc27b949b',
    messagingSenderId: '705460445314',
    projectId: 'tetraq-32a4a',
    storageBucket: 'tetraq-32a4a.firebasestorage.app',
    iosBundleId: 'com.sanza.tetraq',
  );

  static const FirebaseOptions macos = FirebaseOptions(
    apiKey: 'AIzaSyB77j18Jgeb9gBAEwp-uyOQvr4m-RJ_rAE',
    appId: '1:705460445314:ios:da11cbca5d1f6bc27b949b',
    messagingSenderId: '705460445314',
    projectId: 'tetraq-32a4a',
    storageBucket: 'tetraq-32a4a.firebasestorage.app',
    iosBundleId: 'com.sanza.tetraq',
  );
}

// ===========================================================================
// FILE: lib/logic/ai_engine.dart
// ===========================================================================

import 'dart:math';
import '../models/game_board.dart';

class AIEngine {
  static Line getBestMove(GameBoard board, int level) {
    // IL FIX FONDAMENTALE È QUI:
    // Filtriamo le linee in modo che la CPU veda SOLO quelle libere E giocabili!
    List<Line> availableLines = board.lines.where((l) => l.owner == Player.none && l.isPlayable).toList();
    final random = Random();

    // Se per qualche assurdo motivo non ci sono mosse, restituisce la prima linea a caso
    // (Non dovrebbe mai succedere, ma ci protegge dai crash)
    if (availableLines.isEmpty) return board.lines.first;

    // --- FORMULA DI DIFFICOLTÀ ---
    double smartChance = 0.50 + ((level - 1) * 0.10);
    if (smartChance > 1.0) smartChance = 1.0;

    bool beSmart = random.nextDouble() < smartChance;

    // --- REGOLA 1: Chiudere i quadrati ---
    List<Line> closingMoves = [];
    for (var line in availableLines) {
      if (_willCloseBox(board, line)) {
        closingMoves.add(line);
      }
    }

    if (closingMoves.isNotEmpty) {
      if (beSmart || random.nextDouble() < 0.70) {
        return closingMoves[random.nextInt(closingMoves.length)];
      }
    }

    // --- REGOLA 2: Mosse Sicure ---
    List<Line> safeMoves = [];
    for (var line in availableLines) {
      if (_isSafeMove(board, line)) {
        safeMoves.add(line);
      }
    }

    if (safeMoves.isNotEmpty) {
      if (beSmart) {
        return safeMoves[random.nextInt(safeMoves.length)];
      } else {
        if (random.nextDouble() < 0.5) {
          return safeMoves[random.nextInt(safeMoves.length)];
        }
      }
    }

    // --- REGOLA 3: Mossa a caso ---
    return availableLines[random.nextInt(availableLines.length)];
  }

  static bool _willCloseBox(GameBoard board, Line line) {
    for (var box in board.boxes) {
      // Ignora i box invisibili!
      if (box.type == BoxType.invisible) continue;

      if (box.top == line || box.bottom == line || box.left == line || box.right == line) {
        int linesCount = 0;
        if (box.top.owner != Player.none || box.top == line) linesCount++;
        if (box.bottom.owner != Player.none || box.bottom == line) linesCount++;
        if (box.left.owner != Player.none || box.left == line) linesCount++;
        if (box.right.owner != Player.none || box.right == line) linesCount++;

        if (linesCount == 4) return true;
      }
    }
    return false;
  }

  static bool _isSafeMove(GameBoard board, Line line) {
    for (var box in board.boxes) {
      // Ignora i box invisibili!
      if (box.type == BoxType.invisible) continue;

      if (box.top == line || box.bottom == line || box.left == line || box.right == line) {
        int currentLinesCount = 0;
        if (box.top.owner != Player.none) currentLinesCount++;
        if (box.bottom.owner != Player.none) currentLinesCount++;
        if (box.left.owner != Player.none) currentLinesCount++;
        if (box.right.owner != Player.none) currentLinesCount++;

        if (currentLinesCount == 2) return false;
      }
    }
    return true;
  }
}
// ===========================================================================
// FILE: lib/logic/game_controller.dart
// ===========================================================================

import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../models/game_board.dart';
import 'ai_engine.dart';
import '../services/audio_service.dart';
import '../services/storage_service.dart';
import '../core/app_colors.dart';

class GameController extends ChangeNotifier {
  late GameBoard board;
  bool isVsCPU = false;
  bool isCPUThinking = false;

  bool isOnline = false;
  String? roomCode;
  bool isHost = false;
  StreamSubscription<DocumentSnapshot>? _onlineSubscription;

  bool opponentLeft = false;
  bool _hasSavedResult = false;

  Timer? _blitzTimer;
  int timeLeft = 15;
  final int maxTime = 15;

  String effectText = '';
  Color effectColor = Colors.transparent;
  Timer? _effectTimer;

  Player get myPlayer => isHost ? Player.red : Player.blue;
  bool get isGameOver => board.isGameOver;

  int cpuLevel = 1;
  int currentMatchLevel = 1;
  int? currentSeed;
  AppThemeType _activeTheme = AppThemeType.cyberpunk;

  String onlineHostName = "ROSSO";
  String onlineGuestName = "BLU";
  ArenaShape onlineShape = ArenaShape.classic;

  GameController({int radius = 3}) {
    cpuLevel = StorageService.instance.cpuLevel;
    startNewGame(radius);
  }

  void startNewGame(int radius, {bool vsCPU = false, bool isOnline = false, String? roomCode, bool isHost = false, ArenaShape shape = ArenaShape.classic}) {
    _onlineSubscription?.cancel();
    _onlineSubscription = null;
    _blitzTimer?.cancel();
    _effectTimer?.cancel();
    effectText = '';
    _hasSavedResult = false;

    this.isVsCPU = vsCPU;
    this.isOnline = isOnline;
    this.roomCode = roomCode;
    this.isHost = isHost;

    // Salviamo la forma scelta anche se siamo offline
    onlineShape = shape;

    int levelToUse = isOnline ? (currentMatchLevel == 1 ? 2 : currentMatchLevel) : cpuLevel;

    // PASSIAMO LA FORMA AL MOTORE!
    board = GameBoard(radius: radius, level: levelToUse, seed: currentSeed, shape: onlineShape);

    isCPUThinking = false;
    opponentLeft = false;

    if (this.isOnline && this.roomCode != null) {
      _listenToOnlineGame(this.roomCode!);
    }

    _startTimer();
    notifyListeners();
  }

  void triggerSpecialEffect(String text, Color color) {
    effectText = text;
    effectColor = color;
    notifyListeners();
    _effectTimer?.cancel();
    _effectTimer = Timer(const Duration(milliseconds: 1200), () { effectText = ''; notifyListeners(); });
  }

  void _playEffects(List<Box> newClosed, {required bool isOpponent}) {
    if (newClosed.isEmpty) {
      AudioService.instance.playLineSfx(_activeTheme);
      if (!isOpponent) HapticFeedback.lightImpact();
    } else {
      bool isGold = newClosed.any((b) => b.type == BoxType.gold);
      bool isBomb = newClosed.any((b) => b.type == BoxType.bomb);

      if (isGold) {
        AudioService.instance.playBonusSfx(); triggerSpecialEffect("+2", Colors.amber); HapticFeedback.heavyImpact();
      } else if (isBomb) {
        AudioService.instance.playBombSfx(); triggerSpecialEffect("-1", Colors.redAccent); HapticFeedback.heavyImpact();
      } else {
        AudioService.instance.playBoxSfx(_activeTheme); HapticFeedback.heavyImpact();
      }
    }
  }

  // --- FIX TIMER: SCENDE PER ENTRAMBI, MA SCADE SOLO PER CHI HA IL TURNO ---
  void _startTimer() {
    _blitzTimer?.cancel();
    timeLeft = maxTime;

    _blitzTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
      if (isGameOver || isCPUThinking) { timer.cancel(); return; }

      if (timeLeft > 0) {
        timeLeft--;
        notifyListeners();
      } else {
        timer.cancel();
        // IL TIMEOUT FORZA LA MOSSA SOLO SE È IL MIO TURNO
        // Evita che il telefono in attesa forzi mosse per conto dell'avversario
        if (!isOnline || board.currentPlayer == myPlayer) {
          _handleTimeOut();
        }
      }
    });
  }

  void _handleTimeOut() {
    if (isOnline) {
      Line randomMove = AIEngine.getBestMove(board, 5);
      handleLineTap(randomMove, _activeTheme, forced: true);
    }
    else if (isVsCPU && board.currentPlayer == Player.red) {
      Line randomMove = AIEngine.getBestMove(board, cpuLevel);
      handleLineTap(randomMove, _activeTheme, forced: true);
    }
    else if (!isVsCPU) {
      Line randomMove = AIEngine.getBestMove(board, 5);
      handleLineTap(randomMove, _activeTheme, forced: true);
    }
  }

  void disconnectOnlineGame() {
    _onlineSubscription?.cancel();
    _onlineSubscription = null;
    _blitzTimer?.cancel();
    _effectTimer?.cancel();

    if (isOnline && roomCode != null) {
      FirebaseFirestore.instance.collection('games').doc(roomCode).update({'status': 'abandoned'}).catchError((e) => null);
    }

    isOnline = false;
    roomCode = null;
    currentMatchLevel = 1;
    currentSeed = null;
  }

  void requestRematch() {
    if (isOnline && roomCode != null) {
      currentMatchLevel++;
      int newSeed = DateTime.now().millisecondsSinceEpoch % 1000000;
      FirebaseFirestore.instance.collection('games').doc(roomCode).update({
        'moves': [],
        'matchLevel': currentMatchLevel,
        'status': 'playing',
        'seed': newSeed,
        'shape': onlineShape.name
      });
    }
  }

  @override
  void dispose() { disconnectOnlineGame(); super.dispose(); }

  void _listenToOnlineGame(String code) {
    _onlineSubscription = FirebaseFirestore.instance.collection('games').doc(code).snapshots().listen((doc) {
      if (!doc.exists) return;

      var data = doc.data() as Map<String, dynamic>;

      onlineHostName = data['hostName'] ?? "ROSSO";
      onlineGuestName = (data['guestName'] != null && data['guestName'] != '') ? data['guestName'] : "BLU";

      if (data['status'] == 'abandoned' && !board.isGameOver && !opponentLeft) {
        opponentLeft = true; notifyListeners(); return;
      }

      List<dynamic> moves = data['moves'] ?? [];
      int hostLevel = data['matchLevel'] ?? 1;
      int? hostSeed = data['seed'];

      String shapeStr = data['shape'] ?? 'classic';
      ArenaShape hostShape = ArenaShape.values.firstWhere((e) => e.name == shapeStr, orElse: () => ArenaShape.classic);
      onlineShape = hostShape;

      if (hostLevel > currentMatchLevel || (isOnline && currentSeed == null && hostSeed != null) || (hostSeed != null && hostSeed != currentSeed)) {
        currentMatchLevel = hostLevel; currentSeed = hostSeed;
        int levelToUse = (currentMatchLevel == 1) ? 2 : currentMatchLevel;
        board = GameBoard(radius: board.radius, level: levelToUse, seed: currentSeed, shape: onlineShape);
        isCPUThinking = false; notifyListeners(); return;
      }

      int firebaseMovesCount = moves.length;
      int localMovesCount = board.lines.where((l) => l.owner != Player.none).length;

      if (firebaseMovesCount == 0 && localMovesCount > 0) {
        int levelToUse = (currentMatchLevel == 1) ? 2 : currentMatchLevel;
        board = GameBoard(radius: board.radius, level: levelToUse, seed: currentSeed, shape: onlineShape);
        notifyListeners(); return;
      }

      if (firebaseMovesCount > localMovesCount) {
        bool newMovesApplied = false; // <-- FIX: Ci segniamo se abbiamo ricevuto mosse

        for (int i = localMovesCount; i < firebaseMovesCount; i++) {
          var m = moves[i]; Line? lineToPlay;
          for (var line in board.lines) {
            if ((line.p1.x == m['x1'] && line.p1.y == m['y1'] && line.p2.x == m['x2'] && line.p2.y == m['y2']) ||
                (line.p1.x == m['x2'] && line.p1.y == m['y2'] && line.p2.x == m['x1'] && line.p2.y == m['y1'])) {
              lineToPlay = line; break;
            }
          }
          if (lineToPlay != null && lineToPlay.owner == Player.none) {
            Player playerFromFirebase = (m['player'] == 'red') ? Player.red : Player.blue;
            bool isOpponentMove = (playerFromFirebase != myPlayer);
            List<Box> closedBefore = board.boxes.where((b) => b.owner != Player.none).toList();

            board.playMove(lineToPlay, forcedPlayer: playerFromFirebase);
            newMovesApplied = true;

            List<Box> newClosed = board.boxes.where((b) => b.owner != Player.none && !closedBefore.contains(b)).toList();
            if (isOpponentMove) _playEffects(newClosed, isOpponent: true);
          }
        }

        // --- FIX TIMER: SE L'AVVERSARIO HA MOSSO, RESETTIAMO IL TIMER ---
        if (newMovesApplied) {
          _startTimer();
        }

        if (board.isGameOver) _saveMatchResult();
        notifyListeners();
      }
    });
  }

  void handleLineTap(Line line, AppThemeType theme, {bool forced = false}) {
    if ((isCPUThinking || board.isGameOver || opponentLeft) && !forced) return;
    if (isOnline && board.currentPlayer != myPlayer && !forced) return;

    _activeTheme = theme;
    List<Box> closedBefore = board.boxes.where((b) => b.owner != Player.none).toList();

    if (board.playMove(line)) {
      List<Box> newClosed = board.boxes.where((b) => b.owner != Player.none && !closedBefore.contains(b)).toList();
      if (!forced) _playEffects(newClosed, isOpponent: false);

      _startTimer(); notifyListeners();

      if (isOnline && roomCode != null) {
        Map<String, dynamic> moveData = {
          'x1': line.p1.x, 'y1': line.p1.y, 'x2': line.p2.x, 'y2': line.p2.y,
          'player': myPlayer == Player.red ? 'red' : 'blue'
        };
        FirebaseFirestore.instance.collection('games').doc(roomCode).update({
          'moves': FieldValue.arrayUnion([moveData])
        }).catchError((e) => debugPrint("Errore: $e"));

        if (board.isGameOver) _saveMatchResult();

      } else {
        if (board.isGameOver) _saveMatchResult();
        else if (isVsCPU && board.currentPlayer == Player.blue) _checkCPUTurn();
      }
    }
  }

  void _checkCPUTurn() async {
    if (isVsCPU && board.currentPlayer == Player.blue && !board.isGameOver) {
      isCPUThinking = true; _blitzTimer?.cancel(); notifyListeners();
      await Future.delayed(const Duration(milliseconds: 600));

      if (!board.isGameOver) {
        List<Box> closedBefore = board.boxes.where((b) => b.owner != Player.none).toList();
        Line bestMove = AIEngine.getBestMove(board, cpuLevel);
        board.playMove(bestMove);

        List<Box> newClosed = board.boxes.where((b) => b.owner != Player.none && !closedBefore.contains(b)).toList();
        _playEffects(newClosed, isOpponent: true);

        isCPUThinking = false; _startTimer(); notifyListeners();

        if (board.isGameOver) _saveMatchResult();
        else _checkCPUTurn();
      }
    }
  }

  void _saveMatchResult() {
    if (_hasSavedResult) return;
    _hasSavedResult = true;

    String myRealName = StorageService.instance.playerName;
    if (myRealName.isEmpty) myRealName = "IO";

    if (isOnline) {
      String oppName = isHost ? onlineGuestName : onlineHostName;
      int myScore = isHost ? board.scoreRed : board.scoreBlue;
      int oppScore = isHost ? board.scoreBlue : board.scoreRed;
      StorageService.instance.saveMatchToHistory(myName: myRealName, opponent: oppName, myScore: myScore, oppScore: oppScore, isOnline: true);
    } else if (isVsCPU) {
      int myScore = board.scoreRed; int cpuScore = board.scoreBlue;
      if (myScore > cpuScore) StorageService.instance.addWin();
      else if (cpuScore > myScore) StorageService.instance.addLoss();
      StorageService.instance.saveMatchToHistory(myName: myRealName, opponent: "CPU (Liv. $cpuLevel)", myScore: myScore, oppScore: cpuScore, isOnline: false);
    } else {
      StorageService.instance.saveMatchToHistory(myName: myRealName, opponent: "Ospite (Locale)", myScore: board.scoreRed, oppScore: board.scoreBlue, isOnline: false);
    }
  }

  void increaseLevelAndRestart() {
    cpuLevel++; StorageService.instance.saveCpuLevel(cpuLevel);
    startNewGame(board.radius, vsCPU: true, shape: board.shape);
  }
}
// ===========================================================================
// FILE: lib/main.dart
// ===========================================================================

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'core/theme_manager.dart';
import 'logic/game_controller.dart';
import 'ui/home/home_screen.dart';
import 'services/storage_service.dart'; // <-- Importiamo il servizio
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';

void main() async {
  // Assicuriamoci che i motori di Flutter siano pronti
  WidgetsFlutterBinding.ensureInitialized();

  // 1. Accendiamo Firebase! (Questo ti era sfuggito)
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  // 2. Accendiamo la Memoria Locale!
  await StorageService.instance.init();

  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => ThemeManager()),
        ChangeNotifierProvider(create: (_) => GameController()),
      ],
      child: const TetraQApp(),
    ),
  );
}

class TetraQApp extends StatelessWidget {
  const TetraQApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'TetraQ',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        fontFamily: 'Roboto',
        useMaterial3: true,
      ),
      home: const HomeScreen(),
    );
  }
}
// ===========================================================================
// FILE: lib/models/game_board.dart
// ===========================================================================

import 'dart:math';

enum Player { red, blue, none }
enum BoxType { normal, gold, bomb, invisible }

enum ArenaShape { classic, cross, donut, hourglass }

class Dot {
  final int x;
  final int y;
  Dot(this.x, this.y);

  @override
  bool operator ==(Object other) => identical(this, other) || other is Dot && runtimeType == other.runtimeType && x == other.x && y == other.y;
  @override
  int get hashCode => x.hashCode ^ y.hashCode;
}

class Line {
  final Dot p1;
  final Dot p2;
  Player owner = Player.none;
  bool isPlayable = false;

  Line(this.p1, this.p2);

  bool connects(Dot a, Dot b) { return (p1 == a && p2 == b) || (p1 == b && p2 == a); }
}

class Box {
  final int x;
  final int y;
  Player owner = Player.none;
  late Line top, bottom, left, right;
  BoxType type = BoxType.normal;

  Box(this.x, this.y);

  bool isClosed() {
    if (type == BoxType.invisible) return false;
    return top.owner != Player.none && bottom.owner != Player.none && left.owner != Player.none && right.owner != Player.none;
  }

  int get value {
    if (type == BoxType.gold) return 2;
    if (type == BoxType.bomb) return -1;
    return 1;
  }
}

class GameBoard {
  final int radius;
  final int level;
  final int? seed;
  final ArenaShape shape;

  List<Dot> dots = [];
  List<Line> lines = [];
  List<Box> boxes = [];

  Player currentPlayer = Player.red;
  int scoreRed = 0;
  int scoreBlue = 0;
  bool isGameOver = false;

  GameBoard({required this.radius, this.level = 1, this.seed, this.shape = ArenaShape.classic}) {
    _generateBoard();
  }

  void _generateBoard() {
    int size = radius * 2 + 1;
    final random = seed != null ? Random(seed) : Random();

    dots.clear();
    lines.clear();
    boxes.clear();

    for (int y = 0; y < size; y++) {
      for (int x = 0; x < size; x++) {
        var box = Box(x, y);

        // Distanze dal centro della scacchiera
        int dx = (x - radius).abs();
        int dy = (y - radius).abs();

        // 1. Controllo base: Deve appartenere al Rombo primario
        bool isVisible = (dx + dy) <= radius;

        // 2. LOGICA FORME (Scolpiamo i blocchi dall'interno)
        if (isVisible) {
          switch (shape) {
            case ArenaShape.classic:
              break; // Nessun taglio

            case ArenaShape.cross:
            // Per fare una croce *all'interno* di un rombo, dobbiamo svuotare
            // 4 "triangolini" vicini agli assi mediani.
            // La logica è: se non sei sull'asse centrale verticale o orizzontale, sparisci.
            // Aumentiamo lo spessore del braccio se il raggio è grande.
              int spessoreBraccio = radius > 3 ? 1 : 0;
              if (dx > spessoreBraccio && dy > spessoreBraccio) {
                isVisible = false;
              }
              break;

            case ArenaShape.donut:
            // Il Buco Nero (Donut). Svuotiamo il nucleo centrale.
              int dimensioneBuco = radius > 3 ? 2 : 1;
              if ((dx + dy) <= dimensioneBuco) {
                isVisible = false;
              }
              break;

            case ArenaShape.hourglass:
            // La Clessidra. Svuotiamo i due lobi laterali (sinistro e destro).
            // Vogliamo mantenere solo l'alto e il basso.
              if (dx > dy) {
                isVisible = false;
              }
              // Manteniamo una singola scatola di giunzione al centro esatto
              if (x == radius && y == radius) {
                isVisible = true;
              }
              break;
          }
        }

        if (!isVisible) {
          box.type = BoxType.invisible;
        } else if (level > 1) {
          double chance = random.nextDouble();
          if (chance < 0.10) { box.type = BoxType.gold; }
          else if (chance > 0.90) { box.type = BoxType.bomb; }
        }
        boxes.add(box);
      }
    }

    // --- PULIZIA DEFINITIVA: ASSEGNAZIONE DELLE LINEE ---
    for (var box in boxes) {
      Dot tl = _getOrAddDot(box.x, box.y);
      Dot tr = _getOrAddDot(box.x + 1, box.y);
      Dot bl = _getOrAddDot(box.x, box.y + 1);
      Dot br = _getOrAddDot(box.x + 1, box.y + 1);

      box.top = _getOrAddLine(tl, tr);
      box.bottom = _getOrAddLine(bl, br);
      box.left = _getOrAddLine(tl, bl);
      box.right = _getOrAddLine(tr, br);

      // Le linee sono "giocabili" SOLO se appartengono a una scatola VISIBILE
      if (box.type != BoxType.invisible) {
        box.top.isPlayable = true;
        box.bottom.isPlayable = true;
        box.left.isPlayable = true;
        box.right.isPlayable = true;
      }
    }
  }

  Dot _getOrAddDot(int x, int y) {
    for (var dot in dots) { if (dot.x == x && dot.y == y) return dot; }
    var newDot = Dot(x, y);
    dots.add(newDot);
    return newDot;
  }

  Line _getOrAddLine(Dot a, Dot b) {
    for (var line in lines) { if (line.connects(a, b)) return line; }
    var newLine = Line(a, b);
    lines.add(newLine);
    return newLine;
  }

  bool playMove(Line lineToPlay, {Player? forcedPlayer}) {
    if (isGameOver) return false;

    Player playerMakingMove = forcedPlayer ?? currentPlayer;
    Line? actualLine;
    for (var l in lines) {
      if (l.connects(lineToPlay.p1, lineToPlay.p2)) {
        actualLine = l; break;
      }
    }

    if (actualLine == null || actualLine.owner != Player.none || !actualLine.isPlayable) return false;

    actualLine.owner = playerMakingMove;
    bool boxedClosed = false;

    for (var box in boxes) {
      if (box.owner == Player.none && box.isClosed()) {
        box.owner = playerMakingMove;
        boxedClosed = true;
        if (playerMakingMove == Player.red) { scoreRed += box.value; }
        else { scoreBlue += box.value; }
      }
    }

    if (lines.where((l) => l.isPlayable).every((l) => l.owner != Player.none)) { isGameOver = true; }

    if (forcedPlayer == null) {
      if (!boxedClosed && !isGameOver) { currentPlayer = (currentPlayer == Player.red) ? Player.blue : Player.red; }
    } else {
      if (!boxedClosed && !isGameOver) { currentPlayer = (forcedPlayer == Player.red) ? Player.blue : Player.red; }
      else { currentPlayer = forcedPlayer; }
    }

    return true;
  }
}
// ===========================================================================
// FILE: lib/models/player_info.dart
// ===========================================================================


// ===========================================================================
// FILE: lib/services/audio_service.dart
// ===========================================================================

import 'package:flutter/material.dart';
import 'package:audioplayers/audioplayers.dart';
import '../core/app_colors.dart';

class AudioService extends ChangeNotifier {
  static final AudioService instance = AudioService._internal();
  AudioService._internal();

  bool isMuted = false;
  final AudioPlayer _sfxPlayer = AudioPlayer();

  void toggleMute() {
    isMuted = !isMuted;
    notifyListeners();
  }

  void playLineSfx(AppThemeType theme) async {
    if (isMuted) return;
    String file = '';
    switch (theme) {
      case AppThemeType.minimal: file = 'minimal_line.wav'; break;
      case AppThemeType.doodle:
      case AppThemeType.wood:
        file = 'doodle_line.wav'; break;
      case AppThemeType.cyberpunk: file = 'cyber_line.wav'; break;
    }
    await _sfxPlayer.play(AssetSource('audio/sfx/$file'));
  }

  void playBoxSfx(AppThemeType theme) async {
    if (isMuted) return;
    String file = '';
    switch (theme) {
      case AppThemeType.minimal: file = 'minimal_box.wav'; break;
      case AppThemeType.doodle:
      case AppThemeType.wood:
        file = 'doodle_box.wav'; break;
      case AppThemeType.cyberpunk: file = 'cyber_box.wav'; break;
    }
    await _sfxPlayer.play(AssetSource('audio/sfx/$file'));
  }

  // --- NUOVI EFFETTI SPECIALI ---
  void playBonusSfx() async {
    if (isMuted) return;
    // Assicurati di aggiungere questo file nella cartella assets/audio/sfx/
    await _sfxPlayer.play(AssetSource('audio/sfx/bonus.wav'));
  }

  void playBombSfx() async {
    if (isMuted) return;
    // Assicurati di aggiungere questo file nella cartella assets/audio/sfx/
    await _sfxPlayer.play(AssetSource('audio/sfx/bomb.wav'));
  }
}
// ===========================================================================
// FILE: lib/services/firebase_service.dart
// ===========================================================================


// ===========================================================================
// FILE: lib/services/multiplayer_service.dart
// ===========================================================================

import 'dart:math';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:share_plus/share_plus.dart';

class MultiplayerService {
  final FirebaseFirestore _firestore = FirebaseFirestore.instance;

  CollectionReference get _gamesCollection => _firestore.collection('games');

  // AGGIUNTO shapeName
  Future<String> createGameRoom(int boardRadius, String hostName, String shapeName) async {
    String roomCode = _generateRoomCode();
    int randomSeed = Random().nextInt(1000000);

    await _gamesCollection.doc(roomCode).set({
      'status': 'waiting',
      'radius': boardRadius,
      'createdAt': FieldValue.serverTimestamp(),
      'players': ['host'],
      'turn': 'host',
      'moves': [],
      'seed': randomSeed,
      'hostName': hostName,
      'guestName': '',
      'shape': shapeName, // <-- SALVIAMO LA FORMA DELL'ARENA SU FIREBASE
    });

    return roomCode;
  }

  Future<Map<String, dynamic>?> joinGameRoom(String roomCode, String guestName) async {
    DocumentSnapshot doc = await _gamesCollection.doc(roomCode).get();

    if (doc.exists && doc['status'] == 'waiting') {
      await _gamesCollection.doc(roomCode).update({
        'status': 'playing',
        'players': FieldValue.arrayUnion(['guest']),
        'guestName': guestName,
      });
      return doc.data() as Map<String, dynamic>;
    }
    return null;
  }

  void shareInviteLink(String roomCode) {
    String message = "Ehi! Giochiamo a TetraQ? 🎮\nCopia questo intero messaggio e apri l'app per entrare direttamente, oppure inserisci manualmente il codice: $roomCode";
    Share.share(message);
  }

  Stream<DocumentSnapshot> listenToRoom(String roomCode) {
    return _gamesCollection.doc(roomCode).snapshots();
  }

  String _generateRoomCode() {
    const chars = 'ACDEFGHJKLMNPQRSTUVWXYZ2345679';
    final random = Random();
    return String.fromCharCodes(Iterable.generate(
      5, (_) => chars.codeUnitAt(random.nextInt(chars.length)),
    ));
  }
}
// ===========================================================================
// FILE: lib/services/storage_service.dart
// ===========================================================================

import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
import '../core/app_colors.dart';

class StorageService {
  static final StorageService instance = StorageService._internal();
  StorageService._internal();

  late SharedPreferences _prefs;

  // Si avvia quando apriamo l'app
  Future<void> init() async {
    _prefs = await SharedPreferences.getInstance();
  }

  // --- IMPOSTAZIONI ---
  int get savedThemeIndex => _prefs.getInt('theme') ?? AppThemeType.cyberpunk.index;
  Future<void> saveTheme(AppThemeType theme) async => await _prefs.setInt('theme', theme.index);

  int get savedRadius => _prefs.getInt('radius') ?? 2;
  Future<void> saveRadius(int radius) async => await _prefs.setInt('radius', radius);

  bool get isMuted => _prefs.getBool('isMuted') ?? false;
  Future<void> saveMuted(bool muted) async => await _prefs.setBool('isMuted', muted);

  // --- STATISTICHE VS CPU ---
  int get wins => _prefs.getInt('wins') ?? 0;
  Future<void> addWin() async => await _prefs.setInt('wins', wins + 1);

  int get losses => _prefs.getInt('losses') ?? 0;
  Future<void> addLoss() async => await _prefs.setInt('losses', losses + 1);

  int get cpuLevel => _prefs.getInt('cpuLevel') ?? 1;
  Future<void> saveCpuLevel(int level) async => await _prefs.setInt('cpuLevel', level);

  // --- MULTIPLAYER ---
  String get playerName => _prefs.getString('playerName') ?? '';
  Future<void> savePlayerName(String name) async => await _prefs.setString('playerName', name);

  // --- STORICO PARTITE ---
  List<Map<String, dynamic>> get matchHistory {
    List<String> history = _prefs.getStringList('matchHistory') ?? [];
    return history.map((e) => jsonDecode(e) as Map<String, dynamic>).toList();
  }

  // Salviamo sia il nostro nome che quello dell'avversario
  Future<void> saveMatchToHistory({required String myName, required String opponent, required int myScore, required int oppScore, required bool isOnline}) async {
    List<String> history = _prefs.getStringList('matchHistory') ?? [];

    Map<String, dynamic> match = {
      'date': DateTime.now().toIso8601String(),
      'myName': myName,
      'opponent': opponent,
      'myScore': myScore,
      'oppScore': oppScore,
      'isOnline': isOnline,
    };

    // Aggiungiamo in cima (il più recente per primo)
    history.insert(0, jsonEncode(match));

    // Teniamo solo le ultime 50 partite per non intasare la memoria
    if (history.length > 50) {
      history = history.sublist(0, 50);
    }

    await _prefs.setStringList('matchHistory', history);
  }
}
// ===========================================================================
// FILE: lib/ui/game/board_painter.dart
// ===========================================================================

import 'dart:math';
import 'package:flutter/material.dart';
import '../../models/game_board.dart';
import '../../core/app_colors.dart';

class BoardPainter extends CustomPainter {
  final GameBoard board;
  final ThemeColors theme;
  final AppThemeType themeType;

  BoardPainter({required this.board, required this.theme, required this.themeType});

  @override
  void paint(Canvas canvas, Size size) {
    if (themeType == AppThemeType.doodle) {
      final Paint paperGridPaint = Paint()
        ..color = Colors.grey.withOpacity(0.3)
        ..strokeWidth = 1.0
        ..style = PaintingStyle.stroke;

      double paperStep = 20.0;
      for (double i = 0; i <= size.width; i += paperStep) {
        canvas.drawLine(Offset(i, 0), Offset(i, size.height), paperGridPaint);
      }
      for (double i = 0; i <= size.height; i += paperStep) {
        canvas.drawLine(Offset(0, i), Offset(size.width, i), paperGridPaint);
      }
    }

    int gridPoints = board.radius * 2 + 2;
    double spacing = size.width / gridPoints;
    double offset = spacing / 2;
    Offset getScreenPos(int x, int y) => Offset(x * spacing + offset, y * spacing + offset);

    // --- 1. DISEGNO AREE CONQUISTATE E ICONE ---
    for (var box in board.boxes) {
      // Ignoriamo totalmente le scatole invisibili (tagliate via dalle nuove forme)
      if (box.type == BoxType.invisible) continue;

      Offset p1 = getScreenPos(box.x, box.y);
      Offset p2 = getScreenPos(box.x + 1, box.y + 1);
      Rect rect = Rect.fromPoints(p1, p2);

      if (box.owner != Player.none) {
        final boxPaint = Paint()
          ..style = PaintingStyle.fill
          ..color = box.owner == Player.red ? theme.playerRed.withOpacity(0.6) : theme.playerBlue.withOpacity(0.6);

        if (themeType == AppThemeType.wood) {
          _drawFlameBox(canvas, rect, box.owner == Player.red);
        } else if (themeType == AppThemeType.doodle) {
          Color penColor = box.owner == Player.red ? Colors.redAccent.shade700 : Colors.blueAccent.shade700;
          _drawScribbleBox(canvas, rect, penColor);
        } else {
          canvas.drawRect(rect, boxPaint);
        }
      }

      if (box.type == BoxType.gold) {
        _drawIconInBox(canvas, rect, Icons.star_rounded, Colors.amber);
      } else if (box.type == BoxType.bomb) {
        _drawIconInBox(canvas, rect, Icons.mood_bad_rounded, themeType == AppThemeType.cyberpunk ? Colors.greenAccent : Colors.deepPurple);
      }
    }

    // --- 2. DISEGNO LINEE ---
    for (var line in board.lines) {
      // FIX FONDAMENTALE PER LE FORME: Non disegnare linee non giocabili!
      if (!line.isPlayable) continue;

      Offset p1 = getScreenPos(line.p1.x, line.p1.y);
      Offset p2 = getScreenPos(line.p2.x, line.p2.y);

      Color lineColor = line.owner == Player.none
          ? theme.gridLine.withOpacity(0.4)
          : (line.owner == Player.red ? theme.playerRed : theme.playerBlue);

      if (themeType == AppThemeType.wood) {
        if (line.owner == Player.none) {
          canvas.drawLine(p1, p2, Paint()..color = const Color(0xFF3E2723).withOpacity(0.3)..strokeWidth = 4.5..strokeCap = StrokeCap.round);
        } else {
          _drawRealisticMatch(canvas, p1, p2, lineColor);
        }
      } else if (themeType == AppThemeType.cyberpunk) {
        _drawNeonLine(canvas, p1, p2, lineColor, line.owner != Player.none);
      } else if (themeType == AppThemeType.doodle) {
        Color doodleColor = line.owner == Player.none ? Colors.black.withOpacity(0.05) : lineColor;
        _drawWobblyLine(canvas, p1, p2, doodleColor, line.owner != Player.none);
      } else {
        canvas.drawLine(p1, p2, Paint()..color = lineColor..strokeWidth = 6.0..strokeCap = StrokeCap.round);
      }
    }

    // --- 3. DISEGNO PUNTINI (SOLO QUELLI UTILI) ---
    final dotPaint = Paint()..style = PaintingStyle.fill;

    // Raccogliamo solo i puntini che appartengono a linee giocabili
    Set<Dot> activeDots = {};
    for (var line in board.lines) {
      if (line.isPlayable) {
        activeDots.add(line.p1);
        activeDots.add(line.p2);
      }
    }

    for (var dot in activeDots) {
      Offset pos = getScreenPos(dot.x, dot.y);
      if (themeType == AppThemeType.wood) {
        canvas.drawCircle(pos, 3.5, dotPaint..color = const Color(0xFF3E2723).withOpacity(0.2));
      } else if (themeType == AppThemeType.cyberpunk) {
        canvas.drawCircle(pos, 6.0, Paint()..color = theme.gridLine.withOpacity(0.3));
        canvas.drawCircle(pos, 3.0, Paint()..color = Colors.white.withOpacity(0.5));
      } else if (themeType == AppThemeType.doodle) {
        canvas.drawRect(Rect.fromCenter(center: pos, width: 4, height: 4), dotPaint..color = Colors.black.withOpacity(0.25));
      } else {
        canvas.drawCircle(pos, 5.0, dotPaint..color = theme.text.withOpacity(0.6));
      }
    }
  }

  void _drawIconInBox(Canvas canvas, Rect rect, IconData icon, Color color) {
    TextPainter textPainter = TextPainter(textDirection: TextDirection.ltr);
    textPainter.text = TextSpan(
      text: String.fromCharCode(icon.codePoint),
      style: TextStyle(
          color: color.withOpacity(0.7),
          fontSize: rect.width * 0.45,
          fontFamily: icon.fontFamily,
          package: icon.fontPackage,
          shadows: [Shadow(color: color.withOpacity(0.6), blurRadius: 10, offset: const Offset(0, 0))]
      ),
    );
    textPainter.layout();
    textPainter.paint(canvas, Offset(rect.center.dx - textPainter.width / 2, rect.center.dy - textPainter.height / 2));
  }

  void _drawFlameBox(Canvas canvas, Rect baseRect, bool isRed) {
    final rand = Random((baseRect.left + baseRect.top).toInt());
    Offset center = baseRect.center;

    double w = baseRect.width * 0.35;
    double h = baseRect.height * 0.55;

    Offset bottomCenter = Offset(center.dx, center.dy + h * 0.5);

    Color outerColor = isRed ? Colors.red.shade600.withOpacity(0.85) : Colors.blue.shade700.withOpacity(0.85);
    Color midColor = isRed ? Colors.orangeAccent : Colors.lightBlueAccent;
    Color coreColor = isRed ? Colors.yellowAccent : Colors.white;

    canvas.drawOval(
      Rect.fromCenter(center: bottomCenter, width: w * 1.5, height: w * 0.5),
      Paint()
        ..color = Colors.black.withOpacity(0.4)
        ..maskFilter = const MaskFilter.blur(BlurStyle.normal, 4.0),
    );

    void drawFlameLayer(double scale, Color color, double tipOffsetX) {
      Path path = Path();
      double fw = w * scale;
      double fh = h * scale;

      path.moveTo(bottomCenter.dx, bottomCenter.dy);

      path.cubicTo(
        bottomCenter.dx + fw, bottomCenter.dy,
        bottomCenter.dx + fw * 0.8, bottomCenter.dy - fh * 0.6,
        bottomCenter.dx + tipOffsetX, bottomCenter.dy - fh,
      );

      path.cubicTo(
        bottomCenter.dx - fw * 0.8, bottomCenter.dy - fh * 0.6,
        bottomCenter.dx - fw, bottomCenter.dy,
        bottomCenter.dx, bottomCenter.dy,
      );

      canvas.drawPath(
        path,
        Paint()
          ..color = color
          ..style = PaintingStyle.fill
          ..maskFilter = const MaskFilter.blur(BlurStyle.normal, 1.5),
      );
    }

    double randomTipX = (rand.nextDouble() - 0.5) * w * 0.8;

    drawFlameLayer(1.0, outerColor, randomTipX);
    drawFlameLayer(0.65, midColor.withOpacity(0.9), randomTipX * 0.6);
    drawFlameLayer(0.35, coreColor.withOpacity(0.9), randomTipX * 0.2);
  }

  void _drawScribbleBox(Canvas canvas, Rect baseRect, Color color) {
    final rand = Random((baseRect.left + baseRect.top).toInt());
    final paint = Paint()
      ..color = color.withOpacity(0.85)
      ..style = PaintingStyle.stroke
      ..strokeWidth = 3.5
      ..strokeCap = StrokeCap.round
      ..strokeJoin = StrokeJoin.round;

    final path = Path();
    Rect rect = baseRect.deflate(4.0);

    int numZigs = 15 + rand.nextInt(6);
    double stepY = rect.height / numZigs;

    path.moveTo(rect.left + rand.nextDouble() * 5, rect.top + rand.nextDouble() * 5);

    for (int i = 1; i <= numZigs; i++) {
      double targetX = (i % 2 != 0) ? rect.right + (rand.nextDouble() * 4 - 2) : rect.left + (rand.nextDouble() * 4 - 2);
      double targetY = rect.top + stepY * i + (rand.nextDouble() - 0.5) * 3;
      double ctrlX = rect.center.dx + (rand.nextDouble() - 0.5) * 20;
      double ctrlY = targetY - stepY / 2;
      path.quadraticBezierTo(ctrlX, ctrlY, targetX, targetY);
    }
    canvas.drawPath(path, paint);
  }

  void _drawRealisticMatch(Canvas canvas, Offset p1, Offset p2, Color headColor) {
    int seed = (p1.dx * 1000 + p1.dy).toInt();
    Random rand = Random(seed);
    Vector2 dir = Vector2(p2.dx - p1.dx, p2.dy - p1.dy).normalized();
    double shrink = 8.0;
    Offset start = Offset(p1.dx + dir.x * shrink, p1.dy + dir.y * shrink);
    Offset end = Offset(p2.dx - dir.x * shrink, p2.dy - dir.y * shrink);
    start += Offset(rand.nextDouble() * 4 - 2, rand.nextDouble() * 4 - 2);
    end += Offset(rand.nextDouble() * 4 - 2, rand.nextDouble() * 4 - 2);
    bool headAtEnd = rand.nextBool();
    Offset headPos = headAtEnd ? end : start;
    Offset tailPos = headAtEnd ? start : end;
    Vector2 matchDir = Vector2(headPos.dx - tailPos.dx, headPos.dy - tailPos.dy).normalized();
    canvas.drawLine(tailPos + const Offset(4, 4), headPos + const Offset(4, 4), Paint()..color = Colors.black.withOpacity(0.6)..strokeWidth = 7.0..strokeCap = StrokeCap.round);
    canvas.drawLine(tailPos, headPos, Paint()..color = const Color(0xFF6D4C41)..strokeWidth = 7.0..strokeCap = StrokeCap.round);
    canvas.drawLine(tailPos, headPos, Paint()..color = const Color(0xFFEDC498)..strokeWidth = 4.0..strokeCap = StrokeCap.round);
    Offset burnPos = Offset(headPos.dx - matchDir.x * 8, headPos.dy - matchDir.y * 8);
    canvas.drawLine(burnPos, headPos, Paint()..color = const Color(0xFF2E1A14)..strokeWidth = 6.0..strokeCap = StrokeCap.round);
    canvas.save();
    canvas.translate(headPos.dx, headPos.dy);
    double angle = atan2(matchDir.y, matchDir.x);
    canvas.rotate(angle);
    Rect headOval = Rect.fromCenter(center: Offset.zero, width: 18.0, height: 13.0);
    canvas.drawOval(headOval.shift(const Offset(1, 2)), Paint()..color = Colors.black.withOpacity(0.6));
    canvas.drawOval(headOval, Paint()..color = headColor);
    canvas.restore();
  }

  void _drawNeonLine(Canvas canvas, Offset p1, Offset p2, Color color, bool isConquered) {
    double mainWidth = isConquered ? 6.0 : 3.0;

    canvas.drawLine(p1, p2, Paint()
      ..color = color.withOpacity(isConquered ? 0.4 : 0.2)
      ..strokeWidth = mainWidth * 4
      ..strokeCap = StrokeCap.round
      ..maskFilter = MaskFilter.blur(BlurStyle.normal, isConquered ? 12.0 : 6.0)
    );

    if (isConquered) {
      canvas.drawLine(p1, p2, Paint()
        ..color = color.withOpacity(0.7)
        ..strokeWidth = mainWidth * 2
        ..strokeCap = StrokeCap.round
        ..maskFilter = const MaskFilter.blur(BlurStyle.normal, 6.0)
      );
    }

    canvas.drawLine(p1, p2, Paint()
      ..color = isConquered ? Colors.white.withOpacity(0.9) : color.withOpacity(0.6)
      ..strokeWidth = mainWidth
      ..strokeCap = StrokeCap.round
    );
  }

  void _drawWobblyLine(Canvas canvas, Offset p1, Offset p2, Color color, bool isConquered) {
    final random = Random((p1.dx + p1.dy + p2.dx + p2.dy).toInt());
    final dx = p2.dx - p1.dx;
    final dy = p2.dy - p1.dy;

    double strokeW = isConquered ? 4.5 : 2.0;

    final basePaint = Paint()
      ..color = color
      ..strokeWidth = strokeW
      ..style = PaintingStyle.stroke
      ..strokeCap = StrokeCap.round;

    final mid1 = Offset(p1.dx + dx / 2 + (random.nextDouble() - 0.5) * 8, p1.dy + dy / 2 + (random.nextDouble() - 0.5) * 8);
    canvas.drawPath(Path()..moveTo(p1.dx, p1.dy)..quadraticBezierTo(mid1.dx, mid1.dy, p2.dx, p2.dy), basePaint);

    final mid2 = Offset(p1.dx + dx / 2 + (random.nextDouble() - 0.5) * 6, p1.dy + dy / 2 + (random.nextDouble() - 0.5) * 6);
    canvas.drawPath(Path()..moveTo(p1.dx, p1.dy)..quadraticBezierTo(mid2.dx, mid2.dy, p2.dx, p2.dy), basePaint..strokeWidth = strokeW * 0.5..color = color.withOpacity(0.8));
  }

  @override
  bool shouldRepaint(covariant BoardPainter oldDelegate) => true;
}

class Vector2 {
  final double x, y;
  Vector2(this.x, this.y);
  double get length => sqrt(x * x + y * y);
  Vector2 normalized() {
    double l = length;
    return l == 0 ? Vector2(0, 0) : Vector2(x / l, y / l);
  }
}
// ===========================================================================
// FILE: lib/ui/game/game_screen.dart
// ===========================================================================

import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../logic/game_controller.dart';
import '../../core/theme_manager.dart';
import '../../core/app_colors.dart';
import 'board_painter.dart';
import 'score_board.dart';
import '../../widgets/game_over_dialog.dart';
import '../../models/game_board.dart';

class GameScreen extends StatelessWidget {
  const GameScreen({super.key});

  @override
  Widget build(BuildContext context) {
    final themeManager = context.watch<ThemeManager>();
    final themeType = themeManager.currentThemeType;
    final theme = themeManager.currentColors;
    final gameController = context.watch<GameController>();

    // --- CONTROLLO EVENTI DI FINE PARTITA O ABBANDONO ---
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (gameController.opponentLeft) {
        showDialog(
            barrierDismissible: false,
            context: context,
            builder: (dialogContext) => AlertDialog(
              backgroundColor: theme.background,
              shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
              title: Text("VITTORIA A TAVOLINO!", textAlign: TextAlign.center, style: TextStyle(color: theme.playerRed, fontWeight: FontWeight.bold)),
              content: Text("L'avversario ha abbandonato la stanza.\nSei il vincitore incontestato!", textAlign: TextAlign.center, style: TextStyle(color: theme.text, fontSize: 16)),
              actionsAlignment: MainAxisAlignment.center,
              actions: [
                ElevatedButton(
                  style: ElevatedButton.styleFrom(
                      backgroundColor: theme.playerBlue,
                      foregroundColor: Colors.white,
                      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15))
                  ),
                  onPressed: () {
                    gameController.disconnectOnlineGame();
                    Navigator.pop(dialogContext);
                    Navigator.pop(context);
                  },
                  child: const Text("MENU PRINCIPALE", style: TextStyle(fontWeight: FontWeight.bold)),
                )
              ],
            )
        );
      } else if (gameController.board.isGameOver) {
        showDialog(barrierDismissible: false, context: context, builder: (_) => const GameOverDialog());
      }
    });

    String? bgImage;
    if (themeType == AppThemeType.wood) bgImage = 'assets/images/wood_bg.jpg';
    if (themeType == AppThemeType.doodle) bgImage = 'assets/images/doodle_bg.jpg';

    Color indicatorColor = themeType == AppThemeType.cyberpunk ? Colors.white : Colors.black;

    // --- IL CONTENUTO PRINCIPALE (Plancia e UI) ---
    Widget gameContent = SafeArea(
      child: Column(
        children: [
          const ScoreBoard(),

          Expanded(
            child: Center(
              child: Padding(
                padding: const EdgeInsets.all(10.0),
                child: AspectRatio(
                  aspectRatio: 1,
                  child: LayoutBuilder(
                      builder: (context, constraints) {
                        return GestureDetector(
                          behavior: HitTestBehavior.opaque,
                          onTapDown: (details) => _handleTap(details.localPosition, constraints.maxWidth, gameController, themeType),
                          child: CustomPaint(
                            size: Size(constraints.maxWidth, constraints.maxHeight),
                            painter: BoardPainter(
                              board: gameController.board,
                              theme: theme,
                              themeType: themeType,
                            ),
                          ),
                        );
                      }
                  ),
                ),
              ),
            ),
          ),

          // --- ZONA INFERIORE: INDICATORE A SX, PULSANTE ESCI A DX ---
          Padding(
            padding: const EdgeInsets.only(bottom: 20.0, left: 20.0, right: 20.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                if (gameController.isVsCPU)
                  Container(
                    padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                    decoration: BoxDecoration(
                      color: indicatorColor.withOpacity(0.1),
                      borderRadius: BorderRadius.circular(20),
                      border: Border.all(color: indicatorColor.withOpacity(0.3)),
                    ),
                    child: Row(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        Icon(Icons.smart_toy_rounded, size: 16, color: indicatorColor),
                        const SizedBox(width: 8),
                        Text(
                          "LIVELLO CPU: ${gameController.cpuLevel}",
                          style: TextStyle(
                            color: indicatorColor,
                            fontWeight: FontWeight.bold,
                            fontSize: 13,
                            letterSpacing: 1.0,
                          ),
                        ),
                      ],
                    ),
                  )
                else
                  const SizedBox(),

                // --- PULSANTE ESCI ---
                Container(
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(20),
                    boxShadow: [
                      BoxShadow(
                        color: Colors.black.withOpacity(0.4),
                        offset: const Offset(0, 4),
                        blurRadius: 5,
                      ),
                    ],
                  ),
                  child: TextButton.icon(
                    style: TextButton.styleFrom(
                        backgroundColor: bgImage != null ? Colors.black87 : theme.background,
                        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
                        shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(20),
                          side: BorderSide(color: Colors.white.withOpacity(0.1), width: 1),
                        )
                    ),
                    icon: Icon(Icons.exit_to_app, color: bgImage != null ? Colors.white : theme.text, size: 20),
                    onPressed: () {
                      gameController.disconnectOnlineGame();
                      Navigator.pop(context);
                    },
                    label: Text("ESCI", style: TextStyle(color: bgImage != null ? Colors.white : theme.text, fontWeight: FontWeight.bold, fontSize: 14)),
                  ),
                ),
              ],
            ),
          )
        ],
      ),
    );

    // --- STRUTTURA A LIVELLI (STACK) DELLO SCHERMO ---
    return PopScope(
      canPop: true,
      onPopInvoked: (didPop) {
        gameController.disconnectOnlineGame();
      },
      child: Scaffold(
        backgroundColor: bgImage != null ? Colors.transparent : theme.background,
        body: CustomPaint(
          painter: themeType == AppThemeType.minimal
              ? FullScreenGridPainter(Colors.black.withOpacity(0.06))
              : null,
          child: Container(
            decoration: bgImage != null
                ? BoxDecoration(
              image: DecorationImage(
                image: AssetImage(bgImage),
                fit: BoxFit.cover,
                colorFilter: themeType == AppThemeType.doodle
                    ? ColorFilter.mode(Colors.white.withOpacity(0.7), BlendMode.lighten)
                    : null,
              ),
            )
                : null,

            // ==========================================
            // LA MAGIA DELLO SFARFALLIO AVVIENE QUI
            // ==========================================
            child: Stack(
              children: [
                // EFFETTO 1: TIMER LAMPEGGIANTE (Se restano 5 secondi)
                if (!gameController.isCPUThinking && !gameController.isGameOver && gameController.timeLeft > 0 && gameController.timeLeft <= 5)
                  Positioned.fill(
                    child: BlitzBackgroundEffect(
                      timeLeft: gameController.timeLeft,
                      color: theme.playerRed, // Rosso Allarme!
                    ),
                  ),

                // --- NUOVO EFFETTO 2: POPUP ORO (+2) E BOMBA (-1) ---
                if (gameController.effectText.isNotEmpty)
                  Positioned.fill(
                    child: SpecialEventBackgroundEffect(
                      text: gameController.effectText,
                      color: gameController.effectColor,
                    ),
                  ),

                // LA PLANCIA DI GIOCO SOPRA TUTTI GLI EFFETTI
                Positioned.fill(
                  child: gameContent,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  // ==========================================
  // NUOVA GESTIONE DEI TOCCHI E DELLE DISTANZE
  // ==========================================
  void _handleTap(Offset tapPos, double size, GameController controller, AppThemeType themeType) {
    final board = controller.board;
    if (board.isGameOver) return;

    int gridPoints = board.radius * 2 + 2;
    double spacing = size / gridPoints;
    double offset = spacing / 2;

    Line? closestLine;
    double minDistance = double.infinity;
    double maxTouchDistance = spacing * 0.4;

    // Scorriamo TUTTE le linee valide della plancia
    for (var line in board.lines) {
      // FIX FONDAMENTALE: Ignoriamo le linee invisibili o già prese!
      if (line.owner != Player.none || !line.isPlayable) continue;

      Offset screenP1 = Offset(line.p1.x * spacing + offset, line.p1.y * spacing + offset);
      Offset screenP2 = Offset(line.p2.x * spacing + offset, line.p2.y * spacing + offset);

      double dist = _distanceToSegment(tapPos, screenP1, screenP2);

      if (dist < minDistance && dist < maxTouchDistance) {
        minDistance = dist;
        closestLine = line;
      }
    }

    if (closestLine != null) {
      controller.handleLineTap(closestLine, themeType);
    }
  }

  // Calcolo della distanza su coordinate schermo reali
  double _distanceToSegment(Offset p, Offset a, Offset b) {
    double l2 = (a.dx - b.dx) * (a.dx - b.dx) + (a.dy - b.dy) * (a.dy - b.dy);
    if (l2 == 0) return (p - a).distance;
    double t = (((p.dx - a.dx) * (b.dx - a.dx) + (p.dy - a.dy) * (b.dy - a.dy)) / l2).clamp(0.0, 1.0);
    Offset projection = Offset(a.dx + t * (b.dx - a.dx), a.dy + t * (b.dy - a.dy));
    return (p - projection).distance;
  }
}

// --- CLASSE PER LO SFONDO A QUADRETTI ---
class FullScreenGridPainter extends CustomPainter {
  final Color gridColor;
  FullScreenGridPainter(this.gridColor);

  @override
  void paint(Canvas canvas, Size size) {
    final Paint paperGridPaint = Paint()
      ..color = gridColor
      ..strokeWidth = 1.0
      ..style = PaintingStyle.stroke;

    double paperStep = 20.0;
    for (double i = 0; i <= size.width; i += paperStep) {
      canvas.drawLine(Offset(i, 0), Offset(i, size.height), paperGridPaint);
    }
    for (double i = 0; i <= size.height; i += paperStep) {
      canvas.drawLine(Offset(0, i), Offset(size.width, i), paperGridPaint);
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

// ==============================================================
// WIDGET ANIMATO PER IL TIMER (BATTITO CARDIACO / ALLARME)
// ==============================================================
class BlitzBackgroundEffect extends StatefulWidget {
  final int timeLeft;
  final Color color;

  const BlitzBackgroundEffect({super.key, required this.timeLeft, required this.color});

  @override
  State<BlitzBackgroundEffect> createState() => _BlitzBackgroundEffectState();
}

class _BlitzBackgroundEffectState extends State<BlitzBackgroundEffect> with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this, duration: const Duration(milliseconds: 400))..repeat(reverse: true);
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _controller,
      builder: (context, child) {
        return Container(
          color: widget.color.withOpacity(0.12 * _controller.value),
          child: Center(
            child: ImageFiltered(
              imageFilter: ImageFilter.blur(sigmaX: 2.0, sigmaY: 2.0),
              child: Text(
                '${widget.timeLeft}',
                style: TextStyle(
                  fontSize: 300,
                  fontWeight: FontWeight.w900,
                  color: widget.color.withOpacity(0.35 + (0.3 * _controller.value)),
                  height: 1.0,
                ),
              ),
            ),
          ),
        );
      },
    );
  }
}

// ==============================================================
// WIDGET ANIMATO PER LE CASELLE SPECIALI (+2 / -1)
// ==============================================================
class SpecialEventBackgroundEffect extends StatefulWidget {
  final String text;
  final Color color;

  const SpecialEventBackgroundEffect({super.key, required this.text, required this.color});

  @override
  State<SpecialEventBackgroundEffect> createState() => _SpecialEventBackgroundEffectState();
}

class _SpecialEventBackgroundEffectState extends State<SpecialEventBackgroundEffect> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _scaleAnimation;
  late Animation<double> _opacityAnimation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this, duration: const Duration(milliseconds: 1000))..forward();

    _scaleAnimation = Tween<double>(begin: 0.5, end: 1.5).animate(CurvedAnimation(parent: _controller, curve: Curves.easeOutCubic));
    _opacityAnimation = Tween<double>(begin: 0.9, end: 0.0).animate(CurvedAnimation(parent: _controller, curve: Curves.easeIn));
  }

  @override
  void didUpdateWidget(covariant SpecialEventBackgroundEffect oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.text != widget.text) {
      _controller.reset();
      _controller.forward();
    }
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _controller,
      builder: (context, child) {
        return Center(
          child: Transform.scale(
            scale: _scaleAnimation.value,
            child: Opacity(
              opacity: _opacityAnimation.value,
              child: ImageFiltered(
                imageFilter: ImageFilter.blur(sigmaX: 3.0, sigmaY: 3.0),
                child: Text(
                  widget.text,
                  style: TextStyle(
                    fontSize: 250,
                    fontWeight: FontWeight.w900,
                    color: widget.color,
                    height: 1.0,
                  ),
                ),
              ),
            ),
          ),
        );
      },
    );
  }
}
// ===========================================================================
// FILE: lib/ui/game/score_board.dart
// ===========================================================================

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../logic/game_controller.dart';
import '../../models/game_board.dart';
import '../../core/theme_manager.dart';
import '../../services/audio_service.dart';
import '../../core/app_colors.dart';

class ScoreBoard extends StatefulWidget {
  const ScoreBoard({super.key});

  @override
  State<ScoreBoard> createState() => _ScoreBoardState();
}

class _ScoreBoardState extends State<ScoreBoard> {
  @override
  Widget build(BuildContext context) {
    final controller = context.watch<GameController>();
    final themeManager = context.watch<ThemeManager>();
    final theme = themeManager.currentColors;
    final themeType = themeManager.currentThemeType;

    int redScore = controller.board.scoreRed;
    int blueScore = controller.board.scoreBlue;

    bool isRedTurn = controller.board.currentPlayer == Player.red;
    bool isMuted = AudioService.instance.isMuted;

    // --- LOGICA PER I NOMI ---
    String nameRed = "ROSSO";
    String nameBlue = themeType == AppThemeType.cyberpunk ? "VERDE" : "BLU";

    if (controller.isOnline) {
      nameRed = controller.onlineHostName.toUpperCase();
      nameBlue = controller.onlineGuestName.toUpperCase();
    } else if (controller.isVsCPU) {
      nameRed = "TU";
      nameBlue = "CPU";
    }

    return Container(
      padding: const EdgeInsets.only(top: 10, bottom: 20, left: 20, right: 20),
      decoration: BoxDecoration(
        color: theme.background.withOpacity(0.95),
        boxShadow: [
          BoxShadow(
            color: Colors.black.withOpacity(0.3),
            offset: const Offset(0, 4),
            blurRadius: 8,
          ),
        ],
        borderRadius: const BorderRadius.only(
          bottomLeft: Radius.circular(30),
          bottomRight: Radius.circular(30),
        ),
      ),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          _PlayerScore(color: theme.playerRed, score: redScore, isTurn: isRedTurn, textColor: theme.text, title: nameRed),

          Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Text(
                  "TETRAQ",
                  style: TextStyle(
                      fontSize: 24,
                      fontWeight: FontWeight.w900,
                      color: theme.text,
                      letterSpacing: 4,
                      shadows: [Shadow(color: Colors.black.withOpacity(0.3), offset: const Offset(1, 2), blurRadius: 2)]
                  )
              ),
              IconButton(
                icon: Icon(isMuted ? Icons.volume_off : Icons.volume_up, color: theme.text.withOpacity(0.7)),
                onPressed: () {
                  setState(() {
                    AudioService.instance.toggleMute();
                  });
                },
              ),
            ],
          ),

          _PlayerScore(color: theme.playerBlue, score: blueScore, isTurn: !isRedTurn, textColor: theme.text, title: nameBlue),
        ],
      ),
    );
  }
}

class _PlayerScore extends StatelessWidget {
  final Color color;
  final int score;
  final bool isTurn;
  final Color textColor;
  final String title;

  const _PlayerScore({required this.color, required this.score, required this.isTurn, required this.textColor, required this.title});

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Text(title, style: TextStyle(fontWeight: FontWeight.bold, color: isTurn ? color : textColor.withOpacity(0.5), fontSize: 12)),
        const SizedBox(height: 5),
        AnimatedContainer(
          duration: const Duration(milliseconds: 300),
          padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 10),
          decoration: BoxDecoration(
            color: color.withOpacity(isTurn ? 1.0 : 0.2),
            borderRadius: BorderRadius.circular(15),
            border: isTurn ? Border.all(color: Colors.white.withOpacity(0.4), width: 2) : Border.all(color: Colors.transparent, width: 2),
            boxShadow: isTurn ? [
              BoxShadow(color: color.withOpacity(0.5), offset: const Offset(0, 4), blurRadius: 6)
            ] : [],
          ),
          child: Text('$score', style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold, color: isTurn ? Colors.white : textColor.withOpacity(0.5))),
        ),
      ],
    );
  }
}
// ===========================================================================
// FILE: lib/ui/home/history_screen.dart
// ===========================================================================

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:intl/intl.dart';
import '../../core/theme_manager.dart';
import '../../services/storage_service.dart';

class HistoryScreen extends StatelessWidget {
  const HistoryScreen({super.key});

  @override
  Widget build(BuildContext context) {
    final theme = context.watch<ThemeManager>().currentColors;
    final history = StorageService.instance.matchHistory;

    return Scaffold(
      backgroundColor: theme.background,
      appBar: AppBar(
        title: Text("STORICO PARTITE", style: TextStyle(fontWeight: FontWeight.w900, color: theme.text, letterSpacing: 2)),
        backgroundColor: Colors.transparent,
        elevation: 0,
        iconTheme: IconThemeData(color: theme.text),
      ),
      body: history.isEmpty
          ? Center(
        child: Text(
          "Nessuna partita giocata.\nScendi in campo!",
          textAlign: TextAlign.center,
          style: TextStyle(color: theme.text.withOpacity(0.5), fontSize: 18, fontWeight: FontWeight.bold),
        ),
      )
          : ListView.builder(
        padding: const EdgeInsets.all(20),
        itemCount: history.length,
        itemBuilder: (context, index) {
          final match = history[index];

          DateTime date = DateTime.parse(match['date']);
          String formattedDate = DateFormat('dd MMM yyyy - HH:mm').format(date);

          // Leggiamo entrambi i nomi
          String myName = match['myName'] ?? "IO"; // Usa 'IO' se è una partita vecchia
          String opponent = match['opponent'];

          int myScore = match['myScore'];
          int oppScore = match['oppScore'];
          bool isOnline = match['isOnline'];

          bool isWin = myScore > oppScore;
          bool isDraw = myScore == oppScore;

          Color resultColor = isWin ? Colors.green : (isDraw ? Colors.grey : theme.playerRed);
          String resultText = isWin ? "VITTORIA" : (isDraw ? "PAREGGIO" : "SCONFITTA");

          return Container(
            margin: const EdgeInsets.only(bottom: 15),
            padding: const EdgeInsets.all(16),
            decoration: BoxDecoration(
              color: theme.text.withOpacity(0.05),
              borderRadius: BorderRadius.circular(20),
              border: Border.all(color: resultColor.withOpacity(0.5), width: 2),
              boxShadow: [
                BoxShadow(color: Colors.black.withOpacity(0.2), offset: const Offset(0, 4), blurRadius: 6),
              ],
            ),
            child: Row(
              children: [
                // Icona Tipo di Partita
                Container(
                  padding: const EdgeInsets.all(12),
                  decoration: BoxDecoration(
                    color: resultColor.withOpacity(0.1),
                    shape: BoxShape.circle,
                  ),
                  child: Icon(
                    isOnline ? Icons.public : (opponent.contains("CPU") ? Icons.smart_toy : Icons.people_alt),
                    color: resultColor,
                    size: 28,
                  ),
                ),
                const SizedBox(width: 15),

                // Dati Partita (Ora con i nomi chiari)
                Expanded(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(resultText, style: TextStyle(color: resultColor, fontWeight: FontWeight.w900, fontSize: 16, letterSpacing: 1.5)),
                      const SizedBox(height: 5),
                      // NOMI GIOCATORI
                      RichText(
                          text: TextSpan(
                              children: [
                                TextSpan(text: myName, style: TextStyle(color: theme.playerBlue, fontWeight: FontWeight.bold, fontSize: 15)),
                                TextSpan(text: " vs ", style: TextStyle(color: theme.text.withOpacity(0.5), fontStyle: FontStyle.italic, fontSize: 12)),
                                TextSpan(text: opponent, style: TextStyle(color: theme.playerRed, fontWeight: FontWeight.bold, fontSize: 15)),
                              ]
                          )
                      ),
                      const SizedBox(height: 5),
                      Text(formattedDate, style: TextStyle(color: theme.text.withOpacity(0.5), fontSize: 12)),
                    ],
                  ),
                ),

                // Punteggio
                Container(
                  padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
                  decoration: BoxDecoration(
                    color: theme.background,
                    borderRadius: BorderRadius.circular(15),
                    border: Border.all(color: theme.gridLine.withOpacity(0.3)),
                  ),
                  child: Row(
                    children: [
                      Text("$myScore", style: TextStyle(fontSize: 22, fontWeight: FontWeight.w900, color: theme.playerBlue)),
                      Text(" - ", style: TextStyle(fontSize: 18, color: theme.text.withOpacity(0.5))),
                      Text("$oppScore", style: TextStyle(fontSize: 22, fontWeight: FontWeight.w900, color: theme.playerRed)),
                    ],
                  ),
                ),
              ],
            ),
          );
        },
      ),
    );
  }
}
// ===========================================================================
// FILE: lib/ui/home/home_screen.dart
// ===========================================================================

// ===========================================================================
// FILE: lib/ui/home/home_screen.dart
// ===========================================================================

import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter/services.dart';
import 'dart:math' as math;
import '../../core/theme_manager.dart';
import '../../core/app_colors.dart';
import '../../models/game_board.dart';
import '../game/game_screen.dart';
import '../settings/settings_screen.dart';
import '../../logic/game_controller.dart';
import '../../services/storage_service.dart';
import '../multiplayer/lobby_screen.dart';
import 'history_screen.dart';

// --- NUOVI WIDGET PERSONALIZZATI ---

class _NeonShapeButton extends StatelessWidget {
  final IconData icon;
  final String label;
  final bool isSelected;
  final ThemeColors theme;
  final VoidCallback onTap;

  const _NeonShapeButton({required this.icon, required this.label, required this.isSelected, required this.theme, required this.onTap});

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeInOut,
        padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(15),
          color: isSelected ? theme.playerBlue.withOpacity(0.2) : theme.text.withOpacity(0.05),
          border: Border.all(
            color: isSelected ? theme.playerBlue : theme.gridLine.withOpacity(0.3),
            width: isSelected ? 2 : 1,
          ),
          boxShadow: isSelected ? [BoxShadow(color: theme.playerBlue.withOpacity(0.4), blurRadius: 12, spreadRadius: 2)] : [],
        ),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(icon, color: isSelected ? theme.playerBlue : theme.text.withOpacity(0.5), size: 24),
            const SizedBox(height: 6),
            Text(label, style: TextStyle(color: isSelected ? theme.text : theme.text.withOpacity(0.5), fontSize: 11, fontWeight: isSelected ? FontWeight.bold : FontWeight.normal)),
          ],
        ),
      ),
    );
  }
}

class _NeonSizeButton extends StatelessWidget {
  final String label;
  final bool isSelected;
  final ThemeColors theme;
  final VoidCallback onTap;

  const _NeonSizeButton({required this.label, required this.isSelected, required this.theme, required this.onTap});

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeInOut,
        width: 50,
        height: 50,
        decoration: BoxDecoration(
          shape: BoxShape.circle,
          color: isSelected ? theme.playerRed.withOpacity(0.2) : theme.text.withOpacity(0.05),
          border: Border.all(
            color: isSelected ? theme.playerRed : theme.gridLine.withOpacity(0.3),
            width: isSelected ? 2 : 1,
          ),
          boxShadow: isSelected ? [BoxShadow(color: theme.playerRed.withOpacity(0.4), blurRadius: 10, spreadRadius: 1.5)] : [],
        ),
        child: Center(
          child: Text(label, style: TextStyle(color: isSelected ? theme.text : theme.text.withOpacity(0.5), fontSize: 14, fontWeight: isSelected ? FontWeight.w900 : FontWeight.bold)),
        ),
      ),
    );
  }
}

class _NeonTimeSwitch extends StatelessWidget {
  final bool isTimeMode;
  final ThemeColors theme;
  final VoidCallback onTap;

  const _NeonTimeSwitch({required this.isTimeMode, required this.theme, required this.onTap});

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeInOut,
        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(20),
          color: isTimeMode ? Colors.amber.withOpacity(0.2) : theme.text.withOpacity(0.05),
          border: Border.all(
            color: isTimeMode ? Colors.amber : theme.gridLine.withOpacity(0.3),
            width: isTimeMode ? 2 : 1,
          ),
          boxShadow: isTimeMode ? [BoxShadow(color: Colors.amber.withOpacity(0.4), blurRadius: 12, spreadRadius: 2)] : [],
        ),
        child: Row(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(isTimeMode ? Icons.timer : Icons.timer_off, color: isTimeMode ? Colors.amber : theme.text.withOpacity(0.5), size: 28),
            const SizedBox(width: 12),
            Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisSize: MainAxisSize.min,
              children: [
                Text(
                    isTimeMode ? 'A TEMPO' : 'RELAX',
                    style: TextStyle(color: isTimeMode ? theme.text : theme.text.withOpacity(0.5), fontWeight: FontWeight.w900, fontSize: 14, letterSpacing: 1.5)
                ),
                Text(
                    isTimeMode ? '15 sec a mossa' : 'Nessun limite di tempo',
                    style: TextStyle(color: isTimeMode ? Colors.amber.shade200 : theme.text.withOpacity(0.4), fontSize: 11, fontWeight: FontWeight.bold)
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

// ---------------------------------------------------------------------------

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
  // Il raggio di partenza è 4 (Taglia M) come richiesto
  int _selectedRadius = 4;
  ArenaShape _selectedShape = ArenaShape.classic;
  bool _isTimeMode = false;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _checkPlayerName();
    });
    _checkClipboardForInvite();
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      _checkClipboardForInvite();
    }
  }

  void _checkPlayerName() {
    if (StorageService.instance.playerName.isEmpty) {
      _showNameDialog();
    }
  }

  void _showNameDialog() {
    final TextEditingController nameController = TextEditingController();
    showDialog(
      context: context,
      barrierDismissible: false,
      barrierColor: Colors.black.withOpacity(0.8),
      builder: (context) {
        final themeManager = context.watch<ThemeManager>();
        final theme = themeManager.currentColors;
        final themeType = themeManager.currentThemeType;

        Widget dialogContent;

        if (themeType == AppThemeType.cyberpunk) {
          dialogContent = _AnimatedCyberBorder(child: _buildDialogContent(context, theme, nameController));
        } else if (themeType == AppThemeType.wood) {
          dialogContent = Container(
            decoration: BoxDecoration(
              color: theme.background,
              borderRadius: BorderRadius.circular(25),
              border: Border.all(color: const Color(0xFF8B4513), width: 5),
              boxShadow: [
                BoxShadow(color: Colors.black.withOpacity(0.6), blurRadius: 15, offset: const Offset(0, 8)),
                const BoxShadow(color: Color(0xFFD2691E), blurRadius: 0, spreadRadius: 2, offset: Offset(0, 0)),
              ],
            ),
            padding: const EdgeInsets.all(5),
            child: _buildDialogContent(context, theme, nameController),
          );
        } else if (themeType == AppThemeType.doodle) {
          dialogContent = Container(
            decoration: BoxDecoration(
              color: theme.background,
              borderRadius: BorderRadius.circular(25),
              border: Border.all(color: theme.text, width: 3, style: BorderStyle.solid),
              boxShadow: [
                BoxShadow(color: theme.text.withOpacity(0.3), blurRadius: 0, offset: const Offset(4, 4)),
                BoxShadow(color: theme.text.withOpacity(0.3), blurRadius: 0, offset: const Offset(-2, -2)),
              ],
            ),
            padding: const EdgeInsets.all(4),
            child: _buildDialogContent(context, theme, nameController),
          );
        } else {
          dialogContent = Container(
            decoration: BoxDecoration(
                color: theme.background,
                borderRadius: BorderRadius.circular(25),
                border: Border.all(color: theme.playerBlue.withOpacity(0.5), width: 2),
                boxShadow: [
                  BoxShadow(color: theme.playerBlue.withOpacity(0.3), blurRadius: 20, spreadRadius: 5),
                ]
            ),
            child: _buildDialogContent(context, theme, nameController),
          );
        }

        return Dialog(backgroundColor: Colors.transparent, insetPadding: const EdgeInsets.all(20), child: dialogContent);
      },
    );
  }

  Widget _buildDialogContent(BuildContext context, ThemeColors theme, TextEditingController controller) {
    return SingleChildScrollView(
      child: Padding(
        padding: const EdgeInsets.symmetric(vertical: 30.0, horizontal: 25.0),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text('BENVENUTO IN TETRAQ!', style: TextStyle(color: theme.text, fontWeight: FontWeight.w900, fontSize: 24, letterSpacing: 1.5), textAlign: TextAlign.center),
            const SizedBox(height: 20),
            Text('Scegli il tuo nome da battaglia per sfidare i tuoi amici online.', style: TextStyle(color: theme.text.withOpacity(0.8), fontSize: 16), textAlign: TextAlign.center),
            const SizedBox(height: 40),
            TextField(
              controller: controller,
              textCapitalization: TextCapitalization.characters,
              textAlign: TextAlign.center,
              maxLength: 5,
              style: TextStyle(color: theme.text, fontSize: 28, fontWeight: FontWeight.bold, letterSpacing: 4),
              decoration: InputDecoration(
                hintText: 'NOME', hintStyle: TextStyle(color: theme.text.withOpacity(0.3), letterSpacing: 4),
                filled: true, fillColor: theme.text.withOpacity(0.05), counterText: "",
                enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: theme.gridLine.withOpacity(0.5), width: 2), borderRadius: BorderRadius.circular(15)),
                focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: theme.playerBlue, width: 3), borderRadius: BorderRadius.circular(15)),
              ),
            ),
            const SizedBox(height: 40),
            SizedBox(
              width: double.infinity, height: 55,
              child: ElevatedButton(
                style: ElevatedButton.styleFrom(
                  backgroundColor: theme.playerBlue, foregroundColor: Colors.white,
                  shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
                  elevation: 8, shadowColor: theme.playerBlue.withOpacity(0.5),
                ),
                onPressed: () {
                  final name = controller.text.trim();
                  if (name.isNotEmpty) {
                    StorageService.instance.savePlayerName(name);
                    Navigator.of(context).pop();
                    setState(() {});
                  }
                },
                child: const Text('SALVA E GIOCA', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, letterSpacing: 1.5)),
              ),
            ),
          ],
        ),
      ),
    );
  }

  Future<void> _checkClipboardForInvite() async {
    try {
      ClipboardData? data = await Clipboard.getData(Clipboard.kTextPlain);
      String? text = data?.text;

      if (text != null && text.contains("TetraQ") && text.contains("codice:")) {
        RegExp regExp = RegExp(r'codice:\s*([A-Z0-9]{5})', caseSensitive: false);
        Match? match = regExp.firstMatch(text);

        if (match != null) {
          String roomCode = match.group(1)!.toUpperCase();
          await Clipboard.setData(const ClipboardData(text: ''));
          if (mounted && ModalRoute.of(context)?.isCurrent == true) {
            _promptJoinRoom(roomCode);
          }
        }
      }
    } catch (e) {
      debugPrint("Errore lettura appunti: $e");
    }
  }

  void _promptJoinRoom(String roomCode) {
    showDialog(
        context: context,
        builder: (context) {
          final theme = context.watch<ThemeManager>().currentColors;
          return AlertDialog(
            backgroundColor: theme.background,
            title: Text("Invito Trovato!", style: TextStyle(color: theme.text, fontWeight: FontWeight.bold)),
            content: Text("Vuoi unirti alla stanza $roomCode?", style: TextStyle(color: theme.text)),
            actions: [
              TextButton(onPressed: () => Navigator.pop(context), child: const Text("No", style: TextStyle(color: Colors.red))),
              ElevatedButton(
                style: ElevatedButton.styleFrom(backgroundColor: theme.playerBlue),
                onPressed: () {
                  Navigator.of(context).pop();
                  Navigator.push(context, MaterialPageRoute(builder: (_) => LobbyScreen(initialRoomCode: roomCode, selectedRadius: _selectedRadius, selectedShape: _selectedShape)));
                },
                child: const Text("Unisciti", style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold)),
              ),
            ],
          );
        }
    );
  }

  @override
  Widget build(BuildContext context) {
    // --- RIPRISTINATO: Forza la modalità a schermo intero e l'orientamento verticale ---
    SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
      DeviceOrientation.portraitDown,
    ]);

    final themeManager = context.watch<ThemeManager>();
    final themeType = themeManager.currentThemeType;
    final theme = themeManager.currentColors;

    String? bgImage;
    if (themeType == AppThemeType.wood) bgImage = 'assets/images/wood_bg.jpg';
    if (themeType == AppThemeType.doodle) bgImage = 'assets/images/doodle_bg.jpg';

    int wins = StorageService.instance.wins;
    int losses = StorageService.instance.losses;
    String playerName = StorageService.instance.playerName;
    if (playerName.isEmpty) playerName = "GUEST";

    Widget uiContent = SafeArea(
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Row(
                  children: [
                    CircleAvatar(
                      backgroundColor: theme.playerBlue.withOpacity(0.2),
                      radius: 25,
                      child: Icon(Icons.person, color: theme.playerBlue, size: 30),
                    ),
                    const SizedBox(width: 10),
                    Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text("BENVENUTO,", style: TextStyle(color: theme.text.withOpacity(0.5), fontSize: 10, fontWeight: FontWeight.bold, letterSpacing: 1.2)),
                        Text(playerName, style: TextStyle(color: theme.text, fontSize: 18, fontWeight: FontWeight.w900, letterSpacing: 1.5)),
                      ],
                    ),
                  ],
                ),
                Container(
                  padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
                  decoration: BoxDecoration(
                    color: theme.text.withOpacity(0.05),
                    borderRadius: BorderRadius.circular(20),
                    border: Border.all(color: theme.gridLine.withOpacity(0.2)),
                  ),
                  child: Row(
                    children: [
                      Icon(Icons.emoji_events, color: Colors.amber.shade600, size: 18),
                      const SizedBox(width: 4),
                      Text("$wins", style: TextStyle(color: theme.text, fontWeight: FontWeight.bold)),
                      const SizedBox(width: 10),
                      Icon(Icons.sentiment_very_dissatisfied, color: theme.playerRed.withOpacity(0.8), size: 18),
                      const SizedBox(width: 4),
                      Text("$losses", style: TextStyle(color: theme.text, fontWeight: FontWeight.bold)),
                    ],
                  ),
                )
              ],
            ),

            const SizedBox(height: 20),

            Center(
              child: Column(
                children: [
                  Text(
                      "TETRAQ",
                      style: TextStyle(
                          fontSize: 50,
                          fontWeight: FontWeight.w900,
                          color: theme.text,
                          letterSpacing: 8,
                          shadows: [Shadow(color: Colors.black.withOpacity(0.3), offset: const Offset(2, 4), blurRadius: 4)]
                      )
                  ),
                  Text(
                      "THE ROMBUS PUZZLE",
                      style: TextStyle(
                        fontSize: 12,
                        fontWeight: FontWeight.bold,
                        color: theme.gridLine,
                        letterSpacing: 3,
                      )
                  ),
                ],
              ),
            ),

            const SizedBox(height: 20),

            // --- PANNELLO IMPOSTAZIONI ARENA CON LOGICA GRANDEZZA CORRETTA ---
            Container(
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                color: theme.background.withOpacity(0.8),
                borderRadius: BorderRadius.circular(20),
                border: Border.all(color: theme.gridLine.withOpacity(0.3)),
                boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.2), blurRadius: 10, offset: const Offset(0, 4))],
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  // 1. SEZIONE FORMA
                  Text("FORMA DELL'ARENA", style: TextStyle(fontSize: 11, fontWeight: FontWeight.w900, color: theme.text.withOpacity(0.5), letterSpacing: 1.5)),
                  const SizedBox(height: 10),
                  Wrap(
                    spacing: 10,
                    runSpacing: 10,
                    alignment: WrapAlignment.center,
                    children: [
                      _NeonShapeButton(
                        icon: Icons.diamond_outlined, label: 'Rombo', isSelected: _selectedShape == ArenaShape.classic, theme: theme,
                        onTap: () => setState(() => _selectedShape = ArenaShape.classic),
                      ),
                      _NeonShapeButton(
                        icon: Icons.add, label: 'Croce', isSelected: _selectedShape == ArenaShape.cross, theme: theme,
                        onTap: () => setState(() => _selectedShape = ArenaShape.cross),
                      ),
                      _NeonShapeButton(
                        icon: Icons.donut_large, label: 'Buco Nero', isSelected: _selectedShape == ArenaShape.donut, theme: theme,
                        onTap: () => setState(() => _selectedShape = ArenaShape.donut),
                      ),
                      _NeonShapeButton(
                        icon: Icons.hourglass_bottom, label: 'Clessidra', isSelected: _selectedShape == ArenaShape.hourglass, theme: theme,
                        onTap: () => setState(() => _selectedShape = ArenaShape.hourglass),
                      ),
                    ],
                  ),

                  const SizedBox(height: 20),
                  Divider(color: theme.gridLine.withOpacity(0.2), height: 1),
                  const SizedBox(height: 20),

                  // 2. SEZIONE TAGLIA (SCALA CORRETTA DA 3 A 6)
                  Text("GRANDEZZA", style: TextStyle(fontSize: 11, fontWeight: FontWeight.w900, color: theme.text.withOpacity(0.5), letterSpacing: 1.5)),
                  const SizedBox(height: 10),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      _NeonSizeButton(label: 'S', isSelected: _selectedRadius == 3, theme: theme, onTap: () => setState(() => _selectedRadius = 3)),
                      _NeonSizeButton(label: 'M', isSelected: _selectedRadius == 4, theme: theme, onTap: () => setState(() => _selectedRadius = 4)),
                      _NeonSizeButton(label: 'L', isSelected: _selectedRadius == 5, theme: theme, onTap: () => setState(() => _selectedRadius = 5)),
                      _NeonSizeButton(label: 'MAX', isSelected: _selectedRadius == 6, theme: theme, onTap: () => setState(() => _selectedRadius = 6)),
                    ],
                  ),

                  const SizedBox(height: 20),
                  Divider(color: theme.gridLine.withOpacity(0.2), height: 1),
                  const SizedBox(height: 20),

                  // 3. SEZIONE TEMPO
                  Text("MODALITÀ DI GIOCO", style: TextStyle(fontSize: 11, fontWeight: FontWeight.w900, color: theme.text.withOpacity(0.5), letterSpacing: 1.5)),
                  const SizedBox(height: 10),
                  _NeonTimeSwitch(
                    isTimeMode: _isTimeMode,
                    theme: theme,
                    onTap: () => setState(() => _isTimeMode = !_isTimeMode),
                  ),
                ],
              ),
            ),
            // --------------------------------------------------------------

            const SizedBox(height: 20),

            Expanded(
              child: GridView.count(
                crossAxisCount: 2,
                crossAxisSpacing: 15,
                mainAxisSpacing: 15,
                childAspectRatio: 1.1,
                physics: const BouncingScrollPhysics(),
                children: [
                  _FeatureCard(
                    title: "ONLINE", subtitle: "Sfida il mondo", icon: Icons.public, color: theme.playerBlue, theme: theme, isFeatured: true,
                    onTap: () {
                      Navigator.push(context, MaterialPageRoute(builder: (_) => LobbyScreen(selectedRadius: _selectedRadius, selectedShape: _selectedShape)));
                    },
                  ),
                  _FeatureCard(
                    title: "VS CPU", subtitle: "Allenati", icon: Icons.smart_toy, color: Colors.purple.shade400, theme: theme,
                    onTap: () async {
                      context.read<GameController>().startNewGame(_selectedRadius, vsCPU: true, shape: _selectedShape);
                      await Navigator.push(context, MaterialPageRoute(builder: (_) => const GameScreen()));
                      setState(() {});
                    },
                  ),
                  _FeatureCard(
                    title: "LOCALE", subtitle: "Stesso schermo", icon: Icons.people_alt, color: theme.playerRed, theme: theme,
                    onTap: () {
                      context.read<GameController>().startNewGame(_selectedRadius, vsCPU: false, shape: _selectedShape);
                      Navigator.push(context, MaterialPageRoute(builder: (_) => const GameScreen()));
                    },
                  ),
                  Column(
                    children: [
                      Expanded(child: _MiniCard(title: "STORICO", icon: Icons.history, color: Colors.orange.shade400, theme: theme, onTap: () => Navigator.push(context, MaterialPageRoute(builder: (_) => const HistoryScreen())))),
                      const SizedBox(height: 15),
                      Expanded(child: _MiniCard(title: "TEMI", icon: Icons.palette, color: Colors.teal.shade400, theme: theme, onTap: () => Navigator.push(context, MaterialPageRoute(builder: (_) => const SettingsScreen())))),
                    ],
                  )
                ],
              ),
            ),
          ],
        ),
      ),
    );

    return Scaffold(
      backgroundColor: bgImage != null ? Colors.transparent : theme.background,
      body: Container(
        decoration: bgImage != null ? BoxDecoration(image: DecorationImage(image: AssetImage(bgImage), fit: BoxFit.cover)) : null,
        child: bgImage != null ? BackdropFilter(filter: ImageFilter.blur(sigmaX: 3.5, sigmaY: 3.5), child: Container(color: themeType == AppThemeType.doodle ? Colors.white.withOpacity(0.1) : Colors.transparent, child: uiContent)) : uiContent,
      ),
    );
  }
}

class _FeatureCard extends StatelessWidget {
  final String title;
  final String subtitle;
  final IconData icon;
  final Color color;
  final ThemeColors theme;
  final VoidCallback onTap;
  final bool isFeatured;

  const _FeatureCard({required this.title, required this.subtitle, required this.icon, required this.color, required this.theme, required this.onTap, this.isFeatured = false});

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: Container(
        decoration: BoxDecoration(
            color: isFeatured ? color : theme.background,
            borderRadius: BorderRadius.circular(25),
            border: Border.all(color: isFeatured ? Colors.transparent : color.withOpacity(0.5), width: 2),
            boxShadow: [BoxShadow(color: color.withOpacity(isFeatured ? 0.4 : 0.1), offset: const Offset(0, 8), blurRadius: 15)]
        ),
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Container(
                padding: const EdgeInsets.all(10),
                decoration: BoxDecoration(color: isFeatured ? Colors.white.withOpacity(0.2) : color.withOpacity(0.1), shape: BoxShape.circle),
                child: Icon(icon, color: isFeatured ? Colors.white : color, size: 32),
              ),
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(title, style: TextStyle(color: isFeatured ? Colors.white : theme.text, fontSize: 20, fontWeight: FontWeight.w900)),
                  Text(subtitle, style: TextStyle(color: isFeatured ? Colors.white.withOpacity(0.8) : theme.text.withOpacity(0.5), fontSize: 12, fontWeight: FontWeight.bold)),
                ],
              )
            ],
          ),
        ),
      ),
    );
  }
}

class _MiniCard extends StatelessWidget {
  final String title;
  final IconData icon;
  final Color color;
  final ThemeColors theme;
  final VoidCallback onTap;

  const _MiniCard({required this.title, required this.icon, required this.color, required this.theme, required this.onTap});

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: Container(
        decoration: BoxDecoration(
            color: theme.background,
            borderRadius: BorderRadius.circular(20),
            border: Border.all(color: color.withOpacity(0.5), width: 1.5),
            boxShadow: [BoxShadow(color: color.withOpacity(0.1), blurRadius: 10, offset: const Offset(0, 5))]
        ),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(icon, color: color, size: 24),
            const SizedBox(width: 8),
            Text(title, style: TextStyle(color: theme.text, fontWeight: FontWeight.bold, fontSize: 14)),
          ],
        ),
      ),
    );
  }
}

class _AnimatedCyberBorder extends StatefulWidget {
  final Widget child;
  const _AnimatedCyberBorder({required this.child});
  @override
  State<_AnimatedCyberBorder> createState() => _AnimatedCyberBorderState();
}

class _AnimatedCyberBorderState extends State<_AnimatedCyberBorder> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  @override
  void initState() { super.initState(); _controller = AnimationController(vsync: this, duration: const Duration(seconds: 3))..repeat(); }
  @override
  void dispose() { _controller.dispose(); super.dispose(); }
  @override
  Widget build(BuildContext context) {
    final theme = context.watch<ThemeManager>().currentColors;
    return AnimatedBuilder(
      animation: _controller,
      builder: (context, child) {
        return CustomPaint(
          painter: _CyberBorderPainter(animationValue: _controller.value, color1: theme.playerBlue, color2: theme.playerRed),
          child: Container(
            decoration: BoxDecoration(color: theme.background.withOpacity(0.9), borderRadius: BorderRadius.circular(25), boxShadow: [BoxShadow(color: theme.playerBlue.withOpacity(0.3), blurRadius: 25, spreadRadius: 2)]),
            padding: const EdgeInsets.all(3),
            child: widget.child,
          ),
        );
      },
      child: widget.child,
    );
  }
}

class _CyberBorderPainter extends CustomPainter {
  final double animationValue;
  final Color color1;
  final Color color2;

  _CyberBorderPainter({required this.animationValue, required this.color1, required this.color2});

  @override
  void paint(Canvas canvas, Size size) {
    final rect = Offset.zero & size;
    final RRect rrect = RRect.fromRectAndRadius(rect, const Radius.circular(25));
    final Paint paint = Paint()
      ..shader = SweepGradient(colors: [color1, color2, color1, color2, color1], stops: const [0.0, 0.25, 0.5, 0.75, 1.0], transform: GradientRotation(animationValue * 2 * math.pi)).createShader(rect)
      ..style = PaintingStyle.stroke
      ..strokeWidth = 4.0
      ..maskFilter = const MaskFilter.blur(BlurStyle.solid, 4);
    canvas.drawRRect(rrect, paint);
  }

  @override
  bool shouldRepaint(covariant _CyberBorderPainter oldDelegate) => oldDelegate.animationValue != animationValue;
}
// ===========================================================================
// FILE: lib/ui/multiplayer/lobby_screen.dart
// ===========================================================================

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import '../../core/theme_manager.dart';
import '../../models/game_board.dart'; // <-- IMPORTANTE
import '../../services/multiplayer_service.dart';
import '../../services/storage_service.dart';
import '../game/game_screen.dart';
import '../../logic/game_controller.dart';

class LobbyScreen extends StatefulWidget {
  final String? initialRoomCode;
  final int selectedRadius;
  final ArenaShape selectedShape; // <-- RICEVIAMO LA FORMA

  const LobbyScreen({super.key, this.initialRoomCode, this.selectedRadius = 2, this.selectedShape = ArenaShape.classic});

  @override
  State<LobbyScreen> createState() => _LobbyScreenState();
}

class _LobbyScreenState extends State<LobbyScreen> {
  final MultiplayerService _multiplayerService = MultiplayerService();
  late TextEditingController _codeController;

  bool _isLoading = false;
  String? _myRoomCode;
  String _playerName = '';

  @override
  void initState() {
    super.initState();
    _codeController = TextEditingController();
    _playerName = StorageService.instance.playerName;

    if (widget.initialRoomCode != null && widget.initialRoomCode!.isNotEmpty) {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        setState(() { _codeController.text = widget.initialRoomCode!; });
      });
    }
  }

  @override
  void dispose() { _codeController.dispose(); super.dispose(); }

  Future<void> _createRoom() async {
    if (_isLoading) return;
    setState(() => _isLoading = true);

    try {
      int radius = widget.selectedRadius;
      // PASSIAMO ANCHE IL NOME DELLA FORMA!
      String code = await _multiplayerService.createGameRoom(radius, _playerName, widget.selectedShape.name);

      if (!mounted) return;
      setState(() { _myRoomCode = code; _isLoading = false; });

      _multiplayerService.shareInviteLink(code);
      _showWaitingDialog(code);
    } catch (e) {
      if (mounted) { setState(() => _isLoading = false); _showError("Errore durante la creazione della partita."); }
    }
  }

  Future<void> _joinRoom() async {
    if (_isLoading) return;
    FocusScope.of(context).unfocus();

    String code = _codeController.text.trim().toUpperCase();
    if (code.isEmpty || code.length != 5) { _showError("Inserisci un codice valido di 5 caratteri."); return; }

    setState(() => _isLoading = true);

    try {
      Map<String, dynamic>? roomData = await _multiplayerService.joinGameRoom(code, _playerName);

      if (!mounted) return;
      setState(() => _isLoading = false);

      if (roomData != null) {
        ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Stanza trovata! Partita in avvio..."), backgroundColor: Colors.green));

        int hostRadius = roomData['radius'] ?? 2;

        // LEGGIAMO LA FORMA DELL'HOST
        String shapeStr = roomData['shape'] ?? 'classic';
        ArenaShape hostShape = ArenaShape.values.firstWhere((e) => e.name == shapeStr, orElse: () => ArenaShape.classic);

        context.read<GameController>().startNewGame(hostRadius, isOnline: true, roomCode: code, isHost: false, shape: hostShape);
        Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => const GameScreen()));
      } else {
        _showError("Stanza non trovata, piena o partita già iniziata.");
      }
    } catch (e) {
      if (mounted) { setState(() => _isLoading = false); _showError("Errore di connessione: $e"); }
    }
  }

  void _showError(String message) { ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(message, style: const TextStyle(color: Colors.white)), backgroundColor: Colors.red)); }

  void _showWaitingDialog(String code) {
    showDialog(
        context: context,
        barrierDismissible: false,
        builder: (context) {
          final theme = context.watch<ThemeManager>().currentColors;

          return StreamBuilder<DocumentSnapshot>(
            stream: _multiplayerService.listenToRoom(code),
            builder: (context, snapshot) {
              if (snapshot.hasData && snapshot.data!.exists) {
                var data = snapshot.data!.data() as Map<String, dynamic>;
                if (data['status'] == 'playing') {
                  WidgetsBinding.instance.addPostFrameCallback((_) {
                    Navigator.pop(context);
                    int radius = widget.selectedRadius;
                    // AVVIAMO IL GIOCO CON LA FORMA SCELTA DALL'HOST!
                    context.read<GameController>().startNewGame(radius, isOnline: true, roomCode: code, isHost: true, shape: widget.selectedShape);
                    Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => const GameScreen()));
                  });
                }
              }

              return AlertDialog(
                backgroundColor: theme.background,
                shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
                title: Text("In attesa...", textAlign: TextAlign.center, style: TextStyle(color: theme.text, fontWeight: FontWeight.bold)),
                content: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    const CircularProgressIndicator(), const SizedBox(height: 25),
                    Text("CODICE STANZA", style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: theme.text.withOpacity(0.6), letterSpacing: 2)),
                    Text(code, style: TextStyle(fontSize: 40, fontWeight: FontWeight.w900, color: theme.playerRed, letterSpacing: 8)),
                    const SizedBox(height: 20),
                    Container(
                      padding: const EdgeInsets.all(16),
                      decoration: BoxDecoration(color: theme.text.withOpacity(0.05), borderRadius: BorderRadius.circular(15), border: Border.all(color: theme.playerBlue.withOpacity(0.3), width: 1.5)),
                      child: Column(
                        children: [
                          Icon(Icons.auto_awesome, color: theme.playerBlue, size: 28), const SizedBox(height: 10),
                          Text("Condividi l'invito con un amico.", textAlign: TextAlign.center, style: TextStyle(color: theme.text, fontWeight: FontWeight.bold, fontSize: 14)),
                          const SizedBox(height: 5),
                          Text("Gli basterà copiare il messaggio e aprire l'app.", textAlign: TextAlign.center, style: TextStyle(color: theme.text.withOpacity(0.8), fontSize: 13, height: 1.4)),
                        ],
                      ),
                    ),
                  ],
                ),
                actionsAlignment: MainAxisAlignment.center,
                actions: [
                  TextButton(
                    onPressed: () { FirebaseFirestore.instance.collection('games').doc(code).delete(); Navigator.pop(context); },
                    child: const Text("ANNULLA", style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold, fontSize: 16, letterSpacing: 1.5)),
                  ),
                ],
              );
            },
          );
        }
    );
  }

  @override
  Widget build(BuildContext context) {
    final theme = context.watch<ThemeManager>().currentColors;

    return Scaffold(
      backgroundColor: theme.background,
      appBar: AppBar(title: Text("Multiplayer Online", style: TextStyle(color: theme.text, fontWeight: FontWeight.bold)), backgroundColor: Colors.transparent, elevation: 0, iconTheme: IconThemeData(color: theme.text)),
      body: _isLoading ? Center(child: CircularProgressIndicator(color: theme.playerRed)) : Center(
        child: SingleChildScrollView(
          padding: const EdgeInsets.all(24.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              Icon(Icons.wifi, size: 80, color: theme.playerBlue), const SizedBox(height: 10),
              Text("Giocatore: $_playerName", textAlign: TextAlign.center, style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: theme.playerRed)),
              const SizedBox(height: 40),
              SizedBox(height: 60, child: ElevatedButton(style: ElevatedButton.styleFrom(backgroundColor: theme.playerRed, foregroundColor: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15))), onPressed: _createRoom, child: const Text("CREA PARTITA", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, letterSpacing: 2)))),
              const SizedBox(height: 40),
              TextField(
                controller: _codeController, textCapitalization: TextCapitalization.characters, textAlign: TextAlign.center, maxLength: 5,
                style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold, color: theme.text, letterSpacing: 8),
                decoration: InputDecoration(hintText: "CODICE", hintStyle: TextStyle(color: theme.text.withOpacity(0.3)), enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: theme.text.withOpacity(0.3), width: 2), borderRadius: BorderRadius.circular(15)), focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: theme.playerBlue, width: 3), borderRadius: BorderRadius.circular(15))),
              ),
              const SizedBox(height: 16),
              SizedBox(height: 60, child: ElevatedButton(style: ElevatedButton.styleFrom(backgroundColor: theme.playerBlue, foregroundColor: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15))), onPressed: _joinRoom, child: const Text("UNISCITI", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, letterSpacing: 2)))),
            ],
          ),
        ),
      ),
    );
  }
}
// ===========================================================================
// FILE: lib/ui/settings/settings_screen.dart
// ===========================================================================

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../core/theme_manager.dart';
import '../../core/app_colors.dart';

class SettingsScreen extends StatelessWidget {
  const SettingsScreen({super.key});

  @override
  Widget build(BuildContext context) {
    final themeManager = context.watch<ThemeManager>();
    final theme = themeManager.currentColors;

    return Scaffold(
      backgroundColor: theme.background,
      appBar: AppBar(
        title: Text("SELEZIONA TEMA", style: TextStyle(fontWeight: FontWeight.bold, color: theme.text)),
        backgroundColor: Colors.transparent,
        elevation: 0,
        iconTheme: IconThemeData(color: theme.text),
      ),
      body: ListView(
        padding: const EdgeInsets.all(20),
        children: [
          _ThemeCard(
            title: "Minimal",
            subtitle: "Linee pulite, sfondo chiaro",
            type: AppThemeType.minimal,
            previewColors: AppColors.minimal,
          ),
          const SizedBox(height: 15),
          _ThemeCard(
            title: "Quaderno (Doodle)",
            subtitle: "Sfondo a quadretti, tratto a penna",
            type: AppThemeType.doodle,
            previewColors: AppColors.doodle,
          ),
          const SizedBox(height: 15),
          _ThemeCard(
            title: "Cyberpunk",
            subtitle: "Nero profondo, luci al neon",
            type: AppThemeType.cyberpunk,
            previewColors: AppColors.cyberpunk,
          ),
          const SizedBox(height: 15),
          // --- NUOVA CARD TEMA LEGNO ---
          _ThemeCard(
            title: "Legno & Fiammiferi",
            subtitle: "Tavolo di legno, linee come fiammiferi",
            type: AppThemeType.wood,
            previewColors: AppColors.wood,
          ),
          // -----------------------------
        ],
      ),
    );
  }
}

class _ThemeCard extends StatelessWidget {
  final String title;
  final String subtitle;
  final AppThemeType type;
  final ThemeColors previewColors;

  const _ThemeCard({required this.title, required this.subtitle, required this.type, required this.previewColors});

  @override
  Widget build(BuildContext context) {
    final themeManager = context.watch<ThemeManager>();
    bool isSelected = themeManager.currentThemeType == type;

    return GestureDetector(
      onTap: () => themeManager.setTheme(type),
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 300),
        padding: const EdgeInsets.all(20),
        decoration: BoxDecoration(
          color: previewColors.background,
          borderRadius: BorderRadius.circular(20),
          border: Border.all(
            color: isSelected ? previewColors.playerBlue : previewColors.gridLine.withOpacity(0.5),
            width: isSelected ? 4 : 2,
          ),
          boxShadow: isSelected ? [BoxShadow(color: previewColors.playerBlue.withOpacity(0.4), blurRadius: 10, spreadRadius: 2)] : [],
        ),
        child: Row(
          children: [
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(title, style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold, color: previewColors.text)),
                  Text(subtitle, style: TextStyle(fontSize: 14, color: previewColors.text.withOpacity(0.7))),
                ],
              ),
            ),
            Container(width: 20, height: 20, decoration: BoxDecoration(color: previewColors.playerRed, shape: BoxShape.circle)),
            const SizedBox(width: 10),
            Container(width: 20, height: 20, decoration: BoxDecoration(color: previewColors.playerBlue, shape: BoxShape.circle)),
          ],
        ),
      ),
    );
  }
}
// ===========================================================================
// FILE: lib/widgets/custom_button.dart
// ===========================================================================


// ===========================================================================
// FILE: lib/widgets/custom_settings_button.dart
// ===========================================================================

import 'package:flutter/material.dart';
import '../theme/app_colors.dart';

// Widget per i pulsanti di selezione della forma dell'arena
class NeonShapeButton extends StatelessWidget {
  final IconData icon;
  final String label;
  final bool isSelected;
  final VoidCallback onTap;
  final ShapeBorder shape; // La forma geometrica del pulsante

  const NeonShapeButton({
    super.key,
    required this.icon,
    required this.label,
    required this.isSelected,
    required this.onTap,
    this.shape = const RoundedRectangleBorder( // Forma di default
        borderRadius: BorderRadius.all(Radius.circular(12.0))),
  });

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeInOut,
        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
        decoration: ShapeDecoration(
          shape: shape,
          color: isSelected
              ? AppColors.neonGreen.withOpacity(0.2) // Sfondo luminoso se selezionato
              : AppColors.surface.withOpacity(0.5), // Sfondo più scuro se non selezionato
          shadows: isSelected
              ? [ // Bagliore intenso se selezionato
            BoxShadow(
              color: AppColors.neonGreen.withOpacity(0.6),
              blurRadius: 12.0,
              spreadRadius: 2.0,
            ),
          ]
              : [],
        ),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(
              icon,
              color: isSelected ? AppColors.neonGreen : AppColors.textSecondary,
              size: 28,
            ),
            const SizedBox(height: 4),
            Text(
              label,
              style: TextStyle(
                color: isSelected ? AppColors.textPrimary : AppColors.textSecondary,
                fontSize: 12,
                fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

// Widget per i pulsanti di selezione della taglia dell'arena
class NeonSizeButton extends StatelessWidget {
  final String label;
  final bool isSelected;
  final VoidCallback onTap;

  const NeonSizeButton({
    super.key,
    required this.label,
    required this.isSelected,
    required this.onTap,
  });

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeInOut,
        width: 50,
        height: 50,
        decoration: BoxDecoration(
          shape: BoxShape.circle, // Forma circolare
          color: isSelected
              ? AppColors.neonBlue.withOpacity(0.2)
              : AppColors.surface.withOpacity(0.5),
          border: Border.all(
            color: isSelected ? AppColors.neonBlue : AppColors.surfaceLight,
            width: 2.0,
          ),
          shadows: isSelected
              ? [
            BoxShadow(
              color: AppColors.neonBlue.withOpacity(0.6),
              blurRadius: 10.0,
              spreadRadius: 1.5,
            ),
          ]
              : [],
        ),
        child: Center(
          child: Text(
            label,
            style: TextStyle(
              color: isSelected ? AppColors.textPrimary : AppColors.textSecondary,
              fontSize: 16,
              fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
            ),
          ),
        ),
      ),
    );
  }
}

// Widget per l'interruttore della modalità tempo (Clessidra)
class NeonTimeSwitch extends StatelessWidget {
  final bool isTimeMode;
  final VoidCallback onTap;

  const NeonTimeSwitch({
    super.key,
    required this.isTimeMode,
    required this.onTap,
  });

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeInOut,
        padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(30.0), // Forma arrotondata per lo switch
          color: isTimeMode
              ? AppColors.neonGreen.withOpacity(0.2)
              : AppColors.surface.withOpacity(0.5),
          border: Border.all(
            color: isTimeMode ? AppColors.neonGreen : AppColors.surfaceLight,
            width: 2.0,
          ),
          shadows: isTimeMode
              ? [
            BoxShadow(
              color: AppColors.neonGreen.withOpacity(0.6),
              blurRadius: 12.0,
              spreadRadius: 2.0,
            ),
          ]
              : [],
        ),
        child: Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(
              Icons.hourglass_empty, // Icona clessidra
              color: isTimeMode ? AppColors.neonGreen : AppColors.textSecondary,
            ),
            const SizedBox(width: 8),
            Text(
              isTimeMode ? 'A TEMPO' : 'SENZA TEMPO',
              style: TextStyle(
                color: isTimeMode ? AppColors.textPrimary : AppColors.textSecondary,
                fontWeight: isTimeMode ? FontWeight.bold : FontWeight.normal,
              ),
            ),
          ],
        ),
      ),
    );
  }
}
// ===========================================================================
// FILE: lib/widgets/game_over_dialog.dart
// ===========================================================================

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../logic/game_controller.dart';
import '../core/theme_manager.dart';
import '../core/app_colors.dart';

class GameOverDialog extends StatelessWidget {
  const GameOverDialog({super.key});

  @override
  Widget build(BuildContext context) {
    final game = context.read<GameController>();
    final themeManager = context.read<ThemeManager>();
    final theme = themeManager.currentColors;
    final themeType = themeManager.currentThemeType;

    int red = game.board.scoreRed;
    int blue = game.board.scoreBlue;

    bool playerBeatCPU = game.isVsCPU && red > blue;

    // --- LOGICA NOMI ---
    String nameRed = "ROSSO";
    String nameBlue = themeType == AppThemeType.cyberpunk ? "VERDE" : "BLU";

    if (game.isOnline) {
      nameRed = game.onlineHostName.toUpperCase();
      nameBlue = game.onlineGuestName.toUpperCase();
    } else if (game.isVsCPU) {
      nameRed = "TU";
      nameBlue = "CPU";
    }

    // --- DETERMINA IL VINCITORE ---
    String winnerText = "";
    Color winnerColor = theme.text;

    if (red > blue) {
      winnerText = "VINCE $nameRed!";
      winnerColor = theme.playerRed;
    } else if (blue > red) {
      winnerText = "VINCE $nameBlue!";
      winnerColor = theme.playerBlue;
    } else {
      winnerText = "PAREGGIO!";
      winnerColor = theme.text;
    }

    return AlertDialog(
      backgroundColor: theme.background,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(20),
        side: BorderSide(color: winnerColor.withOpacity(0.5), width: 2),
      ),
      title: Text("FINE PARTITA", textAlign: TextAlign.center, style: TextStyle(color: theme.text, fontWeight: FontWeight.bold, fontSize: 22)),
      content: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Text(winnerText, textAlign: TextAlign.center, style: TextStyle(fontSize: 26, fontWeight: FontWeight.w900, color: winnerColor)),
          const SizedBox(height: 20),
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
            decoration: BoxDecoration(
              color: theme.text.withOpacity(0.05),
              borderRadius: BorderRadius.circular(15),
            ),
            child: Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                Text("$nameRed: $red", style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: theme.playerRed)),
                Text("  -  ", style: TextStyle(fontSize: 18, color: theme.text)),
                Text("$nameBlue: $blue", style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: theme.playerBlue)),
              ],
            ),
          ),

          if (game.isVsCPU) ...[
            const SizedBox(height: 15),
            Text("Difficoltà CPU: Livello ${game.cpuLevel}", style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: theme.text.withOpacity(0.7))),
          ]
        ],
      ),
      actionsPadding: const EdgeInsets.only(left: 20, right: 20, bottom: 20, top: 10),
      actionsAlignment: MainAxisAlignment.center,
      actions: [
        Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            if (playerBeatCPU)
              ElevatedButton(
                style: ElevatedButton.styleFrom(
                  backgroundColor: winnerColor,
                  foregroundColor: Colors.white,
                  padding: const EdgeInsets.symmetric(vertical: 15),
                  shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
                  elevation: 5,
                ),
                onPressed: () {
                  Navigator.pop(context);
                  game.increaseLevelAndRestart();
                },
                child: const Text("PROSSIMO LIVELLO ➔", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16)),
              )
            else if (game.isOnline)
              ElevatedButton(
                style: ElevatedButton.styleFrom(
                  backgroundColor: winnerColor == theme.text ? theme.playerBlue : winnerColor,
                  foregroundColor: Colors.white,
                  padding: const EdgeInsets.symmetric(vertical: 15),
                  shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
                  elevation: 5,
                ),
                onPressed: () {
                  Navigator.pop(context);
                  if (game.board.isGameOver) {
                    game.requestRematch();
                  }
                },
                child: const Text("RIGIOCA ONLINE", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16, letterSpacing: 1.5)),
              )
            else
              ElevatedButton(
                style: ElevatedButton.styleFrom(
                  backgroundColor: winnerColor == theme.text ? theme.playerBlue : winnerColor,
                  foregroundColor: Colors.white,
                  padding: const EdgeInsets.symmetric(vertical: 15),
                  shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
                  elevation: 5,
                ),
                onPressed: () {
                  Navigator.pop(context);
                  game.startNewGame(game.board.radius, vsCPU: game.isVsCPU);
                },
                child: const Text("RIGIOCA", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16, letterSpacing: 2)),
              ),

            const SizedBox(height: 12),

            OutlinedButton(
              style: OutlinedButton.styleFrom(
                foregroundColor: theme.text,
                side: BorderSide(color: theme.text.withOpacity(0.3), width: 2),
                padding: const EdgeInsets.symmetric(vertical: 15),
                shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
              ),
              onPressed: () {
                if (game.isOnline) {
                  game.disconnectOnlineGame();
                }
                Navigator.pop(context);
                Navigator.pop(context);
              },
              child: Text("TORNA AL MENU", style: TextStyle(fontWeight: FontWeight.bold, color: theme.text, fontSize: 14, letterSpacing: 1.5)),
            ),
          ],
        )
      ],
    );
  }
}