=== FLUTTER PROJECT BACKUP ===

=== PROJECT STRUCTURE (LIB & ASSETS) ===
assets/.DS_Store
assets/audio/.DS_Store
assets/audio/bgm/8-bit_Prowler.mp3
assets/audio/bgm/Cyber_Dystopia.mp3
assets/audio/bgm/Grimorio_Astral.mp3
assets/audio/bgm/Legno_Canopy.mp3
assets/audio/bgm/Music_Loop.mp3
assets/audio/bgm/Quad_Dreams.mp3
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/arcade.jpg
assets/images/cyber_bg.jpg
assets/images/doodle_bg.jpg
assets/images/doodle_bg_riserva.jpg
assets/images/egizi_bg.jpg
assets/images/grimorio copia.jpg
assets/images/grimorio.jpg
assets/images/icona_big.jpeg
assets/images/music_bg.jpg
assets/images/sfondo_temi.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_de.arb
lib/l10n/app_en.arb
lib/l10n/app_es.arb
lib/l10n/app_fr.arb
lib/l10n/app_it.arb
lib/l10n/app_localizations.dart
lib/l10n/app_localizations_de.dart
lib/l10n/app_localizations_en.dart
lib/l10n/app_localizations_es.dart
lib/l10n/app_localizations_fr.dart
lib/l10n/app_localizations_it.dart
lib/l10n/app_localizations_pt.dart
lib/l10n/app_localizations_ru.dart
lib/l10n/app_localizations_zh.dart
lib/l10n/app_pt.arb
lib/l10n/app_ru.arb
lib/l10n/app_zh.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/.DS_Store
lib/ui/admin/admin_screen.dart
lib/ui/game/board_painter.dart
lib/ui/game/game_screen.dart
lib/ui/game/score_board.dart
lib/ui/home/dialog.dart
lib/ui/home/history_screen.dart
lib/ui/home/home_modals.dart
lib/ui/home/home_screen.dart
lib/ui/multiplayer/lobby_screen.dart
lib/ui/multiplayer/lobby_widgets.dart
lib/ui/settings/settings_screen.dart
lib/widgets/custom_button.dart
lib/widgets/custom_settings_button.dart
lib/widgets/cyber_border.dart
lib/widgets/game_over_dialog.dart
lib/widgets/home_buttons.dart
lib/widgets/music_theme_widgets.dart
lib/widgets/painters.dart

=== pubspec.yaml ===
name: tetraq
description: A new Flutter project.
publish_to: 'none'
version: 1.1.5+7
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
  firebase_auth: ^6.1.4       # <--- NUOVO: LA CORAZZA DI SICUREZZA!
  cloud_firestore: ^6.1.2
  share_plus: ^12.0.1
  app_links: ^7.0.0
  google_fonts: ^8.0.2
  font_awesome_flutter: ^10.12.0
  firebase_app_check: ^0.4.1+5
  package_info_plus: ^9.0.0
  device_info_plus: ^12.3.0

  # --- NUOVI PACCHETTI PER GLI AGGIORNAMENTI ---
  upgrader: ^12.5.0
  in_app_update: ^4.2.0

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

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/audio/


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>--- 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/>
	<key>keychain-access-groups</key>
	<array/>
</dict>
</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>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>keychain-access-groups</key>
	<array/>
</dict>
</plist>
--- Podfile ---
platform :osx, '10.15'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

project 'Runner', {
  'Debug' => :debug,
  'Profile' => :release,
  'Release' => :release,
}

def flutter_root
  generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
  unless File.exist?(generated_xcode_build_settings_path)
    raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
  end

  File.foreach(generated_xcode_build_settings_path) do |line|
    matches = line.match(/FLUTTER_ROOT\=(.*)/)
    return matches[1].strip if matches
  end
  raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
end

require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)

flutter_macos_podfile_setup

target 'Runner' do
  use_frameworks!

  flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
  target 'RunnerTests' do
    inherit! :search_paths
  end
end

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_macos_build_settings(target)
  end
end

=== 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>CADisableMinimumFrameDurationOnPhone</key>
	<true/>
	<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>CFBundleURLTypes</key>
	<array>
		<dict>
			<key>CFBundleTypeRole</key>
			<string>Editor</string>
			<key>CFBundleURLName</key>
			<string>com.sanza.tetraq</string>
			<key>CFBundleURLSchemes</key>
			<array>
				<string>tetraq</string>
			</array>
		</dict>
	</array>
	<key>CFBundleVersion</key>
	<string>$(FLUTTER_BUILD_NUMBER)</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>UIApplicationSupportsIndirectInputEvents</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>
</dict>
</plist>
--- Podfile ---
# Uncomment this line to define a global platform for your project
 platform :ios, '15.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

project 'Runner', {
  'Debug' => :debug,
  'Profile' => :release,
  'Release' => :release,
}

def flutter_root
  generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
  unless File.exist?(generated_xcode_build_settings_path)
    raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
  end

  File.foreach(generated_xcode_build_settings_path) do |line|
    matches = line.match(/FLUTTER_ROOT\=(.*)/)
    return matches[1].strip if matches
  end
  raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end

require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)

flutter_ios_podfile_setup

target 'Runner' do
  use_frameworks!

  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
  target 'RunnerTests' do
    inherit! :search_paths
  end
end

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
  end
end

=== 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>--- build.gradle / build.gradle.kts ---
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")
}

// Aggiungiamo esplicitamente gli import richiesti da Kotlin
import java.io.FileInputStream
        import java.util.Properties

// Carichiamo il file con le password
val keystoreProperties = Properties()
val keystorePropertiesFile = rootProject.file("key.properties")
if (keystorePropertiesFile.exists()) {
    keystoreProperties.load(FileInputStream(keystorePropertiesFile))
}

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

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

    // Sintassi aggiornata come richiesto dal compilatore Kotlin
    kotlin {
        compilerOptions {
            jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17)
        }
    }

    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId = "com.amastra.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
    }

    // Aggiunto il blocco per la firma in formato Kotlin DSL
    signingConfigs {
        create("release") {
            keyAlias = keystoreProperties.getProperty("keyAlias")
            keyPassword = keystoreProperties.getProperty("keyPassword")
            val storeFileString = keystoreProperties.getProperty("storeFile")
            if (storeFileString != null) {
                storeFile = file(storeFileString)
            }
            storePassword = keystoreProperties.getProperty("storePassword")
        }
    }

    buildTypes {
        getByName("release") {
            // TODO: Add your own signing config for the release build.
            // Ora usiamo la chiave di release appena creata
            signingConfig = signingConfigs.getByName("release")
        }
    }
}

flutter {
    source = "../.."
}
=== SOURCE CODE (lib/) ===

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

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

import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';

enum AppThemeType { doodle, cyberpunk, arcade, grimorio, music }

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 doodle = ThemeColors(
    background: Color(0xFFFFF9E6), gridLine: Color(0xFFB0BEC5),
    playerRed: Color(0xFFD32F2F), playerBlue: Color(0xFF1565C0), text: Color(0xFF37474F),
  );

  static const ThemeColors cyberpunk = ThemeColors(
    background: Color(0xFF0A001A), gridLine: Color(0xFF6200EA),
    playerRed: Color(0xFFFF007F), playerBlue: Color(0xFF69F0AE), text: Color(0xFFFFFFFF),
  );

  static const ThemeColors arcade = ThemeColors(
    background: Color(0xFF111111), gridLine: Color(0xFF00FF00),
    playerRed: Color(0xFFFF004D), playerBlue: Color(0xFF00E5FF), text: Color(0xFFFFFFFF),
  );

  static const ThemeColors grimorio = ThemeColors(
    background: Color(0xFF1E112A), gridLine: Colors.black,
    playerRed: Color(0xFFE91E63), playerBlue: Color(0xFF4FC3F7), text: Color(0xFFFFF3E0),
  );

  static const ThemeColors music = ThemeColors(
    background: Color(0xFF120B29),
    gridLine: Color(0xFF6A1B9A),
    playerRed: Color(0xFFFF2A6D),
    playerBlue: Color(0xFF05D5FF),
    text: Color(0xFFE0E0E0),
  );

  static ThemeColors getTheme(AppThemeType type) {
    switch (type) {
      case AppThemeType.doodle: return doodle;
      case AppThemeType.cyberpunk: return cyberpunk;
      case AppThemeType.arcade: return arcade;
      case AppThemeType.grimorio: return grimorio;
      case AppThemeType.music: return music;
    }
  }
}

class ThemeIcons {
  static IconData gold(AppThemeType type) {
    switch (type) {
      case AppThemeType.doodle: return FontAwesomeIcons.star;
      case AppThemeType.cyberpunk: return FontAwesomeIcons.microchip;
      case AppThemeType.arcade: return FontAwesomeIcons.coins;
      case AppThemeType.grimorio: return FontAwesomeIcons.crown;
      case AppThemeType.music: return FontAwesomeIcons.compactDisc;
    }
  }

  static IconData bomb(AppThemeType type) {
    switch (type) {
      case AppThemeType.doodle: return FontAwesomeIcons.virus;
      case AppThemeType.cyberpunk: return FontAwesomeIcons.bug;
      case AppThemeType.arcade: return FontAwesomeIcons.ghost;
      case AppThemeType.grimorio: return FontAwesomeIcons.hatWizard;
      case AppThemeType.music: return FontAwesomeIcons.volumeXmark;
    }
  }

  static IconData swap(AppThemeType type) {
    switch (type) {
      case AppThemeType.doodle: return FontAwesomeIcons.arrowsRotate;
      case AppThemeType.cyberpunk: return FontAwesomeIcons.networkWired;
      case AppThemeType.arcade: return FontAwesomeIcons.shuffle;
      case AppThemeType.grimorio: return FontAwesomeIcons.hurricane;
      case AppThemeType.music: return FontAwesomeIcons.sliders;
    }
  }

  static IconData joker(AppThemeType type) {
    switch (type) {
      case AppThemeType.doodle: return FontAwesomeIcons.faceSmileBeam;
      case AppThemeType.cyberpunk: return FontAwesomeIcons.robot;
      case AppThemeType.arcade: return FontAwesomeIcons.gamepad;
      case AppThemeType.grimorio: return FontAwesomeIcons.masksTheater;
      case AppThemeType.music: return FontAwesomeIcons.headphones;
    }
  }

  static IconData block(AppThemeType type) {
    switch (type) {
      case AppThemeType.doodle: return FontAwesomeIcons.squareXmark;
      case AppThemeType.cyberpunk: return FontAwesomeIcons.shieldHalved;
      case AppThemeType.arcade: return FontAwesomeIcons.powerOff;
      case AppThemeType.grimorio: return FontAwesomeIcons.meteor;
      case AppThemeType.music: return FontAwesomeIcons.pause;
    }
  }

  static IconData ice(AppThemeType type) {
    if (type == AppThemeType.music) return FontAwesomeIcons.music;
    return FontAwesomeIcons.snowflake;
  }

  static IconData multiplier(AppThemeType type) {
    if (type == AppThemeType.music) return FontAwesomeIcons.forwardFast;
    return FontAwesomeIcons.bolt;
  }
}
// ===========================================================================
// 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
// ===========================================================================

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

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

// --- ENUM DEI TEMI AGGIORNATO ---
const Map<AppThemeType, IconData> themeIcons = {
  AppThemeType.cyberpunk: Icons.electric_bolt,
  AppThemeType.doodle: Icons.brush,
  AppThemeType.music: Icons.headset_mic,
  AppThemeType.arcade: Icons.videogame_asset,
  AppThemeType.grimorio: Icons.auto_stories,
};

const Map<AppThemeType, String> themeNames = {
  AppThemeType.cyberpunk: "Cyberpunk",
  AppThemeType.doodle: "Doodle",
  AppThemeType.music: "Music",
  AppThemeType.arcade: "Arcade",
  AppThemeType.grimorio: "Grimorio",
};

class ThemeManager with ChangeNotifier {
  AppThemeType _currentThemeType = AppThemeType.doodle;
  ThemeColors _currentColors = AppColors.getTheme(AppThemeType.doodle);

  AppThemeType get currentThemeType => _currentThemeType;
  ThemeColors get currentColors => _currentColors;

  ThemeManager() {
    _loadTheme();
  }

  void _loadTheme() async {
    String themeStr = StorageService.instance.getTheme();
    AppThemeType loadedType = AppThemeType.values.firstWhere(
            (e) => e.toString() == themeStr,
        orElse: () => AppThemeType.doodle
    );
    _currentThemeType = loadedType;
    _currentColors = AppColors.getTheme(loadedType);
    _updateSystemUI();
    notifyListeners();
  }

  void setTheme(AppThemeType type) {
    _currentThemeType = type;
    _currentColors = AppColors.getTheme(type);
    StorageService.instance.saveTheme(type.toString());
    _updateSystemUI();
    notifyListeners();
  }

  void _updateSystemUI() {
    SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
      statusBarColor: Colors.transparent,
      statusBarIconBrightness: _currentThemeType == AppThemeType.doodle ? Brightness.dark : Brightness.light,
      systemNavigationBarColor: _currentColors.background,
      systemNavigationBarIconBrightness: _currentThemeType == AppThemeType.doodle ? Brightness.dark : Brightness.light,
    ));
  }
}
// ===========================================================================
// 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:ceac21bb06b7a9f07b949b',
    messagingSenderId: '705460445314',
    projectId: 'tetraq-32a4a',
    storageBucket: 'tetraq-32a4a.firebasestorage.app',
  );

  static const FirebaseOptions ios = FirebaseOptions(
    apiKey: 'AIzaSyB77j18Jgeb9gBAEwp-uyOQvr4m-RJ_rAE',
    appId: '1:705460445314:ios:54d64cb7592954327b949b',
    messagingSenderId: '705460445314',
    projectId: 'tetraq-32a4a',
    storageBucket: 'tetraq-32a4a.firebasestorage.app',
    iosBundleId: 'com.amastra.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/l10n/app_localizations.dart
// ===========================================================================

import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:intl/intl.dart' as intl;

import 'app_localizations_de.dart';
import 'app_localizations_en.dart';
import 'app_localizations_es.dart';
import 'app_localizations_fr.dart';
import 'app_localizations_it.dart';
import 'app_localizations_pt.dart';
import 'app_localizations_ru.dart';
import 'app_localizations_zh.dart';

// ignore_for_file: type=lint

/// Callers can lookup localized strings with an instance of AppLocalizations
/// returned by `AppLocalizations.of(context)`.
///
/// Applications need to include `AppLocalizations.delegate()` in their app's
/// `localizationDelegates` list, and the locales they support in the app's
/// `supportedLocales` list. For example:
///
/// ```dart
/// import 'l10n/app_localizations.dart';
///
/// return MaterialApp(
///   localizationsDelegates: AppLocalizations.localizationsDelegates,
///   supportedLocales: AppLocalizations.supportedLocales,
///   home: MyApplicationHome(),
/// );
/// ```
///
/// ## Update pubspec.yaml
///
/// Please make sure to update your pubspec.yaml to include the following
/// packages:
///
/// ```yaml
/// dependencies:
///   # Internationalization support.
///   flutter_localizations:
///     sdk: flutter
///   intl: any # Use the pinned version from flutter_localizations
///
///   # Rest of dependencies
/// ```
///
/// ## iOS Applications
///
/// iOS applications define key application metadata, including supported
/// locales, in an Info.plist file that is built into the application bundle.
/// To configure the locales supported by your app, you’ll need to edit this
/// file.
///
/// First, open your project’s ios/Runner.xcworkspace Xcode workspace file.
/// Then, in the Project Navigator, open the Info.plist file under the Runner
/// project’s Runner folder.
///
/// Next, select the Information Property List item, select Add Item from the
/// Editor menu, then select Localizations from the pop-up menu.
///
/// Select and expand the newly-created Localizations item then, for each
/// locale your application supports, add a new item and select the locale
/// you wish to add from the pop-up menu in the Value field. This list should
/// be consistent with the languages listed in the AppLocalizations.supportedLocales
/// property.
abstract class AppLocalizations {
  AppLocalizations(String locale)
    : localeName = intl.Intl.canonicalizedLocale(locale.toString());

  final String localeName;

  static AppLocalizations? of(BuildContext context) {
    return Localizations.of<AppLocalizations>(context, AppLocalizations);
  }

  static const LocalizationsDelegate<AppLocalizations> delegate =
      _AppLocalizationsDelegate();

  /// A list of this localizations delegate along with the default localizations
  /// delegates.
  ///
  /// Returns a list of localizations delegates containing this delegate along with
  /// GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate,
  /// and GlobalWidgetsLocalizations.delegate.
  ///
  /// Additional delegates can be added by appending to this list in
  /// MaterialApp. This list does not have to be used at all if a custom list
  /// of delegates is preferred or required.
  static const List<LocalizationsDelegate<dynamic>> localizationsDelegates =
      <LocalizationsDelegate<dynamic>>[
        delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ];

  /// A list of this localizations delegate's supported locales.
  static const List<Locale> supportedLocales = <Locale>[
    Locale('de'),
    Locale('en'),
    Locale('es'),
    Locale('fr'),
    Locale('it'),
    Locale('pt'),
    Locale('ru'),
    Locale('zh'),
  ];

  /// No description provided for @appTitle.
  ///
  /// In it, this message translates to:
  /// **'TetraQ'**
  String get appTitle;

  /// No description provided for @welcomeTitle.
  ///
  /// In it, this message translates to:
  /// **'BENVENUTO IN TETRAQ!'**
  String get welcomeTitle;

  /// No description provided for @nameHint.
  ///
  /// In it, this message translates to:
  /// **'NOME'**
  String get nameHint;

  /// No description provided for @saveAndPlay.
  ///
  /// In it, this message translates to:
  /// **'SALVA E GIOCA'**
  String get saveAndPlay;

  /// No description provided for @onlineTitle.
  ///
  /// In it, this message translates to:
  /// **'ONLINE'**
  String get onlineTitle;

  /// No description provided for @onlineSub.
  ///
  /// In it, this message translates to:
  /// **'Sfida il mondo'**
  String get onlineSub;

  /// No description provided for @cpuTitle.
  ///
  /// In it, this message translates to:
  /// **'VS CPU'**
  String get cpuTitle;

  /// No description provided for @cpuSub.
  ///
  /// In it, this message translates to:
  /// **'Allenati con l\'IA'**
  String get cpuSub;

  /// No description provided for @localTitle.
  ///
  /// In it, this message translates to:
  /// **'LOCALE'**
  String get localTitle;

  /// No description provided for @localSub.
  ///
  /// In it, this message translates to:
  /// **'Stesso schermo'**
  String get localSub;

  /// No description provided for @leaderboardTitle.
  ///
  /// In it, this message translates to:
  /// **'CLASSIFICA'**
  String get leaderboardTitle;

  /// No description provided for @questsTitle.
  ///
  /// In it, this message translates to:
  /// **'SFIDE'**
  String get questsTitle;

  /// No description provided for @themesTitle.
  ///
  /// In it, this message translates to:
  /// **'TEMI'**
  String get themesTitle;

  /// No description provided for @tutorialTitle.
  ///
  /// In it, this message translates to:
  /// **'TUTORIAL'**
  String get tutorialTitle;

  /// No description provided for @startGame.
  ///
  /// In it, this message translates to:
  /// **'AVVIA PARTITA'**
  String get startGame;

  /// No description provided for @createMatch.
  ///
  /// In it, this message translates to:
  /// **'CREA PARTITA'**
  String get createMatch;

  /// No description provided for @joinMatch.
  ///
  /// In it, this message translates to:
  /// **'UNISCITI'**
  String get joinMatch;

  /// No description provided for @gameOver.
  ///
  /// In it, this message translates to:
  /// **'FINE PARTITA'**
  String get gameOver;

  /// No description provided for @mainMenu.
  ///
  /// In it, this message translates to:
  /// **'TORNA AL MENU'**
  String get mainMenu;

  /// No description provided for @exit.
  ///
  /// In it, this message translates to:
  /// **'ESCI'**
  String get exit;
}

class _AppLocalizationsDelegate
    extends LocalizationsDelegate<AppLocalizations> {
  const _AppLocalizationsDelegate();

  @override
  Future<AppLocalizations> load(Locale locale) {
    return SynchronousFuture<AppLocalizations>(lookupAppLocalizations(locale));
  }

  @override
  bool isSupported(Locale locale) => <String>[
    'de',
    'en',
    'es',
    'fr',
    'it',
    'pt',
    'ru',
    'zh',
  ].contains(locale.languageCode);

  @override
  bool shouldReload(_AppLocalizationsDelegate old) => false;
}

AppLocalizations lookupAppLocalizations(Locale locale) {
  // Lookup logic when only language code is specified.
  switch (locale.languageCode) {
    case 'de':
      return AppLocalizationsDe();
    case 'en':
      return AppLocalizationsEn();
    case 'es':
      return AppLocalizationsEs();
    case 'fr':
      return AppLocalizationsFr();
    case 'it':
      return AppLocalizationsIt();
    case 'pt':
      return AppLocalizationsPt();
    case 'ru':
      return AppLocalizationsRu();
    case 'zh':
      return AppLocalizationsZh();
  }

  throw FlutterError(
    'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely '
    'an issue with the localizations generation tool. Please file an issue '
    'on GitHub with a reproducible sample app and the gen-l10n configuration '
    'that was used.',
  );
}

// ===========================================================================
// FILE: lib/l10n/app_localizations_de.dart
// ===========================================================================

// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';

// ignore_for_file: type=lint

/// The translations for German (`de`).
class AppLocalizationsDe extends AppLocalizations {
  AppLocalizationsDe([String locale = 'de']) : super(locale);

  @override
  String get appTitle => 'TetraQ';

  @override
  String get welcomeTitle => 'WILLKOMMEN BEI TETRAQ!';

  @override
  String get nameHint => 'NAME';

  @override
  String get saveAndPlay => 'SPEICHERN & SPIELEN';

  @override
  String get onlineTitle => 'ONLINE';

  @override
  String get onlineSub => 'Fordere die Welt heraus';

  @override
  String get cpuTitle => 'VS CPU';

  @override
  String get cpuSub => 'Trainiere mit KI';

  @override
  String get localTitle => 'LOKAL';

  @override
  String get localSub => 'Gleicher Bildschirm';

  @override
  String get leaderboardTitle => 'RANGLISTE';

  @override
  String get questsTitle => 'MISSIONEN';

  @override
  String get themesTitle => 'THEMEN';

  @override
  String get tutorialTitle => 'TUTORIAL';

  @override
  String get startGame => 'SPIEL STARTEN';

  @override
  String get createMatch => 'SPIEL ERSTELLEN';

  @override
  String get joinMatch => 'BEITRETEN';

  @override
  String get gameOver => 'SPIELENDE';

  @override
  String get mainMenu => 'ZURÜCK ZUM MENÜ';

  @override
  String get exit => 'BEENDEN';
}

// ===========================================================================
// FILE: lib/l10n/app_localizations_en.dart
// ===========================================================================

// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';

// ignore_for_file: type=lint

/// The translations for English (`en`).
class AppLocalizationsEn extends AppLocalizations {
  AppLocalizationsEn([String locale = 'en']) : super(locale);

  @override
  String get appTitle => 'TetraQ';

  @override
  String get welcomeTitle => 'WELCOME TO TETRAQ!';

  @override
  String get nameHint => 'NAME';

  @override
  String get saveAndPlay => 'SAVE & PLAY';

  @override
  String get onlineTitle => 'ONLINE';

  @override
  String get onlineSub => 'Challenge the world';

  @override
  String get cpuTitle => 'VS CPU';

  @override
  String get cpuSub => 'Train with AI';

  @override
  String get localTitle => 'LOCAL';

  @override
  String get localSub => 'Same screen';

  @override
  String get leaderboardTitle => 'LEADERBOARD';

  @override
  String get questsTitle => 'QUESTS';

  @override
  String get themesTitle => 'THEMES';

  @override
  String get tutorialTitle => 'TUTORIAL';

  @override
  String get startGame => 'START GAME';

  @override
  String get createMatch => 'CREATE MATCH';

  @override
  String get joinMatch => 'JOIN';

  @override
  String get gameOver => 'GAME OVER';

  @override
  String get mainMenu => 'BACK TO MENU';

  @override
  String get exit => 'EXIT';
}

// ===========================================================================
// FILE: lib/l10n/app_localizations_es.dart
// ===========================================================================

// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';

// ignore_for_file: type=lint

/// The translations for Spanish Castilian (`es`).
class AppLocalizationsEs extends AppLocalizations {
  AppLocalizationsEs([String locale = 'es']) : super(locale);

  @override
  String get appTitle => 'TetraQ';

  @override
  String get welcomeTitle => '¡BIENVENIDO A TETRAQ!';

  @override
  String get nameHint => 'NOMBRE';

  @override
  String get saveAndPlay => 'GUARDAR Y JUGAR';

  @override
  String get onlineTitle => 'ONLINE';

  @override
  String get onlineSub => 'Desafía al mundo';

  @override
  String get cpuTitle => 'VS CPU';

  @override
  String get cpuSub => 'Entrena con IA';

  @override
  String get localTitle => 'LOCAL';

  @override
  String get localSub => 'Misma pantalla';

  @override
  String get leaderboardTitle => 'RANKING';

  @override
  String get questsTitle => 'MISIONES';

  @override
  String get themesTitle => 'TEMAS';

  @override
  String get tutorialTitle => 'TUTORIAL';

  @override
  String get startGame => 'INICIAR JUEGO';

  @override
  String get createMatch => 'CREAR PARTIDA';

  @override
  String get joinMatch => 'UNIRSE';

  @override
  String get gameOver => 'FIN DEL JUEGO';

  @override
  String get mainMenu => 'VOLVER AL MENÚ';

  @override
  String get exit => 'SALIR';
}

// ===========================================================================
// FILE: lib/l10n/app_localizations_fr.dart
// ===========================================================================

// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';

// ignore_for_file: type=lint

/// The translations for French (`fr`).
class AppLocalizationsFr extends AppLocalizations {
  AppLocalizationsFr([String locale = 'fr']) : super(locale);

  @override
  String get appTitle => 'TetraQ';

  @override
  String get welcomeTitle => 'BIENVENUE DANS TETRAQ !';

  @override
  String get nameHint => 'NOM';

  @override
  String get saveAndPlay => 'SAUVEGARDER ET JOUER';

  @override
  String get onlineTitle => 'EN LIGNE';

  @override
  String get onlineSub => 'Défiez le monde';

  @override
  String get cpuTitle => 'VS CPU';

  @override
  String get cpuSub => 'Entraînez avec l\'IA';

  @override
  String get localTitle => 'LOCAL';

  @override
  String get localSub => 'Même écran';

  @override
  String get leaderboardTitle => 'CLASSEMENT';

  @override
  String get questsTitle => 'QUÊTES';

  @override
  String get themesTitle => 'THÈMES';

  @override
  String get tutorialTitle => 'TUTORIEL';

  @override
  String get startGame => 'JOUER';

  @override
  String get createMatch => 'CRÉER UN MATCH';

  @override
  String get joinMatch => 'REJOINDRE';

  @override
  String get gameOver => 'FIN DE PARTIE';

  @override
  String get mainMenu => 'RETOUR AU MENU';

  @override
  String get exit => 'QUITTER';
}

// ===========================================================================
// FILE: lib/l10n/app_localizations_it.dart
// ===========================================================================

// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';

// ignore_for_file: type=lint

/// The translations for Italian (`it`).
class AppLocalizationsIt extends AppLocalizations {
  AppLocalizationsIt([String locale = 'it']) : super(locale);

  @override
  String get appTitle => 'TetraQ';

  @override
  String get welcomeTitle => 'BENVENUTO IN TETRAQ!';

  @override
  String get nameHint => 'NOME';

  @override
  String get saveAndPlay => 'SALVA E GIOCA';

  @override
  String get onlineTitle => 'ONLINE';

  @override
  String get onlineSub => 'Sfida il mondo';

  @override
  String get cpuTitle => 'VS CPU';

  @override
  String get cpuSub => 'Allenati con l\'IA';

  @override
  String get localTitle => 'LOCALE';

  @override
  String get localSub => 'Stesso schermo';

  @override
  String get leaderboardTitle => 'CLASSIFICA';

  @override
  String get questsTitle => 'SFIDE';

  @override
  String get themesTitle => 'TEMI';

  @override
  String get tutorialTitle => 'TUTORIAL';

  @override
  String get startGame => 'AVVIA PARTITA';

  @override
  String get createMatch => 'CREA PARTITA';

  @override
  String get joinMatch => 'UNISCITI';

  @override
  String get gameOver => 'FINE PARTITA';

  @override
  String get mainMenu => 'TORNA AL MENU';

  @override
  String get exit => 'ESCI';
}

// ===========================================================================
// FILE: lib/l10n/app_localizations_pt.dart
// ===========================================================================

// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';

// ignore_for_file: type=lint

/// The translations for Portuguese (`pt`).
class AppLocalizationsPt extends AppLocalizations {
  AppLocalizationsPt([String locale = 'pt']) : super(locale);

  @override
  String get appTitle => 'TetraQ';

  @override
  String get welcomeTitle => 'BEM-VINDO AO TETRAQ!';

  @override
  String get nameHint => 'NOME';

  @override
  String get saveAndPlay => 'SALVAR E JOGAR';

  @override
  String get onlineTitle => 'ONLINE';

  @override
  String get onlineSub => 'Desafie o mundo';

  @override
  String get cpuTitle => 'VS CPU';

  @override
  String get cpuSub => 'Treine com a IA';

  @override
  String get localTitle => 'LOCAL';

  @override
  String get localSub => 'Mesma tela';

  @override
  String get leaderboardTitle => 'CLASSIFICAÇÃO';

  @override
  String get questsTitle => 'DESAFIOS';

  @override
  String get themesTitle => 'TEMAS';

  @override
  String get tutorialTitle => 'TUTORIAL';

  @override
  String get startGame => 'INICIAR JOGO';

  @override
  String get createMatch => 'CRIAR PARTIDA';

  @override
  String get joinMatch => 'ENTRAR';

  @override
  String get gameOver => 'FIM DE JOGO';

  @override
  String get mainMenu => 'VOLTAR AO MENU';

  @override
  String get exit => 'SAIR';
}

// ===========================================================================
// FILE: lib/l10n/app_localizations_ru.dart
// ===========================================================================

// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';

// ignore_for_file: type=lint

/// The translations for Russian (`ru`).
class AppLocalizationsRu extends AppLocalizations {
  AppLocalizationsRu([String locale = 'ru']) : super(locale);

  @override
  String get appTitle => 'TetraQ';

  @override
  String get welcomeTitle => 'ДОБРО ПОЖАЛОВАТЬ В TETRAQ!';

  @override
  String get nameHint => 'ИМЯ';

  @override
  String get saveAndPlay => 'СОХРАНИТЬ И ИГРАТЬ';

  @override
  String get onlineTitle => 'ОНЛАЙН';

  @override
  String get onlineSub => 'Брось вызов миру';

  @override
  String get cpuTitle => 'VS ИИ';

  @override
  String get cpuSub => 'Тренировка с ИИ';

  @override
  String get localTitle => 'ЛОКАЛЬНО';

  @override
  String get localSub => 'Один экран';

  @override
  String get leaderboardTitle => 'РЕЙТИНГ';

  @override
  String get questsTitle => 'ЗАДАНИЯ';

  @override
  String get themesTitle => 'ТЕМЫ';

  @override
  String get tutorialTitle => 'ОБУЧЕНИЕ';

  @override
  String get startGame => 'НАЧАТЬ ИГРУ';

  @override
  String get createMatch => 'СОЗДАТЬ ИГРУ';

  @override
  String get joinMatch => 'ПРИСОЕДИНИТЬСЯ';

  @override
  String get gameOver => 'ИГРА ОКОНЧЕНА';

  @override
  String get mainMenu => 'В ГЛАВНОЕ МЕНЮ';

  @override
  String get exit => 'ВЫХОД';
}

// ===========================================================================
// FILE: lib/l10n/app_localizations_zh.dart
// ===========================================================================

// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';

// ignore_for_file: type=lint

/// The translations for Chinese (`zh`).
class AppLocalizationsZh extends AppLocalizations {
  AppLocalizationsZh([String locale = 'zh']) : super(locale);

  @override
  String get appTitle => 'TetraQ';

  @override
  String get welcomeTitle => '欢迎来到 TETRAQ！';

  @override
  String get nameHint => '名字';

  @override
  String get saveAndPlay => '保存并开始';

  @override
  String get onlineTitle => '在线匹配';

  @override
  String get onlineSub => '挑战世界';

  @override
  String get cpuTitle => '人机对战';

  @override
  String get cpuSub => '与AI训练';

  @override
  String get localTitle => '本地游戏';

  @override
  String get localSub => '同屏对战';

  @override
  String get leaderboardTitle => '排行榜';

  @override
  String get questsTitle => '任务';

  @override
  String get themesTitle => '主题';

  @override
  String get tutorialTitle => '教程';

  @override
  String get startGame => '开始游戏';

  @override
  String get createMatch => '创建比赛';

  @override
  String get joinMatch => '加入';

  @override
  String get gameOver => '游戏结束';

  @override
  String get mainMenu => '返回主菜单';

  @override
  String get exit => '退出';
}

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

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

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

class _ClosureResult {
  final bool closesSomething;
  final int netValue;
  final bool causesSwap;
  _ClosureResult(this.closesSomething, this.netValue, this.causesSwap);
}

class AIEngine {
  static Line getBestMove(GameBoard board, int level) {
    List<Line> availableLines = board.lines.where((l) => l.owner == Player.none && l.isPlayable).toList();
    final random = Random();

    if (availableLines.isEmpty) return board.lines.first;

    double smartChance = 0.50 + ((level - 1) * 0.10);
    if (smartChance > 1.0) smartChance = 1.0;

    bool beSmart = random.nextDouble() < smartChance;

    int myScore = board.currentPlayer == Player.red ? board.scoreRed : board.scoreBlue;
    int oppScore = board.currentPlayer == Player.red ? board.scoreBlue : board.scoreRed;

    List<Line> goodClosingMoves = [];
    List<Line> badClosingMoves = [];

    for (var line in availableLines) {
      var result = _checkClosure(board, line);
      if (result.closesSomething) {
        if (result.causesSwap) {
          if (myScore < oppScore) {
            goodClosingMoves.add(line);
          } else {
            badClosingMoves.add(line);
          }
        } else {
          if (result.netValue >= 0) {
            goodClosingMoves.add(line);
          } else {
            badClosingMoves.add(line);
          }
        }
      }
    }

    // --- REGOLA 1: Chiudere i quadrati vantaggiosi ---
    if (goodClosingMoves.isNotEmpty) {
      if (beSmart || random.nextDouble() < 0.70) {
        return goodClosingMoves[random.nextInt(goodClosingMoves.length)];
      }
    }

    // --- REGOLA 2: Mosse Sicure ---
    List<Line> safeMoves = [];
    for (var line in availableLines) {
      if (!badClosingMoves.contains(line) && !goodClosingMoves.contains(line) && _isSafeMove(board, line, myScore, oppScore)) {
        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: Scegliere il male minore ---
    if (beSmart) {
      List<Line> riskyButNotTerrible = availableLines.where((l) => !badClosingMoves.contains(l) && !goodClosingMoves.contains(l)).toList();
      if (riskyButNotTerrible.isNotEmpty) {
        return riskyButNotTerrible[random.nextInt(riskyButNotTerrible.length)];
      }
    }

    List<Line> nonTerribleMoves = availableLines.where((l) => !badClosingMoves.contains(l)).toList();
    if (nonTerribleMoves.isNotEmpty) {
      return nonTerribleMoves[random.nextInt(nonTerribleMoves.length)];
    }

    return availableLines[random.nextInt(availableLines.length)];
  }

  static _ClosureResult _checkClosure(GameBoard board, Line line) {
    int netValue = 0;
    bool closesSomething = false;
    bool causesSwap = false;

    for (var box in board.boxes) {
      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) {
          closesSomething = true;

          // FIX: Togliamo la "vista a raggi X" all'Intelligenza Artificiale!
          if (box.hiddenJokerOwner == board.currentPlayer) {
            // L'IA conosce il suo Jolly, sa che vale +2 e cercherà di chiuderlo
            netValue += 2;
          } else {
            // Se c'è il Jolly del giocatore, l'IA NON DEVE SAPERLO e valuta la casella normalmente!
            if (box.type == BoxType.gold) netValue += 2;
            else if (box.type == BoxType.bomb) netValue -= 1;
            else if (box.type == BoxType.swap) netValue += 0;
            else netValue += 1;
          }

          if (box.type == BoxType.swap) causesSwap = true;
        }
      }
    }
    return _ClosureResult(closesSomething, netValue, causesSwap);
  }

  static bool _isSafeMove(GameBoard board, Line line, int myScore, int oppScore) {
    for (var box in board.boxes) {
      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) {

          // Nuova logica di sicurezza: cosa succede se l'IA lascia questa scatola all'avversario?
          int valueForOpponent = 0;
          if (box.hiddenJokerOwner == board.currentPlayer) {
            // Se l'avversario la chiude, becca la trappola dell'IA (-1).
            // Quindi PER L'IA È SICURISSIMO LASCIARE QUESTA CASELLA APERTA!
            valueForOpponent = -1;
          } else {
            if (box.type == BoxType.gold) valueForOpponent = 2;
            else if (box.type == BoxType.bomb) valueForOpponent = -1;
            else if (box.type == BoxType.swap) valueForOpponent = 0;
            else valueForOpponent = 1;
          }

          // Se per l'avversario vale -1 (bomba normale o trappola dell'IA), lasciamogliela!
          if (valueForOpponent < 0) {
            continue;
          }

          if (box.type == BoxType.swap) {
            if (myScore < oppScore) {
              continue;
            } else {
              return false;
            }
          }

          return false;
        }
      }
    }
    return true;
  }
}
// ===========================================================================
// FILE: lib/logic/game_controller.dart
// ===========================================================================

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

import 'dart:async';
import 'dart:math';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import '../models/game_board.dart';
export '../models/game_board.dart';

import 'ai_engine.dart';
import '../services/audio_service.dart';
import '../services/storage_service.dart';
import '../services/multiplayer_service.dart';
import '../core/app_colors.dart';

class CpuMatchSetup {
  final int radius;
  final ArenaShape shape;
  CpuMatchSetup(this.radius, this.shape);
}

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 = 10;
  int maxTime = 10;
  String timeModeSetting = 'fixed'; // 'fixed', 'relax', 'dynamic'
  bool get isTimeMode => timeModeSetting != 'relax';
  int consecutiveRematches = 0; // Contatore per la modalità Dinamica

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

  String? myReaction;
  String? opponentReaction;
  Timer? _myReactionTimer;
  Timer? _oppReactionTimer;

  Timestamp? _lastOpponentReactionTime;

  bool rematchRequested = false;
  bool opponentWantsRematch = false;
  int lastMatchXP = 0;

  static const Map<int, List<Map<String, dynamic>>> rewardsRoadmap = {
    2: [{'title': 'Bomba & Oro', 'desc': 'Appaiono le caselle speciali: Oro (+2) e Bomba (-1)!', 'icon': Icons.stars, 'color': Colors.amber}],
    3: [
      {'title': 'Tema Cyberpunk', 'desc': 'Sbloccato un nuovo tema visivo nelle impostazioni.', 'icon': Icons.palette, 'color': Colors.tealAccent},
      {'title': 'Arena a Croce', 'desc': 'Sbloccata una nuova forma arena più complessa.', 'icon': Icons.add_box, 'color': Colors.blueAccent}
    ],
    5: [{'title': 'Scambio', 'desc': 'Nuova casella! Inverte istantaneamente i punteggi.', 'icon': Icons.swap_horiz, 'color': Colors.purpleAccent}],
    7: [
      {'title': 'Tema 8-Bit', 'desc': 'Sbloccato il nostalgico tema sala giochi.', 'icon': Icons.videogame_asset, 'color': Colors.greenAccent},
      {'title': 'Arene Caos', 'desc': 'Generazione procedurale sbloccata. Nessuna partita sarà uguale!', 'icon': Icons.all_inclusive, 'color': Colors.redAccent}
    ],
    10: [
      {'title': 'Tema Grimorio', 'desc': 'Sbloccato il tema della magia antica.', 'icon': Icons.auto_stories, 'color': Colors.deepPurpleAccent},
      {'title': 'Blocco di Ghiaccio', 'desc': 'Nuova meccanica! Il ghiaccio richiede due colpi per rompersi.', 'icon': Icons.ac_unit, 'color': Colors.cyanAccent}
    ],
    15: [
      {'title': 'Tema Musica', 'desc': 'Sbloccato il tema a tempo di beat.', 'icon': Icons.headphones, 'color': Colors.pinkAccent},
      {'title': 'Moltiplicatore x2', 'desc': 'Nuova casella! Raddoppia i punti della tua prossima conquista.', 'icon': Icons.bolt, 'color': Colors.yellowAccent}
    ],
  };

  bool hasLeveledUp = false;
  int newlyReachedLevel = 1;
  List<Map<String, dynamic>> unlockedRewards = [];

  bool isSetupPhase = true;
  bool myJokerPlaced = false;
  bool oppJokerPlaced = false;
  Player jokerTurn = Player.red;

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

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

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

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

  CpuMatchSetup _getSetupForCpuLevel(int level) {
    final rand = Random();
    if (level == 1) return CpuMatchSetup(3, ArenaShape.classic);
    if (level == 2) return CpuMatchSetup(4, ArenaShape.classic);
    if (level == 3) return CpuMatchSetup(4, ArenaShape.cross);
    if (level == 4) return CpuMatchSetup(4, ArenaShape.donut);
    if (level == 5) return CpuMatchSetup(5, ArenaShape.classic);
    if (level == 6) return CpuMatchSetup(4, ArenaShape.hourglass);
    if (level == 7) return CpuMatchSetup(5, ArenaShape.cross);
    if (level == 8) return CpuMatchSetup(5, ArenaShape.donut);
    if (level == 9) return CpuMatchSetup(5, ArenaShape.hourglass);

    List<ArenaShape> hardShapes = [ArenaShape.classic, ArenaShape.cross, ArenaShape.donut, ArenaShape.hourglass, ArenaShape.chaos];
    ArenaShape chosenShape = hardShapes[rand.nextInt(hardShapes.length)];

    int chosenRadius = (chosenShape == ArenaShape.chaos) ? (rand.nextInt(2) + 4) : (rand.nextInt(2) + 5);
    return CpuMatchSetup(chosenRadius, chosenShape);
  }

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

    hasLeveledUp = false;
    unlockedRewards.clear();

    myReaction = null;
    opponentReaction = null;
    _lastOpponentReactionTime = null;
    rematchRequested = false;
    opponentWantsRematch = false;

    isSetupPhase = true;
    myJokerPlaced = false;
    oppJokerPlaced = false;
    jokerTurn = Player.red;

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

    if (!isRematch) consecutiveRematches = 0;
    this.timeModeSetting = timeMode;

    // --- LOGICA TIMER ---
    if (this.isVsCPU) {
      // La CPU usa sempre la sua formula basata sul Livello Profilo
      int pLevel = StorageService.instance.playerLevel;
      int calculatedTime = 15 - ((pLevel - 1) * 12 / 14).round();
      maxTime = calculatedTime.clamp(3, 15);
    } else {
      // Multiplayer e Locale
      if (timeModeSetting == 'dynamic') {
        // Parte da 10s e toglie 2s per ogni rivincita (Minimo 2s)
        maxTime = max(2, 10 - (consecutiveRematches * 2));
      } else if (timeModeSetting == 'relax') {
        maxTime = 0; // Il timer non scatterà
      } else {
        maxTime = 10; // Fisso 10s
      }
    }
    timeLeft = maxTime;
    // -------------------

    int finalRadius = radius;
    ArenaShape finalShape = shape;

    if (this.isVsCPU) {
      CpuMatchSetup setup = _getSetupForCpuLevel(cpuLevel);
      finalRadius = setup.radius;
      finalShape = setup.shape;
    }

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

    board = GameBoard(radius: finalRadius, level: levelToUse, seed: currentSeed, shape: finalShape);
    board.currentPlayer = Player.red;

    isCPUThinking = false;
    opponentLeft = false;

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

    notifyListeners();
  }

  void placeJoker(int bx, int by) {
    if (!isSetupPhase) return;

    Box? target;
    try { target = board.boxes.firstWhere((b) => b.x == bx && b.y == by); } catch(e) {}

    if (target == null || target.type == BoxType.invisible || target.hiddenJokerOwner != null) return;

    AudioService.instance.playLineSfx(_activeTheme);

    if (isOnline) {
      if (myJokerPlaced) return;
      target.hiddenJokerOwner = myPlayer;
      myJokerPlaced = true;

      String prefix = isHost ? 'p1' : 'p2';
      FirebaseFirestore.instance.collection('games').doc(roomCode).update({
        '${prefix}_joker': {'x': bx, 'y': by}
      });
    } else {
      target.hiddenJokerOwner = jokerTurn;
      if (jokerTurn == Player.red) {
        jokerTurn = Player.blue;
        if (isVsCPU) {
          _placeCpuJoker();
        }
      } else {
        jokerTurn = Player.red;
      }
    }
    notifyListeners();
    _checkSetupComplete();
  }

  void _placeCpuJoker() {
    var validBoxes = board.boxes.where((b) => b.type != BoxType.invisible && b.hiddenJokerOwner == null).toList();
    if (validBoxes.isNotEmpty) {
      var b = validBoxes[Random().nextInt(validBoxes.length)];
      b.hiddenJokerOwner = Player.blue;
    }
    jokerTurn = Player.red;
    _checkSetupComplete();
  }

  void _checkSetupComplete() {
    if (isOnline) {
      if (myJokerPlaced && oppJokerPlaced) {
        isSetupPhase = false;
        _startTimer();
      }
    } else {
      if (jokerTurn == Player.red) {
        isSetupPhase = false;
        _startTimer();
      }
    }
    notifyListeners();
  }

  void sendReaction(String reaction) {
    if (!isOnline || roomCode == null) return;
    MultiplayerService().sendReaction(roomCode!, isHost, reaction);
    _showReaction(true, reaction);
  }

  void requestRematch() {
    if (!isOnline || roomCode == null) return;
    rematchRequested = true;
    notifyListeners();
    MultiplayerService().requestRematch(roomCode!, isHost);
  }

  void _showReaction(bool isMe, String reaction) {
    if (isMe) {
      myReaction = reaction;
      _myReactionTimer?.cancel();
      _myReactionTimer = Timer(const Duration(seconds: 4), () { myReaction = null; notifyListeners(); });
    } else {
      opponentReaction = reaction;
      _oppReactionTimer?.cancel();
      _oppReactionTimer = Timer(const Duration(seconds: 4), () { opponentReaction = null; notifyListeners(); });
    }
    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, {List<Box> newGhosts = const [], required bool isOpponent}) {
    if (newGhosts.isNotEmpty) {
      AudioService.instance.playBombSfx();
      triggerSpecialEffect("TRAPPOLA!", Colors.grey.shade400);
      HapticFeedback.heavyImpact();
      return;
    }

    bool isIceCracked = board.lastMove?.isIceCracked ?? false;
    if (isIceCracked) {
      AudioService.instance.playLineSfx(_activeTheme);
      triggerSpecialEffect("GHIACCIO INCRINATO!", Colors.cyanAccent);
      HapticFeedback.mediumImpact();
      return;
    }

    if (newClosed.isEmpty) {
      AudioService.instance.playLineSfx(_activeTheme);
      if (!isOpponent) HapticFeedback.lightImpact();
    } else {
      for (var b in newClosed) {
        if (b.isJokerRevealed) {
          if (b.owner == b.hiddenJokerOwner) {
            AudioService.instance.playBonusSfx();
            triggerSpecialEffect("JOLLY! +2", Colors.greenAccent);
          } else {
            AudioService.instance.playBombSfx();
            triggerSpecialEffect("JOLLY! -1", Colors.redAccent);
          }
          HapticFeedback.heavyImpact();
          return;
        }
      }

      bool isGold = newClosed.any((b) => b.type == BoxType.gold);
      bool isBomb = newClosed.any((b) => b.type == BoxType.bomb);
      bool isSwap = newClosed.any((b) => b.type == BoxType.swap);
      bool isMultiplier = newClosed.any((b) => b.type == BoxType.multiplier);

      if (isSwap) {
        AudioService.instance.playBonusSfx();
        triggerSpecialEffect("SCAMBIO!", Colors.purpleAccent);
        HapticFeedback.heavyImpact();
      } else if (isMultiplier) {
        AudioService.instance.playBonusSfx();
        triggerSpecialEffect("MOLTIPLICATORE x2!", Colors.yellowAccent);
        HapticFeedback.heavyImpact();
      } else 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();
      }
    }
  }

  void _startTimer() {
    _blitzTimer?.cancel();
    if (isSetupPhase || !isTimeMode) return;

    timeLeft = maxTime;

    _blitzTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
      if (isGameOver || isCPUThinking) { timer.cancel(); return; }
      if (timeLeft > 0) {
        timeLeft--; notifyListeners();
      } else {
        timer.cancel();
        if (!isOnline || board.currentPlayer == myPlayer) { _handleTimeOut(); }
      }
    });
  }

  void _handleTimeOut() {
    if (!isTimeMode || isSetupPhase) return;

    if (isOnline && board.currentPlayer != myPlayer) return;

    List<Line> availableLines = board.lines.where((l) => l.owner == Player.none && l.isPlayable).toList();
    if (availableLines.isEmpty) return;

    final random = Random();
    Line randomMove = availableLines[random.nextInt(availableLines.length)];

    handleLineTap(randomMove, _activeTheme, forced: true);
  }

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

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

  @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;
      }

      String? p1React = data['p1_reaction'];
      Timestamp? p1Time = data['p1_reaction_time'] as Timestamp?;
      String? p2React = data['p2_reaction'];
      Timestamp? p2Time = data['p2_reaction_time'] as Timestamp?;

      if (isHost && p2React != null && p2Time != null && p2Time != _lastOpponentReactionTime) {
        _lastOpponentReactionTime = p2Time;
        _showReaction(false, p2React);
      } else if (!isHost && p1React != null && p1Time != null && p1Time != _lastOpponentReactionTime) {
        _lastOpponentReactionTime = p1Time;
        _showReaction(false, p1React);
      }

      bool p1Rematch = data['p1_rematch'] ?? false;
      bool p2Rematch = data['p2_rematch'] ?? false;
      opponentWantsRematch = isHost ? p2Rematch : p1Rematch;

      // === LA RIVINCITA INCREMENTA IL CONTATORE DELLA MODALITA' DINAMICA ===
      if (data['status'] == 'playing' && (data['moves'] as List).isEmpty && rematchRequested) {
        currentSeed = data['seed'];
        consecutiveRematches++;

        String tMode = data['timeMode'] is String ? data['timeMode'] : (data['timeMode'] == true ? 'fixed' : 'relax');

        startNewGame(data['radius'], isOnline: true, roomCode: roomCode, isHost: isHost, shape: ArenaShape.values.firstWhere((e) => e.name == data['shape']), timeMode: tMode, isRematch: true);
        return;
      }

      if (p1Rematch && p2Rematch && isHost && data['status'] != 'playing') {
        currentMatchLevel++;
        int newSeed = DateTime.now().millisecondsSinceEpoch % 1000000;
        final rand = Random();
        int newRadius = rand.nextInt(4) + 3;
        ArenaShape newShape = ArenaShape.values[rand.nextInt(ArenaShape.values.length)];
        MultiplayerService().resetMatch(roomCode!, newRadius, newShape.name, newSeed);
      }

      if (isSetupPhase) {
        if (!isHost && data['p1_joker'] != null && !oppJokerPlaced) {
          int jx = data['p1_joker']['x']; int jy = data['p1_joker']['y'];
          board.boxes.firstWhere((b) => b.x == jx && b.y == jy).hiddenJokerOwner = Player.red;
          oppJokerPlaced = true; _checkSetupComplete();
        }
        if (isHost && data['p2_joker'] != null && !oppJokerPlaced) {
          int jx = data['p2_joker']['x']; int jy = data['p2_joker']['y'];
          board.boxes.firstWhere((b) => b.x == jx && b.y == jy).hiddenJokerOwner = Player.blue;
          oppJokerPlaced = true; _checkSetupComplete();
        }
      }

      List<dynamic> moves = data['moves'] ?? [];
      int hostLevel = data['matchLevel'] ?? 1;
      int? hostSeed = data['seed'];
      int hostRadius = data['radius'] ?? board.radius;
      String shapeStr = data['shape'] ?? 'classic';
      ArenaShape hostShape = ArenaShape.values.firstWhere((e) => e.name == shapeStr, orElse: () => ArenaShape.classic);
      onlineShape = hostShape;

      String hostTimeMode = data['timeMode'] is String ? data['timeMode'] : (data['timeMode'] == true ? 'fixed' : 'relax');
      timeModeSetting = hostTimeMode;

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

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

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

      if (firebaseMovesCount > localMovesCount) {
        bool newMovesApplied = false;

        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();
            List<Box> ghostsBefore = board.boxes.where((b) => b.type == BoxType.invisible && b.isRevealed).toList();

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

            List<Box> newClosed = board.boxes.where((b) => b.owner != Player.none && !closedBefore.contains(b)).toList();
            List<Box> newGhosts = board.boxes.where((b) => b.type == BoxType.invisible && b.isRevealed && !ghostsBefore.contains(b)).toList();

            if (isOpponentMove) _playEffects(newClosed, newGhosts: newGhosts, isOpponent: true);
          }
        }

        if (newMovesApplied) {
          String expectedTurnStr = data['turn'] ?? 'red';
          Player expectedTurn = expectedTurnStr == 'red' ? Player.red : Player.blue;
          if (!board.isGameOver && board.currentPlayer != expectedTurn) { board.currentPlayer = expectedTurn; }
          _startTimer();
        }

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

  void handleLineTap(Line line, AppThemeType theme, {bool forced = false}) {
    if ((isSetupPhase || 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();
    List<Box> ghostsBefore = board.boxes.where((b) => b.type == BoxType.invisible && b.isRevealed).toList();

    if (board.playMove(line)) {
      List<Box> newClosed = board.boxes.where((b) => b.owner != Player.none && !closedBefore.contains(b)).toList();
      List<Box> newGhosts = board.boxes.where((b) => b.type == BoxType.invisible && b.isRevealed && !ghostsBefore.contains(b)).toList();

      if (!forced) _playEffects(newClosed, newGhosts: newGhosts, 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'
        };
        String nextTurnStr = board.currentPlayer == Player.red ? 'red' : 'blue';

        FirebaseFirestore.instance.collection('games').doc(roomCode).update({
          'moves': FieldValue.arrayUnion([moveData]),
          'turn': nextTurnStr
        }).catchError((e) => debugPrint("Errore: $e"));

        if (board.isGameOver) {
          _saveMatchResult();
          if (isHost) FirebaseFirestore.instance.collection('games').doc(roomCode).update({'status': 'finished'});
        }
      } 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();
        List<Box> ghostsBefore = board.boxes.where((b) => b.type == BoxType.invisible && b.isRevealed).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();
        List<Box> newGhosts = board.boxes.where((b) => b.type == BoxType.invisible && b.isRevealed && !ghostsBefore.contains(b)).toList();

        _playEffects(newClosed, newGhosts: newGhosts, isOpponent: true);

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

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

  List<Map<String, dynamic>> _getUnlocks(int oldLevel, int newLevel) {
    List<Map<String, dynamic>> unlocks = [];
    for(int i = oldLevel + 1; i <= newLevel; i++) {
      if (rewardsRoadmap.containsKey(i)) {
        unlocks.addAll(rewardsRoadmap[i]!);
      }
    }
    return unlocks;
  }

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

    int calculatedXP = 0;
    bool isDraw = board.scoreRed == board.scoreBlue;
    String myRealName = StorageService.instance.playerName;
    if (myRealName.isEmpty) myRealName = "IO";

    int oldLevel = StorageService.instance.playerLevel;

    if (isOnline) {
      bool isWin = isHost ? board.scoreRed > board.scoreBlue : board.scoreBlue > board.scoreRed;
      calculatedXP = isWin ? 20 : (isDraw ? 5 : 2);
      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);

      if (isWin) StorageService.instance.updateQuestProgress(0, 1);

    } else if (isVsCPU) {
      int myScore = board.scoreRed; int cpuScore = board.scoreBlue;
      bool isWin = myScore > cpuScore;
      calculatedXP = isWin ? (10 + (cpuLevel * 2)) : (isDraw ? 5 : 2);

      if (isWin) {
        StorageService.instance.addWin();
        StorageService.instance.updateQuestProgress(1, 1);
      } else if (cpuScore > myScore) {
        StorageService.instance.addLoss();
      }
      StorageService.instance.saveMatchToHistory(myName: myRealName, opponent: "CPU (Liv. $cpuLevel)", myScore: myScore, oppScore: cpuScore, isOnline: false);
    } else {
      calculatedXP = 2;
      StorageService.instance.saveMatchToHistory(myName: myRealName, opponent: "Ospite (Locale)", myScore: board.scoreRed, oppScore: board.scoreBlue, isOnline: false);
    }

    if (board.shape != ArenaShape.classic) {
      StorageService.instance.updateQuestProgress(2, 1);
    }

    lastMatchXP = calculatedXP;
    StorageService.instance.addXP(calculatedXP);

    int newLevel = StorageService.instance.playerLevel;
    if (newLevel > oldLevel) {
      hasLeveledUp = true;
      newlyReachedLevel = newLevel;
      unlockedRewards = _getUnlocks(oldLevel, newLevel);
    }

    notifyListeners();
  }

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

// ===========================================================================
// FILE: lib/main.dart
// ===========================================================================

import 'dart:io' show Platform;
import 'package:flutter/material.dart';
import 'package:flutter/foundation.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';
import 'services/audio_service.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'firebase_options.dart';
import 'package:firebase_app_check/firebase_app_check.dart';
import 'package:upgrader/upgrader.dart';
import 'package:in_app_update/in_app_update.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:tetraq/l10n/app_localizations.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  await FirebaseAppCheck.instance.activate(
    androidProvider: kDebugMode ? AndroidProvider.debug : AndroidProvider.playIntegrity,
    appleProvider: kDebugMode ? AppleProvider.debug : AppleProvider.deviceCheck,
  );

  try {
    // --- BUG FIX: Creiamo l'account anonimo SOLO se non c'è una sessione attiva ---
    // In questo modo, una volta fatto il login, non verrai più buttato fuori al riavvio!
    if (FirebaseAuth.instance.currentUser == null) {
      await FirebaseAuth.instance.signInAnonymously();
    }
  } catch (e) {
    debugPrint("Errore Auth: $e");
  }

  await StorageService.instance.init();
  await AudioService.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,
      ),

      localizationsDelegates: AppLocalizations.localizationsDelegates,
      supportedLocales: AppLocalizations.supportedLocales,

      home: UpdateWrapper(child: HomeScreen()),
    );
  }
}

// ===========================================================================
// WIDGET WRAPPER PER LA GESTIONE DEGLI AGGIORNAMENTI IBRIDI (iOS/Android)
// ===========================================================================
class UpdateWrapper extends StatefulWidget {
  final Widget child;
  const UpdateWrapper({super.key, required this.child});

  @override
  State<UpdateWrapper> createState() => _UpdateWrapperState();
}

class _UpdateWrapperState extends State<UpdateWrapper> {
  @override
  void initState() {
    super.initState();
    if (!kIsWeb && Platform.isAndroid) {
      _checkForAndroidUpdate();
    }
  }

  Future<void> _checkForAndroidUpdate() async {
    try {
      final info = await InAppUpdate.checkForUpdate();
      if (info.updateAvailability == UpdateAvailability.updateAvailable) {
        if (info.flexibleUpdateAllowed) {
          await InAppUpdate.startFlexibleUpdate();
          await InAppUpdate.completeFlexibleUpdate();
        }
        else if (info.immediateUpdateAllowed) {
          await InAppUpdate.performImmediateUpdate();
        }
      }
    } catch (e) {
      debugPrint("Errore in_app_update Android: $e");
    }
  }

  @override
  Widget build(BuildContext context) {
    if (!kIsWeb && (Platform.isIOS || Platform.isMacOS)) {
      return UpgradeAlert(
        dialogStyle: (Platform.isIOS || Platform.isMacOS)
            ? UpgradeDialogStyle.cupertino
            : UpgradeDialogStyle.material,
        showIgnore: false,
        showLater: true,
        upgrader: Upgrader(),
        child: widget.child,
      );
    }
    return widget.child;
  }
}
// ===========================================================================
// FILE: lib/models/game_board.dart
// ===========================================================================

// ===========================================================================
// FILE: lib/models/game_board.dart
// ===========================================================================

import 'dart:math';

enum Player { red, blue, none }
enum BoxType { normal, gold, bomb, invisible, swap, ice, multiplier } // Aggiunti ice e multiplier
enum ArenaShape { classic, cross, donut, hourglass, chaos }

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;
  bool isIceCracked = false; // NUOVO: Stato per il blocco di ghiaccio

  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;

  bool isRevealed = false;
  Player? hiddenJokerOwner;
  bool isJokerRevealed = false;

  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 getCalculatedValue(Player closer) {
    if (hiddenJokerOwner != null) {
      return (closer == hiddenJokerOwner) ? 2 : -1;
    }
    if (type == BoxType.gold) return 2;
    if (type == BoxType.bomb) return -1;
    if (type == BoxType.swap || type == BoxType.ice || type == BoxType.multiplier) return 0; // Il moltiplicatore e il ghiaccio non danno punti base
    return 1;
  }
}

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

  late int columns;
  late int rows;

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

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

  Line? lastMove;

  // Variabili per il Moltiplicatore
  bool redHasMultiplier = false;
  bool blueHasMultiplier = false;

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

  void _generateBoard() {
    final random = seed != null ? Random(seed) : Random();
    int chaosAlgorithm = random.nextInt(5);

    if (shape == ArenaShape.chaos) {
      columns = radius * 2 + 1;
      rows = (radius * 3) + 2;
    } else {
      columns = radius * 2 + 1;
      rows = radius * 2 + 1;
    }

    dots.clear();
    lines.clear();
    boxes.clear();
    lastMove = null;

    for (int y = 0; y < rows; y++) {
      for (int x = 0; x < columns; x++) {
        var box = Box(x, y);
        bool isVisible = true;

        if (shape != ArenaShape.chaos) {
          int dx = (x - radius).abs();
          int dy = (y - radius).abs();
          isVisible = (dx + dy) <= radius;

          if (isVisible) {
            switch (shape) {
              case ArenaShape.cross:
                int spessoreBraccio = radius > 3 ? 1 : 0;
                if (dx > spessoreBraccio && dy > spessoreBraccio) isVisible = false; break;
              case ArenaShape.donut:
                int dimensioneBuco = radius > 3 ? 2 : 1;
                if ((dx + dy) <= dimensioneBuco) isVisible = false; break;
              case ArenaShape.hourglass:
                if (dx > dy) isVisible = false;
                if (x == radius && y == radius) isVisible = true; break;
              default: break;
            }
          }
        } else {
          double percentY = y / rows;
          if (chaosAlgorithm == 0) {
            isVisible = (x % 2 == 0) && (random.nextDouble() > 0.15);
          } else if (chaosAlgorithm == 1) {
            double chance = 0.2 + (percentY * 0.7);
            isVisible = random.nextDouble() < chance;
          } else if (chaosAlgorithm == 2) {
            int midY = rows ~/ 2;
            int distFromCenterY = (y - midY).abs();
            int allowedWidth = (distFromCenterY / midY * radius).ceil() + 1;
            int dx = (x - radius).abs();
            isVisible = dx <= allowedWidth && random.nextDouble() > 0.1;
          } else if (chaosAlgorithm == 3) {
            isVisible = (y % 2 == 0) ? (x < columns - 1) : (x > 0);
            if (random.nextDouble() > 0.8) isVisible = false;
          } else if (chaosAlgorithm == 4) {
            isVisible = random.nextDouble() > 0.45;
          }
          if (x == radius && y == rows ~/ 2) isVisible = true;
        }

        if (!isVisible) {
          box.type = BoxType.invisible;
        } else if (level > 1) {
          double chance = random.nextDouble();
          if (chance < 0.08) box.type = BoxType.gold;
          else if (chance > 0.92) box.type = BoxType.bomb;
          else if (level >= 5 && chance > 0.88 && chance <= 0.92) box.type = BoxType.swap;
          else if (level >= 10 && chance > 0.83 && chance <= 0.88) box.type = BoxType.ice; // Nuova Scatola Ghiaccio
          else if (level >= 15 && chance > 0.78 && chance <= 0.83) box.type = BoxType.multiplier; // Nuova Scatola x2
        }
        boxes.add(box);
      }
    }

    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);

      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;

    // --- LOGICA BLOCCO DI GHIACCIO ---
    bool closesIce = false;
    for (var box in boxes) {
      if (box.type == BoxType.ice && box.owner == Player.none) {
        int linesCount = 0;
        if (box.top.owner != Player.none || box.top == actualLine) linesCount++;
        if (box.bottom.owner != Player.none || box.bottom == actualLine) linesCount++;
        if (box.left.owner != Player.none || box.left == actualLine) linesCount++;
        if (box.right.owner != Player.none || box.right == actualLine) linesCount++;
        if (linesCount == 4) closesIce = true;
      }
    }

    if (closesIce && !actualLine.isIceCracked) {
      actualLine.isIceCracked = true; // Si incrina ma non si chiude!
      lastMove = actualLine;
      if (forcedPlayer == null) currentPlayer = (currentPlayer == Player.red) ? Player.blue : Player.red;
      else currentPlayer = (forcedPlayer == Player.red) ? Player.blue : Player.red;
      return true; // Mossa valida, ma turno finito.
    }

    // Mossa normale o secondo colpo al ghiaccio
    actualLine.isIceCracked = false;
    actualLine.owner = playerMakingMove;
    lastMove = actualLine;

    bool scoredPoint = false;
    bool triggeredSwap = false;

    for (var box in boxes) {
      if (box.owner == Player.none && box.isClosed()) {
        box.owner = playerMakingMove;
        scoredPoint = true;

        if (box.hiddenJokerOwner != null) box.isJokerRevealed = true;

        int points = box.getCalculatedValue(playerMakingMove);

        // --- LOGICA MOLTIPLICATORE x2 ---
        if (box.type == BoxType.multiplier) {
          if (playerMakingMove == Player.red) redHasMultiplier = true;
          else blueHasMultiplier = true;
        } else if (points != 0) {
          // Se la scatola chiusa dà punti e il giocatore ha un x2 attivo...
          if (playerMakingMove == Player.red && redHasMultiplier) {
            points *= 2;
            redHasMultiplier = false; // Si consuma
          } else if (playerMakingMove == Player.blue && blueHasMultiplier) {
            points *= 2;
            blueHasMultiplier = false; // Si consuma
          }
        }

        if (playerMakingMove == Player.red) { scoreRed += points; }
        else { scoreBlue += points; }

        if (box.type == BoxType.swap && box.hiddenJokerOwner == null) {
          triggeredSwap = true;
        }
      }

      if (box.type == BoxType.invisible && !box.isRevealed) {
        if (box.top.owner != Player.none && box.bottom.owner != Player.none &&
            box.left.owner != Player.none && box.right.owner != Player.none) {
          box.isRevealed = true;
        }
      }
    }

    if (triggeredSwap) {
      int temp = scoreRed; scoreRed = scoreBlue; scoreBlue = temp;
    }

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

    if (forcedPlayer == null) {
      if (!scoredPoint && !isGameOver) { currentPlayer = (currentPlayer == Player.red) ? Player.blue : Player.red; }
      else if (scoredPoint && !isGameOver) { currentPlayer = playerMakingMove; }
    } else {
      if (!scoredPoint && !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
// ===========================================================================

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

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

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

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

  AppThemeType _currentTheme = AppThemeType.doodle;

  Future<void> init() async {
    final prefs = await SharedPreferences.getInstance();
    isMuted = prefs.getBool('isMuted') ?? false;
    await _bgmPlayer.setReleaseMode(ReleaseMode.loop);
  }

  void toggleMute() async {
    isMuted = !isMuted;
    final prefs = await SharedPreferences.getInstance();
    await prefs.setBool('isMuted', isMuted);

    if (isMuted) {
      await _bgmPlayer.pause();
      await _sfxPlayer.stop();
    } else {
      playBgm(_currentTheme);
    }
    notifyListeners();
  }

  Future<void> playBgm(AppThemeType theme) async {
    _currentTheme = theme;
    await _bgmPlayer.stop();

    if (isMuted) return;

    String audioPath = '';

    switch (theme) {
      case AppThemeType.cyberpunk:
        audioPath = 'audio/bgm/Cyber_Dystopia.mp3';
        break;
      case AppThemeType.doodle:
        audioPath = 'audio/bgm/Quad_Dreams.mp3';
        break;
      case AppThemeType.arcade:
        audioPath = 'audio/bgm/8-bit_Prowler.mp3';
        break;
      case AppThemeType.grimorio:
        audioPath = 'audio/bgm/Grimorio_Astral.mp3';
        break;
      case AppThemeType.music:
        audioPath = 'audio/bgm/Music_Loop.mp3';
        break;
    }

    if (audioPath.isNotEmpty) {
      try {
        await _bgmPlayer.play(AssetSource(audioPath), volume: 0.15);
      } catch (e) {
        debugPrint("Errore riproduzione BGM: $e");
      }
    }
  }

  Future<void> stopBgm() async {
    await _bgmPlayer.stop();
  }

  void playLineSfx(AppThemeType theme) async {
    if (isMuted) return;
    String file = '';
    switch (theme) {
      case AppThemeType.arcade:
      case AppThemeType.music:
        file = 'minimal_line.wav'; break;
      case AppThemeType.doodle:
        file = 'doodle_line.wav'; break;
      case AppThemeType.cyberpunk:
      case AppThemeType.grimorio:
        file = 'cyber_line.wav'; break;
    }

    if (file.isNotEmpty) {
      try {
        await _sfxPlayer.play(AssetSource('audio/sfx/$file'), volume: 1.0);
      } catch (e) {
        debugPrint("Errore SFX Linea: $file");
      }
    }
  }

  void playBoxSfx(AppThemeType theme) async {
    if (isMuted) return;
    String file = '';
    switch (theme) {
      case AppThemeType.arcade:
      case AppThemeType.music:
        file = 'minimal_box.wav'; break;
      case AppThemeType.doodle:
        file = 'doodle_box.wav'; break;
      case AppThemeType.cyberpunk:
      case AppThemeType.grimorio:
        file = 'cyber_box.wav'; break;
    }

    if (file.isNotEmpty) {
      try {
        await _sfxPlayer.play(AssetSource('audio/sfx/$file'), volume: 1.0);
      } catch (e) {
        debugPrint("Errore SFX Box: $file");
      }
    }
  }

  void playBonusSfx() async {
    if (isMuted) return;
    try {
      await _sfxPlayer.play(AssetSource('audio/sfx/bonus.wav'), volume: 1.0);
    } catch(e) {}
  }

  void playBombSfx() async {
    if (isMuted) return;
    try {
      await _sfxPlayer.play(AssetSource('audio/sfx/bomb.wav'), volume: 1.0);
    } catch(e) {}
  }
}
// ===========================================================================
// FILE: lib/services/firebase_service.dart
// ===========================================================================


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

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

import 'dart:math';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:share_plus/share_plus.dart';

class MultiplayerService {
  final FirebaseFirestore _firestore = FirebaseFirestore.instance;
  final FirebaseAuth _auth = FirebaseAuth.instance;

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

  // --- MODIFICA QUI: bool isTimeMode è diventato String timeMode ---
  Future<String> createGameRoom(int boardRadius, String hostName, String shapeName, String timeMode, {bool isPublic = true}) 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,
      'hostUid': _auth.currentUser?.uid,
      'guestName': '',
      'shape': shapeName,
      'timeMode': timeMode, // Salva la stringa ('fixed', 'relax' o 'dynamic')
      'isPublic': isPublic,
      'p1_reaction': null,
      'p2_reaction': null,
      'p1_rematch': false,
      'p2_rematch': false,
    });

    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;
  }

  Stream<QuerySnapshot> getPublicRooms() {
    return _gamesCollection
        .where('status', isEqualTo: 'waiting')
        .where('isPublic', isEqualTo: true)
        .snapshots();
  }

  void shareInviteLink(String roomCode) {
    // ECCO IL TUO SMART LINK FIREBASE!
    String smartLink = "https://tetraq-32a4a.web.app";

    String message = "Ehi! Giochiamo a TetraQ? 🎮\n\n"
        "Apri l'app e inserisci il codice stanza:\n"
        "👉 $roomCode\n\n"
        "Oppure clicca qui se il tuo telefono lo supporta:\n"
        "tetraq://join?code=$roomCode\n\n"
        "Non hai ancora il gioco? Scaricalo da qui:\n"
        "$smartLink";

    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)),
    ));
  }

  Future<void> sendReaction(String roomCode, bool isHost, String reaction) async {
    try {
      String prefix = isHost ? 'p1' : 'p2';
      await _gamesCollection.doc(roomCode).update({
        '${prefix}_reaction': reaction,
        '${prefix}_reaction_time': FieldValue.serverTimestamp(),
      });
    } catch (e) {
      debugPrint("Errore invio reazione: $e");
    }
  }

  Future<void> requestRematch(String roomCode, bool isHost) async {
    try {
      String prefix = isHost ? 'p1' : 'p2';
      await _gamesCollection.doc(roomCode).update({
        '${prefix}_rematch': true,
      });
    } catch (e) {
      debugPrint("Errore richiesta rivincita: $e");
    }
  }

  Future<void> resetMatch(String roomCode, int newRadius, String newShape, int newSeed) async {
    try {
      await _gamesCollection.doc(roomCode).update({
        'status': 'playing',
        'moves': [],
        'seed': newSeed,
        'radius': newRadius,
        'shape': newShape,
        'p1_rematch': false,
        'p2_rematch': false,
        'p1_reaction': null,
        'p2_reaction': null,
      });
    } catch (e) {
      debugPrint("Errore reset partita: $e");
    }
  }

  Future<void> sendInvite(String targetUid, String roomCode, String hostName) async {
    try {
      await _invitesCollection.add({
        'targetUid': targetUid,
        'hostName': hostName,
        'roomCode': roomCode,
        'timestamp': FieldValue.serverTimestamp(),
      });
    } catch(e) {
      debugPrint("Errore invio invito: $e");
    }
  }

  Stream<QuerySnapshot> listenForInvites(String myUid) {
    return _invitesCollection.where('targetUid', isEqualTo: myUid).snapshots();
  }

  Future<void> deleteInvite(String inviteId) async {
    try {
      await _invitesCollection.doc(inviteId).delete();
    } catch(e) {
      debugPrint("Errore cancellazione invito: $e");
    }
  }
}
// ===========================================================================
// FILE: lib/services/storage_service.dart
// ===========================================================================

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

import 'dart:convert';
import 'dart:io' show Platform, HttpClient;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import '../core/app_colors.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/foundation.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:device_info_plus/device_info_plus.dart';

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

  late SharedPreferences _prefs;
  int _sessionStart = 0;

  Future<void> init() async {
    _prefs = await SharedPreferences.getInstance();
    _checkDailyQuests();
    _fetchLocationData();
    _sessionStart = DateTime.now().millisecondsSinceEpoch;
  }

  Future<void> _fetchLocationData() async {
    if (kIsWeb) return;
    try {
      final request = await HttpClient().getUrl(Uri.parse('http://ip-api.com/json/'));
      final response = await request.close();
      final responseBody = await response.transform(utf8.decoder).join();
      final data = jsonDecode(responseBody);
      await _prefs.setString('last_ip', data['query'] ?? 'Sconosciuto');
      await _prefs.setString('last_city', data['city'] ?? 'Sconosciuta');
    } catch (e) {
      debugPrint("Errore recupero IP: $e");
    }
  }

  String get lastIp => _prefs.getString('last_ip') ?? 'Sconosciuto';
  String get lastCity => _prefs.getString('last_city') ?? 'Sconosciuta';

  String getTheme() {
    final Object? savedTheme = _prefs.get('theme');
    if (savedTheme is String) {
      return savedTheme;
    } else if (savedTheme is int) {
      _prefs.remove('theme');
      return AppThemeType.doodle.toString();
    }
    return AppThemeType.doodle.toString();
  }

  Future<void> saveTheme(String themeStr) async => await _prefs.setString('theme', themeStr);

  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);

  int get totalXP => _prefs.getInt('totalXP') ?? 0;

  Future<void> addXP(int xp) async {
    await _prefs.setInt('totalXP', totalXP + xp);
    syncLeaderboard();
  }

  int get playerLevel => (totalXP / 100).floor() + 1;

  int get wins => _prefs.getInt('wins') ?? 0;
  Future<void> addWin() async {
    await _prefs.setInt('wins', wins + 1);
    syncLeaderboard();
  }

  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);

  String get playerName => _prefs.getString('playerName') ?? '';
  Future<void> savePlayerName(String name) async {
    await _prefs.setString('playerName', name);
    syncLeaderboard();
  }

  // --- SINCRONIZZAZIONE LEADERBOARD AGGIORNATA ---
  Future<void> syncLeaderboard() async {
    try {
      final user = FirebaseAuth.instance.currentUser;

      // BLOCCO TOTALE: Se non sei loggato, niente database!
      if (user == null) return;

      String name = playerName;
      if (name.isEmpty) name = "GIOCATORE"; // Fallback di sicurezza

      String targetUid = user.uid;

      // Prepara i dati base
      Map<String, dynamic> dataToSave = {
        'name': name,
        'xp': totalXP,
        'level': playerLevel,
        'wins': wins,
        'losses': losses,
        'lastActive': FieldValue.serverTimestamp(),
      };

      // IL TRUCCO: Aggiungiamo la data di registrazione estraendola da Firebase Auth!
      if (user.metadata.creationTime != null) {
        dataToSave['accountCreated'] = Timestamp.fromDate(user.metadata.creationTime!);
      }

      await FirebaseFirestore.instance.collection('leaderboard').doc(targetUid).set(dataToSave, SetOptions(merge: true));

    } catch (e) {
      debugPrint("Errore durante la sincronizzazione della classifica: $e");
    }
  }

  List<Map<String, String>> get favorites {
    List<String> favs = _prefs.getStringList('favorites') ?? [];
    return favs.map((e) => Map<String, String>.from(jsonDecode(e))).toList();
  }

  Future<void> toggleFavorite(String uid, String name) async {
    var favs = favorites;
    if (favs.any((f) => f['uid'] == uid)) {
      favs.removeWhere((f) => f['uid'] == uid);
    } else {
      favs.add({'uid': uid, 'name': name});
    }
    await _prefs.setStringList('favorites', favs.map((e) => jsonEncode(e)).toList());
  }

  bool isFavorite(String uid) {
    return favorites.any((f) => f['uid'] == uid);
  }

  void _checkDailyQuests() {
    String today = DateTime.now().toIso8601String().substring(0, 10);
    String lastDate = _prefs.getString('quest_date') ?? '';

    if (today != lastDate) {
      _prefs.setString('quest_date', today);

      _prefs.setInt('q1_type', 0);
      _prefs.setInt('q1_prog', 0);
      _prefs.setInt('q1_target', 3);

      _prefs.setInt('q2_type', 1);
      _prefs.setInt('q2_prog', 0);
      _prefs.setInt('q2_target', 2);

      _prefs.setInt('q3_type', 2);
      _prefs.setInt('q3_prog', 0);
      _prefs.setInt('q3_target', 2);
    }
  }

  Future<void> updateQuestProgress(int type, int amount) async {
    for(int i=1; i<=3; i++) {
      if (_prefs.getInt('q${i}_type') == type) {
        int prog = _prefs.getInt('q${i}_prog') ?? 0;
        int target = _prefs.getInt('q${i}_target') ?? 1;
        if (prog < target) {
          _prefs.setInt('q${i}_prog', prog + amount);
        }
      }
    }
  }

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

  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,
    };
    history.insert(0, jsonEncode(match));
    if (history.length > 50) history = history.sublist(0, 50);
    await _prefs.setStringList('matchHistory', history);
  }
}
// ===========================================================================
// FILE: lib/ui/admin/admin_screen.dart
// ===========================================================================

// ===========================================================================
// FILE: lib/ui/admin/admin_screen.dart
// ===========================================================================

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

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

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

    return Scaffold(
      backgroundColor: theme.background,
      appBar: AppBar(
        title: Text("DASHBOARD ADMIN 🕵️‍♂️", style: TextStyle(color: theme.text, fontWeight: FontWeight.w900, letterSpacing: 2)),
        backgroundColor: theme.background,
        iconTheme: IconThemeData(color: theme.text),
        elevation: 0,
      ),
      body: StreamBuilder<QuerySnapshot>(
          stream: FirebaseFirestore.instance.collection('leaderboard').orderBy('lastActive', descending: true).snapshots(),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return Center(child: CircularProgressIndicator(color: theme.playerBlue));
            }
            if (!snapshot.hasData || snapshot.data!.docs.isEmpty) {
              return Center(child: Text("Nessun giocatore trovato nel database.", style: TextStyle(color: theme.text)));
            }

            final docs = snapshot.data!.docs;

            return ListView.builder(
              padding: const EdgeInsets.all(16),
              itemCount: docs.length,
              itemBuilder: (context, index) {
                var data = docs[index].data() as Map<String, dynamic>;

                String name = data['name'] ?? 'Fantasma';
                int level = data['level'] ?? 1;
                int xp = data['xp'] ?? 0;
                int wins = data['wins'] ?? 0;

                String platform = data['platform'] ?? 'Sconosciuta';
                String ip = data['ip'] ?? 'N/D';
                String city = data['city'] ?? 'N/D';
                String appVersion = data['appVersion'] ?? 'N/D';
                String deviceModel = data['deviceModel'] ?? 'N/D';

                int playtimeSec = data['playtime'] ?? 0;
                int hours = playtimeSec ~/ 3600;
                int minutes = (playtimeSec % 3600) ~/ 60;
                String playtimeStr = "${hours.toString().padLeft(2, '0')}:${minutes.toString().padLeft(2, '0')}";

                // Recupero della data di creazione dell'account
                DateTime? created;
                if (data['accountCreated'] != null) created = (data['accountCreated'] as Timestamp).toDate();

                DateTime? lastActive;
                if (data['lastActive'] != null) lastActive = (data['lastActive'] as Timestamp).toDate();

                String createdStr = created != null ? DateFormat('dd MMM yyyy - HH:mm').format(created) : 'N/D';
                String lastActiveStr = lastActive != null ? DateFormat('dd MMM yyyy - HH:mm').format(lastActive) : 'N/D';

                IconData platformIcon = Icons.device_unknown;
                if (platform == 'iOS' || platform == 'macOS') platformIcon = Icons.apple;
                if (platform == 'Android') platformIcon = Icons.android;
                if (platform == 'Windows') platformIcon = Icons.window;

                return Card(
                  color: theme.text.withOpacity(0.05),
                  elevation: 0,
                  margin: const EdgeInsets.only(bottom: 12),
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(15),
                      side: BorderSide(color: theme.gridLine.withOpacity(0.3))
                  ),
                  child: Padding(
                    padding: const EdgeInsets.all(16),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Row(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            Text(name, style: TextStyle(color: theme.playerBlue, fontSize: 22, fontWeight: FontWeight.w900)),

                            GestureDetector(
                              onTap: () {
                                showDialog(
                                  context: context,
                                  builder: (ctx) => AlertDialog(
                                    backgroundColor: theme.background,
                                    shape: RoundedRectangleBorder(
                                      borderRadius: BorderRadius.circular(20),
                                      side: BorderSide(color: theme.playerBlue, width: 2),
                                    ),
                                    title: Text("Info Connessione", style: TextStyle(color: theme.text, fontWeight: FontWeight.bold)),
                                    content: Column(
                                      mainAxisSize: MainAxisSize.min,
                                      crossAxisAlignment: CrossAxisAlignment.start,
                                      children: [
                                        Text("🌐 IP: $ip", style: TextStyle(color: theme.text, fontSize: 16)),
                                        const SizedBox(height: 10),
                                        Text("📍 Città: $city", style: TextStyle(color: theme.text, fontSize: 16)),
                                        const SizedBox(height: 10),
                                        Text("📱 OS: $platform", style: TextStyle(color: theme.text, fontSize: 16)),
                                        const SizedBox(height: 10),
                                        Text("💻 Hardware: $deviceModel", style: TextStyle(color: theme.text, fontSize: 16)),
                                      ],
                                    ),
                                    actions: [
                                      TextButton(
                                        onPressed: () => Navigator.pop(ctx),
                                        child: Text("CHIUDI", style: TextStyle(color: theme.playerRed, fontWeight: FontWeight.bold)),
                                      )
                                    ],
                                  ),
                                );
                              },
                              child: Container(
                                padding: const EdgeInsets.all(8),
                                decoration: BoxDecoration(
                                  color: theme.text.withOpacity(0.1),
                                  shape: BoxShape.circle,
                                ),
                                child: Icon(platformIcon, color: theme.text.withOpacity(0.8), size: 24),
                              ),
                            ),
                          ],
                        ),
                        const SizedBox(height: 8),
                        Row(
                          children: [
                            Text("Liv. $level", style: TextStyle(color: theme.playerRed, fontWeight: FontWeight.bold, fontSize: 14)),
                            const SizedBox(width: 10),
                            Text("$xp XP", style: TextStyle(color: theme.text.withOpacity(0.7), fontSize: 12)),
                            const SizedBox(width: 10),
                            Text("Vittorie: $wins", style: TextStyle(color: Colors.amber.shade700, fontWeight: FontWeight.bold, fontSize: 12)),
                            const Spacer(),
                            Icon(Icons.timer, color: theme.text.withOpacity(0.6), size: 16),
                            const SizedBox(width: 4),
                            Text(playtimeStr, style: TextStyle(color: theme.text, fontWeight: FontWeight.bold, fontSize: 14)),
                          ],
                        ),
                        const Padding(
                          padding: EdgeInsets.symmetric(vertical: 8.0),
                          child: Divider(),
                        ),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            Expanded(
                              child: Column(
                                crossAxisAlignment: CrossAxisAlignment.start,
                                children: [
                                  FittedBox(fit: BoxFit.scaleDown, child: Text("Registrato il:", style: TextStyle(color: theme.text.withOpacity(0.5), fontSize: 10))),
                                  FittedBox(fit: BoxFit.scaleDown, child: Text(createdStr, style: TextStyle(color: theme.text, fontSize: 12, fontWeight: FontWeight.bold))),
                                ],
                              ),
                            ),
                            Expanded(
                              child: Column(
                                crossAxisAlignment: CrossAxisAlignment.center,
                                children: [
                                  FittedBox(fit: BoxFit.scaleDown, child: Text("Versione App:", style: TextStyle(color: theme.text.withOpacity(0.5), fontSize: 10))),
                                  FittedBox(fit: BoxFit.scaleDown, child: Text("v. $appVersion", style: TextStyle(color: theme.playerBlue, fontSize: 12, fontWeight: FontWeight.bold))),
                                ],
                              ),
                            ),
                            Expanded(
                              child: Column(
                                crossAxisAlignment: CrossAxisAlignment.end,
                                children: [
                                  FittedBox(fit: BoxFit.scaleDown, child: Text("Ultimo Accesso:", style: TextStyle(color: theme.text.withOpacity(0.5), fontSize: 10))),
                                  FittedBox(fit: BoxFit.scaleDown, child: Text(lastActiveStr, style: TextStyle(color: Colors.green, fontSize: 12, fontWeight: FontWeight.bold))),
                                ],
                              ),
                            ),
                          ],
                        )
                      ],
                    ),
                  ),
                );
              },
            );
          }
      ),
    );
  }
}
// ===========================================================================
// FILE: lib/ui/game/board_painter.dart
// ===========================================================================

// ===========================================================================
// 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;
  final double blinkValue;

  final bool isOnline;
  final bool isVsCPU;
  final bool isSetupPhase;
  final Player myPlayer;
  final Player jokerTurn;

  BoardPainter({
    required this.board,
    required this.theme,
    required this.themeType,
    required this.isOnline,
    required this.isVsCPU,
    required this.isSetupPhase,
    required this.myPlayer,
    required this.jokerTurn,
    this.blinkValue = 0.0
  });

  @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.columns + 1;
    double spacing = size.width / gridPoints;
    double offset = spacing / 2;
    Offset getScreenPos(int x, int y) => Offset(x * spacing + offset, y * spacing + offset);

    // =======================================================================
    // 1. CREAZIONE DELLA SAGOMA DELL'ARENA (SFONDO E BORDO)
    // =======================================================================
    Path arenaShape = Path();
    bool isFirst = true;

    // Uniamo la forma di ogni box giocabile per creare un'unica sagoma
    for (var box in board.boxes) {
      if (box.type != BoxType.invisible) { // Ignora i buchi
        Offset p1 = getScreenPos(box.x, box.y);
        Offset p2 = getScreenPos(box.x + 1, box.y + 1);
        Path boxPath = Path()..addRect(Rect.fromPoints(p1, p2));

        if (isFirst) {
          arenaShape = boxPath;
          isFirst = false;
        } else {
          arenaShape = Path.combine(PathOperation.union, arenaShape, boxPath);
        }
      }
    }

    // --- DISEGNO DELLO SFONDO LUMINOSO ---
    final fillPaint = Paint()
      ..style = PaintingStyle.fill
      ..maskFilter = const MaskFilter.blur(BlurStyle.normal, 10.0);

    if (themeType == AppThemeType.music) {
      fillPaint.color = Colors.white.withOpacity(0.08);
      canvas.drawPath(arenaShape, fillPaint);
    } else if (themeType == AppThemeType.cyberpunk) {
      fillPaint.color = theme.playerBlue.withOpacity(0.1);
      canvas.drawPath(arenaShape, fillPaint);
    }

    // --- DISEGNO DEL BORDO ESTERNO SOTTILE ---
    double baseStroke = themeType == AppThemeType.grimorio ? 6.0 : 4.0;
    if (themeType == AppThemeType.doodle) baseStroke = 2.5;

    final outlinePaint = Paint()
      ..style = PaintingStyle.stroke
      ..strokeWidth = baseStroke * 0.5
      ..strokeJoin = StrokeJoin.round;

    if (themeType == AppThemeType.cyberpunk) {
      outlinePaint.color = theme.gridLine;
      outlinePaint.maskFilter = MaskFilter.blur(BlurStyle.solid, 4.0 * blinkValue.clamp(0.1, 1.0));
    }
    else if (themeType == AppThemeType.arcade) { outlinePaint.color = Colors.white; }
    else if (themeType == AppThemeType.grimorio) { outlinePaint.color = theme.gridLine.withOpacity(0.6); }
    else if (themeType == AppThemeType.music) { outlinePaint.color = Colors.black; }
    else if (themeType == AppThemeType.doodle) { outlinePaint.color = const Color(0xFF111122); }
    else { outlinePaint.color = theme.gridLine.withOpacity(0.8); }

    // Disegniamo il contorno
    canvas.drawPath(arenaShape, outlinePaint);
    // =======================================================================


    for (var box in board.boxes) {
      Offset p1 = getScreenPos(box.x, box.y);
      Offset p2 = getScreenPos(box.x + 1, box.y + 1);
      Rect rect = Rect.fromPoints(p1, p2);

      if (box.type == BoxType.invisible) {
        if (box.isRevealed) {
          _drawIconInBox(canvas, rect, ThemeIcons.block(themeType), Colors.grey.shade500);
        }
        continue;
      }

      // Sfondo azzurrino se è di ghiaccio (anche prima di chiuderla)
      if (box.type == BoxType.ice && box.owner == Player.none) {
        canvas.drawRect(rect.deflate(2.0), Paint()..color = Colors.cyanAccent.withOpacity(0.05)..style=PaintingStyle.fill);
      }

      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.doodle) {
          Color penColor = box.owner == Player.red ? Colors.redAccent.shade700 : Colors.blueAccent.shade700;
          _drawScribbleBox(canvas, rect, penColor);
        } else if (themeType == AppThemeType.arcade) {
          _drawArcadeBox(canvas, rect, box.owner == Player.red ? theme.playerRed : theme.playerBlue);
        } else if (themeType == AppThemeType.grimorio) {
          _drawGrimorioBox(canvas, rect, box.owner == Player.red ? theme.playerRed : theme.playerBlue);
        } else {
          canvas.drawRect(rect, boxPaint);
        }
      }

      if (box.hiddenJokerOwner != null) {
        Color jokerColor = box.hiddenJokerOwner == Player.red ? theme.playerRed : theme.playerBlue;

        if (box.isJokerRevealed) {
          _drawIconInBox(canvas, rect, ThemeIcons.joker(themeType), jokerColor);
        } else {
          bool canSee = false;
          if (isOnline || isVsCPU) {
            canSee = box.hiddenJokerOwner == myPlayer;
          } else {
            canSee = false;
          }
          if (canSee) {
            _drawIconInBox(canvas, rect, ThemeIcons.joker(themeType), jokerColor.withOpacity(0.3));
          }
        }
      }

      if (box.type == BoxType.gold) {
        _drawIconInBox(canvas, rect, ThemeIcons.gold(themeType), Colors.amber);
      } else if (box.type == BoxType.bomb) {
        _drawIconInBox(canvas, rect, ThemeIcons.bomb(themeType), themeType == AppThemeType.cyberpunk || themeType == AppThemeType.arcade || themeType == AppThemeType.music ? Colors.greenAccent : Colors.deepPurple);
      } else if (box.type == BoxType.swap) {
        _drawIconInBox(canvas, rect, ThemeIcons.swap(themeType), Colors.purpleAccent);
      } else if (box.type == BoxType.ice) {
        _drawIconInBox(canvas, rect, ThemeIcons.ice(themeType), Colors.cyanAccent);
      } else if (box.type == BoxType.multiplier) {
        _drawIconInBox(canvas, rect, ThemeIcons.multiplier(themeType), Colors.yellowAccent);
      }
    }

    for (var line in board.lines) {
      if (!line.isPlayable) continue;

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

      // --- DISEGNO DELLA LINEA "INCRINATA" DAL GHIACCIO ---
      if (line.isIceCracked) {
        _drawCrackedIceLine(canvas, p1, p2, blinkValue);
        continue;
      }

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

      if (isLastMove && line.owner != Player.none && themeType != AppThemeType.cyberpunk && themeType != AppThemeType.arcade && themeType != AppThemeType.grimorio) {
        canvas.drawLine(p1, p2, Paint()..color = Colors.white.withOpacity(blinkValue * 0.5)..strokeWidth = 16.0..strokeCap = StrokeCap.round..maskFilter = const MaskFilter.blur(BlurStyle.normal, 6.0));
      }

      if (themeType == AppThemeType.cyberpunk) {
        _drawNeonLine(canvas, p1, p2, lineColor, line.owner != Player.none, isLastMove: isLastMove, blinkValue: blinkValue);
      } else if (themeType == AppThemeType.doodle) {
        Color doodleColor = line.owner == Player.none ? Colors.black.withOpacity(0.05) : lineColor;
        if (isLastMove && line.owner != Player.none) doodleColor = Color.lerp(doodleColor, Colors.black, blinkValue * 0.4) ?? doodleColor;
        _drawWobblyLine(canvas, p1, p2, doodleColor, line.owner != Player.none, isLastMove: isLastMove, blinkValue: blinkValue);
      } else if (themeType == AppThemeType.arcade) {
        _drawArcadeLine(canvas, p1, p2, lineColor, line.owner != Player.none, isLastMove: isLastMove, blinkValue: blinkValue);
      } else if (themeType == AppThemeType.grimorio) {
        _drawGrimorioLine(canvas, p1, p2, lineColor, line.owner != Player.none, isLastMove: isLastMove, blinkValue: blinkValue);
      } else if (themeType == AppThemeType.music) {
        if (line.owner == Player.none) lineColor = Colors.black.withOpacity(0.4);
        canvas.drawLine(p1, p2, Paint()..color = lineColor..strokeWidth = isLastMove ? 6.0 + (2.0 * blinkValue) : 6.0..strokeCap = StrokeCap.round);
      } else {
        if (isLastMove && line.owner != Player.none) lineColor = Color.lerp(lineColor, Colors.white, blinkValue * 0.5) ?? lineColor;
        canvas.drawLine(p1, p2, Paint()..color = lineColor..strokeWidth = isLastMove ? 6.0 + (2.0 * blinkValue) : 6.0..strokeCap = StrokeCap.round);
      }
    }

    final dotPaint = Paint()..style = PaintingStyle.fill;
    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.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 if (themeType == AppThemeType.arcade) {
        canvas.drawRect(Rect.fromCenter(center: pos, width: 8, height: 8), dotPaint..color = theme.gridLine.withOpacity(0.9));
        canvas.drawRect(Rect.fromCenter(center: pos, width: 4, height: 4), dotPaint..color = theme.background);
      } else if (themeType == AppThemeType.grimorio) {
        canvas.drawCircle(pos, 6.0, Paint()..color = theme.gridLine.withOpacity(0.3)..maskFilter = const MaskFilter.blur(BlurStyle.normal, 3.0));
        Path crystal = Path()..moveTo(pos.dx, pos.dy - 5)..lineTo(pos.dx + 3, pos.dy)..lineTo(pos.dx, pos.dy + 5)..lineTo(pos.dx - 3, pos.dy)..close();
        canvas.drawPath(crystal, dotPaint..color = theme.gridLine.withOpacity(0.8));
      } else if (themeType == AppThemeType.music) {
        canvas.drawCircle(pos, 4.5, dotPaint..color = Colors.black87);
      } 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: themeType == AppThemeType.arcade ? color : color.withOpacity(0.7),
          fontSize: rect.width * 0.45,
          fontFamily: icon.fontFamily,
          package: icon.fontPackage,
          shadows: themeType == AppThemeType.arcade ? [] : [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 _drawCrackedIceLine(Canvas canvas, Offset p1, Offset p2, double blink) {
    Paint crackPaint = Paint()
      ..color = Colors.cyanAccent.withOpacity(0.6 + (0.4 * blink))
      ..strokeWidth = 3.0
      ..style = PaintingStyle.stroke
      ..strokeCap = StrokeCap.round
      ..maskFilter = const MaskFilter.blur(BlurStyle.solid, 2.0);

    canvas.drawLine(p1, p2, Paint()..color = Colors.cyan.withOpacity(0.2)..strokeWidth=6.0);

    Vector2 dir = Vector2(p2.dx - p1.dx, p2.dy - p1.dy);
    double len = dir.length; Vector2 ndir = dir.normalized(); Vector2 perp = Vector2(-ndir.y, ndir.x);

    Path crack = Path()..moveTo(p1.dx, p1.dy);
    int zigzags = 6;
    for (int i=1; i<zigzags; i++) {
      double d = len * (i / zigzags);
      Offset basePt = Offset(p1.dx + ndir.x * d, p1.dy + ndir.y * d);
      double offset = (i % 2 == 0 ? 3.0 : -3.0);
      crack.lineTo(basePt.dx + perp.x * offset, basePt.dy + perp.y * offset);
    }
    crack.lineTo(p2.dx, p2.dy);
    canvas.drawPath(crack, crackPaint);
  }

  void _drawArcadeBox(Canvas canvas, Rect rect, Color color) {
    double pixelSize = 4.0; Paint paint = Paint()..color = color.withOpacity(0.9)..style = PaintingStyle.fill;
    for (double y = rect.top; y < rect.bottom; y += pixelSize) {
      for (double x = rect.left; x < rect.right; x += pixelSize) {
        int xi = ((x - rect.left) / pixelSize).floor(); int yi = ((y - rect.top) / pixelSize).floor();
        if ((xi + yi) % 2 == 0) canvas.drawRect(Rect.fromLTWH(x, y, pixelSize, pixelSize), paint);
      }
    }
    canvas.drawRect(rect.deflate(2.0), Paint()..color = Colors.white.withOpacity(0.4)..style = PaintingStyle.stroke..strokeWidth = 2.0);
  }

  void _drawGrimorioBox(Canvas canvas, Rect rect, Color color) {
    canvas.drawRect(rect, Paint()..color = color.withOpacity(0.15)..style=PaintingStyle.fill);
    Offset c = rect.center; double r = rect.width * 0.35;
    Paint linePaint = Paint()..color = color.withOpacity(0.8)..style = PaintingStyle.stroke..strokeWidth = 1.5..maskFilter = const MaskFilter.blur(BlurStyle.solid, 1.0);
    canvas.drawCircle(c, r, linePaint); canvas.drawCircle(c, r * 0.8, linePaint..strokeWidth = 0.5);
    Path p = Path();
    for(int i=0; i<3; i++) {
      double a = -pi/2 + i * 2*pi/3; Offset pt = Offset(c.dx + r*cos(a), c.dy + r*sin(a));
      if(i==0) p.moveTo(pt.dx, pt.dy); else p.lineTo(pt.dx, pt.dy);
    }
    p.close(); canvas.drawPath(p, linePaint..strokeWidth = 1.0);
  }

  void _drawArcadeLine(Canvas canvas, Offset p1, Offset p2, Color color, bool isConquered, {bool isLastMove = false, double blinkValue = 0.0}) {
    double pixelSize = 6.0; Vector2 dir = Vector2(p2.dx - p1.dx, p2.dy - p1.dy); double len = dir.length; Vector2 ndir = dir.normalized();
    Paint paint = Paint()..color = isConquered ? color : color.withOpacity(0.15)..style = PaintingStyle.fill;
    Paint highlight = Paint()..color = Colors.white.withOpacity(0.6)..style = PaintingStyle.fill;
    for(double d = 0; d <= len; d += pixelSize + 1.0) {
      Offset pt = Offset(p1.dx + ndir.x * d, p1.dy + ndir.y * d);
      canvas.drawRect(Rect.fromCenter(center: pt, width: pixelSize, height: pixelSize), paint);
      if (isConquered && (d / (pixelSize+1.0)).floor() % 3 == 0) canvas.drawRect(Rect.fromCenter(center: pt - const Offset(1,1), width: pixelSize*0.4, height: pixelSize*0.4), highlight);
    }
    if (isLastMove && isConquered) canvas.drawRect(Rect.fromPoints(p1, p2).inflate(4.0), Paint()..color = Colors.white.withOpacity(blinkValue*0.4)..style=PaintingStyle.stroke..strokeWidth=2.0);
  }

  void _drawGrimorioLine(Canvas canvas, Offset p1, Offset p2, Color color, bool isConquered, {bool isLastMove = false, double blinkValue = 0.0}) {
    if (!isConquered) { canvas.drawLine(p1, p2, Paint()..color = color.withOpacity(0.15)..strokeWidth = 2.0..strokeCap = StrokeCap.round); return; }
    canvas.drawLine(p1, p2, Paint()..color = color.withOpacity(0.6)..strokeWidth = 5.0..strokeCap = StrokeCap.round..maskFilter = const MaskFilter.blur(BlurStyle.normal, 4.0));
    canvas.drawLine(p1, p2, Paint()..color = Colors.white.withOpacity(0.7)..strokeWidth = 1.5..strokeCap = StrokeCap.round);
    int seed = (p1.dx * 1000 + p1.dy).toInt(); Random rand = Random(seed);
    Vector2 dir = Vector2(p2.dx - p1.dx, p2.dy - p1.dy); double len = dir.length; Vector2 ndir = dir.normalized(); Vector2 perp = Vector2(-ndir.y, ndir.x);
    Path thread1 = Path(); Path thread2 = Path(); int segments = 15; double step = len / segments;
    double phaseOffset = (isLastMove ? blinkValue * pi * 4 : 0) + rand.nextDouble()*pi;
    for(int i = 0; i <= segments; i++) {
      double d = i * step; Offset basePt = Offset(p1.dx + ndir.x * d, p1.dy + ndir.y * d);
      double amplitude = 3.5; double wave1 = sin(d * 0.15 + phaseOffset) * amplitude; double wave2 = cos(d * 0.15 + phaseOffset) * amplitude;
      Offset pt1 = basePt + Offset(perp.x * wave1, perp.y * wave1); Offset pt2 = basePt + Offset(perp.x * wave2, perp.y * wave2);
      if (i == 0) { thread1.moveTo(pt1.dx, pt1.dy); thread2.moveTo(pt2.dx, pt2.dy); } else { thread1.lineTo(pt1.dx, pt1.dy); thread2.lineTo(pt2.dx, pt2.dy); }
    }
    Paint threadPaint = Paint()..color = color.withOpacity(0.9)..style = PaintingStyle.stroke..strokeWidth = 1.5..maskFilter = const MaskFilter.blur(BlurStyle.solid, 1.0);
    canvas.drawPath(thread1, threadPaint); canvas.drawPath(thread2, threadPaint..color = Colors.white.withOpacity(0.5));
  }

  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 _drawNeonLine(Canvas canvas, Offset p1, Offset p2, Color color, bool isConquered, {bool isLastMove = false, double blinkValue = 0.0}) {
    double mainWidth = isConquered ? (isLastMove ? 6.0 + (blinkValue * 3.0) : 6.0) : 3.0; Color coreColor = isConquered ? (isLastMove ? Color.lerp(Colors.white, color, 1.0 - blinkValue)! : Colors.white.withOpacity(0.9)) : color.withOpacity(0.6);
    canvas.drawLine(p1, p2, Paint()..color = color.withOpacity(isConquered ? (isLastMove ? 0.4 + (0.4 * blinkValue) : 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(isLastMove ? 0.7 + (0.3 * blinkValue) : 0.7)..strokeWidth = mainWidth * 2..strokeCap = StrokeCap.round..maskFilter = const MaskFilter.blur(BlurStyle.normal, 6.0)); }
    canvas.drawLine(p1, p2, Paint()..color = coreColor..strokeWidth = mainWidth..strokeCap = StrokeCap.round);
  }

  void _drawWobblyLine(Canvas canvas, Offset p1, Offset p2, Color color, bool isConquered, {bool isLastMove = false, double blinkValue = 0.0}) {
    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 ? (isLastMove ? 4.5 + (2.0 * blinkValue) : 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
// ===========================================================================

// ===========================================================================
// FILE: lib/ui/game/game_screen.dart
// ===========================================================================

import 'dart:ui';
import 'dart:math' as math;
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 '../../models/game_board.dart';
import 'board_painter.dart';
import 'score_board.dart';
import 'package:google_fonts/google_fonts.dart';
import '../../services/storage_service.dart';

TextStyle _getTextStyle(AppThemeType themeType, TextStyle baseStyle) {
  if (themeType == AppThemeType.doodle) {
    return GoogleFonts.permanentMarker(textStyle: baseStyle);
  } else if (themeType == AppThemeType.arcade) {
    return GoogleFonts.pressStart2p(textStyle: baseStyle.copyWith(
      fontSize: baseStyle.fontSize != null ? baseStyle.fontSize! * 0.75 : null,
      letterSpacing: 0.5,
    ));
  } else if (themeType == AppThemeType.grimorio) {
    return GoogleFonts.cinzelDecorative(textStyle: baseStyle.copyWith(fontWeight: FontWeight.bold));
  } else if (themeType == AppThemeType.music) {
    return GoogleFonts.audiowide(textStyle: baseStyle.copyWith(letterSpacing: 1.5));
  }
  return baseStyle;
}

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

  @override
  State<GameScreen> createState() => _GameScreenState();
}

class _GameScreenState extends State<GameScreen> with TickerProviderStateMixin {
  late AnimationController _blinkController;
  bool _gameOverDialogShown = false;
  bool _opponentLeftDialogShown = false;

  bool _hideJokerMessage = false;
  bool _wasSetupPhase = false;
  Player _lastJokerTurn = Player.red;

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

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

  void _showGameOverDialog(BuildContext context, GameController game, ThemeColors theme, AppThemeType themeType) {
    _gameOverDialogShown = true;

    showDialog(
        barrierDismissible: false,
        context: context,
        builder: (dialogContext) => Consumer<GameController>(
            builder: (context, controller, child) {
              if (!controller.isGameOver) {
                WidgetsBinding.instance.addPostFrameCallback((_) {
                  if (_gameOverDialogShown) {
                    _gameOverDialogShown = false;
                    if (Navigator.canPop(dialogContext)) Navigator.pop(dialogContext);
                  }
                });
                return const SizedBox.shrink();
              }

              int red = controller.board.scoreRed; int blue = controller.board.scoreBlue;
              bool playerBeatCPU = controller.isVsCPU && red > blue;

              String myName = StorageService.instance.playerName.toUpperCase();
              if (myName.isEmpty) myName = "TU";

              String nameRed = controller.isOnline ? controller.onlineHostName.toUpperCase() : myName;
              String nameBlue = controller.isOnline ? controller.onlineGuestName.toUpperCase() : (themeType == AppThemeType.cyberpunk || themeType == AppThemeType.arcade || themeType == AppThemeType.music ? "VERDE" : "BLU");
              if (controller.isVsCPU) nameBlue = "CPU";

              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: _getTextStyle(themeType, TextStyle(color: theme.text, fontWeight: FontWeight.bold, fontSize: 22))),
                content: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Text(winnerText, textAlign: TextAlign.center, style: _getTextStyle(themeType, 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: FittedBox(
                        fit: BoxFit.scaleDown,
                        child: Row(
                          mainAxisSize: MainAxisSize.min,
                          children: [
                            Text("$nameRed: $red", style: _getTextStyle(themeType, TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: theme.playerRed))),
                            Text("  -  ", style: _getTextStyle(themeType, TextStyle(fontSize: 18, color: theme.text))),
                            Text("$nameBlue: $blue", style: _getTextStyle(themeType, TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: theme.playerBlue))),
                          ],
                        ),
                      ),
                    ),
                    if (controller.lastMatchXP > 0) ...[
                      const SizedBox(height: 15),
                      Container(
                        padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 6),
                        decoration: BoxDecoration(
                          color: Colors.green.withOpacity(0.15),
                          borderRadius: BorderRadius.circular(20),
                          border: Border.all(color: Colors.greenAccent, width: 1.5),
                          boxShadow: (themeType == AppThemeType.cyberpunk || themeType == AppThemeType.music) ? [const BoxShadow(color: Colors.greenAccent, blurRadius: 10, spreadRadius: -5)] : [],
                        ),
                        child: Text("+ ${controller.lastMatchXP} XP", style: _getTextStyle(themeType, const TextStyle(color: Colors.greenAccent, fontWeight: FontWeight.w900, fontSize: 16, letterSpacing: 1.5))),
                      ),
                    ],

                    if (controller.isVsCPU) ...[
                      const SizedBox(height: 15),
                      Text("Difficoltà CPU: Livello ${controller.cpuLevel}", style: _getTextStyle(themeType, TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: theme.text.withOpacity(0.7)))),
                    ],
                    if (controller.isOnline) ...[
                      const SizedBox(height: 20),
                      if (controller.rematchRequested && !controller.opponentWantsRematch)
                        Text("In attesa di $nameBlue...", style: _getTextStyle(themeType, const TextStyle(color: Colors.amber, fontWeight: FontWeight.bold, fontStyle: FontStyle.italic))),
                      if (controller.opponentWantsRematch && !controller.rematchRequested)
                        Text("$nameBlue vuole la rivincita!", style: _getTextStyle(themeType, const TextStyle(color: Colors.greenAccent, fontWeight: FontWeight.bold))),
                      if (controller.rematchRequested && controller.opponentWantsRematch)
                        Text("Avvio nuova partita...", style: _getTextStyle(themeType, const TextStyle(color: Colors.green, fontWeight: FontWeight.bold))),
                    ]
                  ],
                ),
                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: () { controller.increaseLevelAndRestart(); },
                          child: Text("PROSSIMO LIVELLO ➔", style: _getTextStyle(themeType, const TextStyle(fontWeight: FontWeight.bold, fontSize: 16))),
                        )
                      else if (controller.isOnline)
                        ElevatedButton(
                          style: ElevatedButton.styleFrom(backgroundColor: controller.rematchRequested ? Colors.grey : (winnerColor == theme.text ? theme.playerBlue : winnerColor), foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 15), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)), elevation: 5),
                          onPressed: controller.rematchRequested ? null : () { controller.requestRematch(); },
                          child: Text(controller.opponentWantsRematch ? "ACCETTA RIVINCITA" : "CHIEDI RIVINCITA", style: _getTextStyle(themeType, const TextStyle(fontWeight: FontWeight.bold, fontSize: 16, letterSpacing: 1.0))),
                        )
                      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: () { controller.startNewGame(controller.board.radius, vsCPU: controller.isVsCPU, shape: controller.board.shape, timeMode: controller.timeModeSetting); },
                          child: Text("RIGIOCA", style: _getTextStyle(themeType, const 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 (controller.isOnline) controller.disconnectOnlineGame();
                          _gameOverDialogShown = false;
                          Navigator.pop(dialogContext); Navigator.pop(context);
                        },
                        child: Text("TORNA AL MENU", style: _getTextStyle(themeType, TextStyle(fontWeight: FontWeight.bold, color: theme.text, fontSize: 14, letterSpacing: 1.5))),
                      ),
                    ],
                  )
                ],
              );
            }
        )
    );
  }

  Widget _buildThemedJokerMessage(ThemeColors theme, AppThemeType themeType, GameController gameController) {
    String titleText = "";
    String subtitleText = "";

    if (gameController.isOnline) {
      titleText = gameController.myJokerPlaced ? "In attesa dell'avversario..." : "Nascondi il tuo Jolly!";
      subtitleText = gameController.myJokerPlaced ? "" : "(Tocca qui per nascondere)";
    } else if (gameController.isVsCPU) {
      titleText = "Nascondi il tuo Jolly!";
      subtitleText = "(Tocca qui per nascondere)";
    } else {
      String pName = gameController.jokerTurn == Player.red ? "ROSSO" : (themeType == AppThemeType.cyberpunk || themeType == AppThemeType.arcade || themeType == AppThemeType.music ? "VERDE" : "BLU");
      titleText = "TURNO GIOCATORE $pName";
      subtitleText = "Passa il dispositivo.\nL'avversario NON deve guardare!\n\n(Tocca qui quando sei pronto)";
    }

    Widget content = Padding(
      padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 25),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(ThemeIcons.joker(themeType), color: themeType == AppThemeType.cyberpunk || themeType == AppThemeType.arcade || themeType == AppThemeType.music ? Colors.yellowAccent : theme.playerBlue, size: 50),
          const SizedBox(height: 15),
          Text(
            titleText,
            textAlign: TextAlign.center,
            style: _getTextStyle(themeType, TextStyle(
              color: themeType == AppThemeType.doodle ? Colors.black87 : theme.text,
              fontSize: 20,
              fontWeight: FontWeight.bold,
            )),
          ),
          const SizedBox(height: 25),
          Text(
            subtitleText,
            textAlign: TextAlign.center,
            style: _getTextStyle(themeType, TextStyle(
                color: themeType == AppThemeType.doodle ? Colors.black54 : theme.text.withOpacity(0.6),
                fontSize: 12,
                height: 1.5
            )),
          ),
        ],
      ),
    );

    if (themeType == AppThemeType.cyberpunk || themeType == AppThemeType.music) {
      return Container(decoration: BoxDecoration(color: Colors.black.withOpacity(0.9), borderRadius: BorderRadius.circular(20), border: Border.all(color: Colors.purpleAccent, width: 2), boxShadow: [BoxShadow(color: Colors.purpleAccent.withOpacity(0.6), blurRadius: 15, spreadRadius: 0)]), child: content);
    } else if (themeType == AppThemeType.doodle) {
      return Container(decoration: BoxDecoration(color: const Color(0xFFF9F9F9), borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.black87, width: 3), boxShadow: const [BoxShadow(color: Colors.black26, offset: Offset(6, 6))]), child: content);
    } else if (themeType == AppThemeType.arcade) {
      return Container(decoration: BoxDecoration(color: Colors.black, borderRadius: BorderRadius.zero, border: Border.all(color: Colors.greenAccent, width: 4)), child: content);
    } else if (themeType == AppThemeType.grimorio) {
      return Container(decoration: BoxDecoration(color: const Color(0xFF2C1E3D), borderRadius: BorderRadius.circular(30), border: Border.all(color: const Color(0xFFBCAAA4), width: 3), boxShadow: [BoxShadow(color: Colors.deepPurpleAccent.withOpacity(0.5), blurRadius: 20, spreadRadius: 5)]), child: content);
    } else {
      return Container(decoration: BoxDecoration(color: theme.background.withOpacity(0.95), borderRadius: BorderRadius.circular(20), border: Border.all(color: theme.gridLine.withOpacity(0.5), width: 2), boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.3), blurRadius: 20, offset: const Offset(0, 10))]), child: content);
    }
  }

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

    if (gameController.isSetupPhase && !_wasSetupPhase) {
      _hideJokerMessage = false;
      _lastJokerTurn = Player.red;
    } else if (gameController.isSetupPhase && gameController.jokerTurn != _lastJokerTurn) {
      _hideJokerMessage = false;
      _lastJokerTurn = gameController.jokerTurn;
    }
    _wasSetupPhase = gameController.isSetupPhase;

    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (gameController.opponentLeft && !_opponentLeftDialogShown) {
        _opponentLeftDialogShown = true;
        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: _getTextStyle(themeType, TextStyle(color: theme.playerRed, fontWeight: FontWeight.bold))),
              content: Text("L'avversario ha abbandonato la stanza.\nSei il vincitore incontestato!", textAlign: TextAlign.center, style: _getTextStyle(themeType, 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: Text("MENU PRINCIPALE", style: _getTextStyle(themeType, const TextStyle(fontWeight: FontWeight.bold))),
                )
              ],
            )
        );
      } else if (gameController.board.isGameOver && !_gameOverDialogShown) {
        _showGameOverDialog(context, gameController, theme, themeType);
      }
    });

    String? bgImage;
    if (themeType == AppThemeType.doodle) bgImage = 'assets/images/doodle_bg.jpg';
    if (themeType == AppThemeType.cyberpunk) bgImage = 'assets/images/cyber_bg.jpg';
    if (themeType == AppThemeType.music) bgImage = 'assets/images/music_bg.jpg';
    if (themeType == AppThemeType.arcade) bgImage = 'assets/images/arcade.jpg';
    if (themeType == AppThemeType.grimorio) bgImage = 'assets/images/grimorio.jpg';

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

    Widget emojiBar = const SizedBox();
    if (gameController.isOnline && !gameController.isGameOver) {
      final List<String> emojis = ['😂', '😡', '😱', '🥳', '👀'];
      emojiBar = Container(
        padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
        decoration: BoxDecoration(
          color: themeType == AppThemeType.cyberpunk || themeType == AppThemeType.arcade || themeType == AppThemeType.music ? Colors.black.withOpacity(0.6) : Colors.white.withOpacity(0.8),
          borderRadius: BorderRadius.circular(30),
          border: Border.all(color: themeType == AppThemeType.cyberpunk || themeType == AppThemeType.music ? theme.playerBlue.withOpacity(0.3) : Colors.white24, width: 2),
        ),
        child: Row(
          mainAxisSize: MainAxisSize.min,
          children: emojis.map((e) => GestureDetector(
            onTap: () => gameController.sendReaction(e),
            child: Padding(padding: const EdgeInsets.symmetric(horizontal: 6), child: Text(e, style: const TextStyle(fontSize: 22))),
          )).toList(),
        ),
      );
    }

    Widget gameContent = SafeArea(
      child: Stack(
        children: [
          Column(
            children: [
              const ScoreBoard(),
              Expanded(
                child: Center(
                  child: Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 2.0, vertical: 2.0),
                    child: LayoutBuilder(
                        builder: (context, constraints) {
                          int cols = gameController.board.columns + 1;
                          int rows = gameController.board.rows + 1;
                          double boxSize = constraints.maxWidth / cols;
                          double requiredHeight = boxSize * rows;
                          if (requiredHeight > constraints.maxHeight) { boxSize = constraints.maxHeight / rows; }
                          double actualWidth = boxSize * cols;
                          double actualHeight = boxSize * rows;

                          return SizedBox(
                            width: actualWidth, height: actualHeight,
                            child: Stack(
                              children: [
                                Positioned.fill(
                                  child: ClipPath(
                                    clipper: _ArenaClipper(gameController.board),
                                    child: BackdropFilter(
                                      filter: ImageFilter.blur(sigmaX: 8.0, sigmaY: 8.0),
                                      child: Container(
                                        color: themeType == AppThemeType.doodle
                                            ? Colors.black.withOpacity(0.05)
                                            : Colors.white.withOpacity(0.12),
                                      ),
                                    ),
                                  ),
                                ),

                                GestureDetector(
                                  behavior: HitTestBehavior.opaque,
                                  onTapDown: (details) => _handleTap(details.localPosition, actualWidth, actualHeight, gameController, themeType),
                                  child: AnimatedBuilder(
                                      animation: _blinkController,
                                      builder: (context, child) {
                                        return CustomPaint(
                                          size: Size(actualWidth, actualHeight),
                                          painter: BoardPainter(
                                            board: gameController.board, theme: theme, themeType: themeType,
                                            blinkValue: _blinkController.value, isOnline: gameController.isOnline,
                                            isVsCPU: gameController.isVsCPU, isSetupPhase: gameController.isSetupPhase,
                                            myPlayer: gameController.myPlayer, jokerTurn: gameController.jokerTurn,
                                          ),
                                        );
                                      }
                                  ),
                                ),
                              ],
                            ),
                          );
                        }
                    ),
                  ),
                ),
              ),

              Padding(
                padding: const EdgeInsets.only(bottom: 10.0, left: 20.0, right: 20.0, top: 5.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: _getTextStyle(themeType, TextStyle(color: indicatorColor, fontWeight: FontWeight.bold, fontSize: 11, letterSpacing: 1.0))),
                          ],
                        ),
                      )
                    else
                      emojiBar,

                    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 || themeType == AppThemeType.arcade ? 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 || themeType == AppThemeType.arcade ? Colors.white : theme.text, size: 20),
                        onPressed: () { gameController.disconnectOnlineGame(); Navigator.pop(context); },
                        label: Text("ESCI", style: _getTextStyle(themeType, TextStyle(color: bgImage != null || themeType == AppThemeType.arcade ? Colors.white : theme.text, fontWeight: FontWeight.bold, fontSize: 12))),
                      ),
                    ),
                  ],
                ),
              )
            ],
          ),

          if (gameController.myReaction != null)
            Positioned(top: 80, left: gameController.isHost ? 30 : null, right: gameController.isHost ? null : 30, child: _BouncingEmoji(emoji: gameController.myReaction!)),
          if (gameController.opponentReaction != null)
            Positioned(top: 80, left: !gameController.isHost ? 30 : null, right: !gameController.isHost ? null : 30, child: _BouncingEmoji(emoji: gameController.opponentReaction!)),
        ],
      ),
    );

    return PopScope(
      canPop: true,
      onPopInvoked: (didPop) { gameController.disconnectOnlineGame(); },
      child: Scaffold(
        backgroundColor: themeType == AppThemeType.doodle ? Colors.white : (bgImage != null ? Colors.transparent : theme.background),
        body: Stack(
          children: [
            Container(color: themeType == AppThemeType.doodle ? Colors.white : theme.background),

            if (themeType == AppThemeType.doodle)
              Positioned.fill(
                child: CustomPaint(
                  painter: FullScreenGridPainter(Colors.blue.withOpacity(0.15)),
                ),
              ),

            if (bgImage != null)
              Positioned.fill(
                child: Container(
                  decoration: BoxDecoration(
                    image: DecorationImage(
                      image: AssetImage(bgImage!),
                      fit: BoxFit.cover,
                      colorFilter: themeType == AppThemeType.doodle
                          ? ColorFilter.mode(Colors.white.withOpacity(0.5), BlendMode.lighten)
                          : null,
                    ),
                  ),
                ),
              ),

            if (bgImage != null && (themeType == AppThemeType.cyberpunk || themeType == AppThemeType.music || themeType == AppThemeType.arcade || themeType == AppThemeType.grimorio))
              Positioned.fill(
                child: Container(
                  decoration: BoxDecoration(
                      gradient: LinearGradient(
                          begin: Alignment.topCenter, end: Alignment.bottomCenter,
                          colors: [Colors.black.withOpacity(0.4), Colors.black.withOpacity(0.8)]
                      )
                  ),
                ),
              ),

            if (gameController.isTimeMode && !gameController.isCPUThinking && !gameController.isGameOver && gameController.timeLeft > 0 && gameController.timeLeft <= 5 && !gameController.isSetupPhase)
              Positioned.fill(child: BlitzBackgroundEffect(timeLeft: gameController.timeLeft, color: theme.playerRed, themeType: themeType)),

            if (gameController.effectText.isNotEmpty)
              Positioned.fill(child: SpecialEventBackgroundEffect(text: gameController.effectText, color: gameController.effectColor, themeType: themeType)),

            Positioned.fill(child: gameContent),

            if (gameController.isSetupPhase && !_hideJokerMessage)
              Positioned.fill(
                child: Container(
                  color: themeType == AppThemeType.cyberpunk || themeType == AppThemeType.arcade || themeType == AppThemeType.music
                      ? Colors.black.withOpacity(0.98)
                      : theme.background.withOpacity(0.98),
                  child: Center(
                    child: Padding(
                      padding: const EdgeInsets.symmetric(horizontal: 30.0),
                      child: GestureDetector(
                        onTap: () { setState(() { _hideJokerMessage = true; }); },
                        child: Material(color: Colors.transparent, child: _buildThemedJokerMessage(theme, themeType, gameController)),
                      ),
                    ),
                  ),
                ),
              ),

            if (gameController.isGameOver && gameController.board.scoreRed != gameController.board.scoreBlue)
              Positioned.fill(child: IgnorePointer(child: WinnerVFXOverlay(winnerColor: gameController.board.scoreRed > gameController.board.scoreBlue ? theme.playerRed : theme.playerBlue, themeType: themeType))),
          ],
        ),
      ),
    );
  }

  void _handleTap(Offset tapPos, double width, double height, GameController controller, AppThemeType themeType) {
    final board = controller.board;
    if (board.isGameOver) return;
    int cols = board.columns + 1; double spacing = width / cols; double offset = spacing / 2;

    if (controller.isSetupPhase) {
      int bx = ((tapPos.dx - offset) / spacing).floor(); int by = ((tapPos.dy - offset) / spacing).floor();
      controller.placeJoker(bx, by); return;
    }

    Line? closestLine; double minDistance = double.infinity; double maxTouchDistance = spacing * 0.4;
    for (var line in board.lines) {
      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); }
  }

  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;
  }
}

// ===========================================================================
// CLIPPER MAGICO E ALTRI WIDGETS
// ===========================================================================
class _ArenaClipper extends CustomClipper<Path> {
  final GameBoard board;
  _ArenaClipper(this.board);

  @override
  Path getClip(Size size) {
    int cols = board.columns + 1;
    double spacing = size.width / cols;
    double offset = spacing / 2;
    Path path = Path();

    for (var box in board.boxes) {
      if (box.type != BoxType.invisible) {
        path.addRect(Rect.fromLTWH(
            box.x * spacing + offset,
            box.y * spacing + offset,
            spacing,
            spacing
        ));
      }
    }
    return path;
  }
  @override bool shouldReclip(covariant _ArenaClipper oldClipper) => true;
}

class _Particle {
  double x, y, vx, vy, size, angle, spin;
  Color color; int type;
  _Particle({required this.x, required this.y, required this.vx, required this.vy, required this.color, required this.size, required this.angle, required this.spin, required this.type});
}

class WinnerVFXOverlay extends StatefulWidget {
  final Color winnerColor; final AppThemeType themeType;
  const WinnerVFXOverlay({super.key, required this.winnerColor, required this.themeType});
  @override State<WinnerVFXOverlay> createState() => _WinnerVFXOverlayState();
}

class _WinnerVFXOverlayState extends State<WinnerVFXOverlay> with SingleTickerProviderStateMixin {
  late AnimationController _vfxController;
  final List<_Particle> _particles = [];
  final math.Random _rand = math.Random();
  bool _initialized = false;

  @override
  void initState() {
    super.initState();
    _vfxController = AnimationController(vsync: this, duration: const Duration(seconds: 4))..addListener(() { _updateParticles(); })..forward();
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    if (!_initialized) { _initParticles(MediaQuery.of(context).size); _initialized = true; }
  }

  void _initParticles(Size screenSize) {
    int particleCount = widget.themeType == AppThemeType.cyberpunk || widget.themeType == AppThemeType.music ? 150 : 100;
    if (widget.themeType == AppThemeType.arcade) particleCount = 80;
    if (widget.themeType == AppThemeType.grimorio) particleCount = 120;

    List<Color> palette = [widget.winnerColor, widget.winnerColor.withOpacity(0.7), Colors.white];
    if (widget.themeType == AppThemeType.cyberpunk) { palette.add(Colors.cyanAccent); palette.add(Colors.yellowAccent); }
    else if (widget.themeType == AppThemeType.doodle) { palette.add(const Color(0xFF00008B)); palette.add(Colors.redAccent); }
    else if (widget.themeType == AppThemeType.arcade) { palette = [widget.winnerColor, Colors.white, Colors.greenAccent]; }
    else if (widget.themeType == AppThemeType.grimorio) { palette = [widget.winnerColor, Colors.deepPurpleAccent, Colors.white]; }
    else if (widget.themeType == AppThemeType.music) { palette.add(Colors.pinkAccent); palette.add(Colors.cyanAccent); }

    for (int i = 0; i < particleCount; i++) {
      double speed = _rand.nextDouble() * 20 + 5;
      double theta = _rand.nextDouble() * 2 * math.pi;
      _particles.add(_Particle(x: screenSize.width / 2, y: screenSize.height / 2, vx: speed * math.cos(theta), vy: speed * math.sin(theta) - 5, color: palette[_rand.nextInt(palette.length)], size: _rand.nextDouble() * 10 + 6, angle: _rand.nextDouble() * math.pi, spin: (_rand.nextDouble() - 0.5) * 0.5, type: _rand.nextInt(3)));
    }
  }

  void _updateParticles() {
    setState(() {
      for (var p in _particles) {
        p.x += p.vx; p.y += p.vy;
        if (widget.themeType == AppThemeType.cyberpunk || widget.themeType == AppThemeType.music) { p.vy += 0.1; p.vx *= 0.98; p.vy *= 0.98; }
        else if (widget.themeType == AppThemeType.arcade) { p.vy += 0.3; p.spin = 0; p.angle = 0; }
        else if (widget.themeType == AppThemeType.grimorio) { p.vy -= 0.1; p.x += math.sin(p.y * 0.02) * 1.5; p.size *= 0.995; }
        else { p.vy += 0.5; }
        p.angle += p.spin; p.size *= 0.99;
      }
    });
  }
  @override void dispose() { _vfxController.dispose(); super.dispose(); }
  @override Widget build(BuildContext context) { return CustomPaint(painter: _VFXPainter(particles: _particles, themeType: widget.themeType), child: Container()); }
}

class _VFXPainter extends CustomPainter {
  final List<_Particle> particles; final AppThemeType themeType;
  _VFXPainter({required this.particles, required this.themeType});

  @override
  void paint(Canvas canvas, Size size) {
    for (var p in particles) {
      if (p.size < 0.5) continue;
      final paint = Paint()..color = p.color..style = PaintingStyle.fill;
      if (themeType == AppThemeType.cyberpunk || themeType == AppThemeType.music) { paint.maskFilter = const MaskFilter.blur(BlurStyle.solid, 4.0); }
      canvas.save(); canvas.translate(p.x, p.y); canvas.rotate(p.angle);

      if (themeType == AppThemeType.doodle) {
        paint.style = PaintingStyle.stroke; paint.strokeWidth = 2.0;
        if (p.type == 0) { canvas.drawCircle(Offset.zero, p.size, paint); } else { canvas.drawRect(Rect.fromCenter(center: Offset.zero, width: p.size*2, height: p.size*2), paint); }
      } else if (themeType == AppThemeType.arcade) {
        canvas.drawRect(Rect.fromCenter(center: Offset.zero, width: p.size * 1.5, height: p.size * 1.5), paint);
      } else if (themeType == AppThemeType.grimorio) {
        paint.maskFilter = const MaskFilter.blur(BlurStyle.normal, 4.0);
        canvas.drawCircle(Offset.zero, p.size, paint);
        canvas.drawCircle(Offset.zero, p.size * 0.3, Paint()..color=Colors.white..style=PaintingStyle.fill);
      } else {
        if (p.type == 0) { canvas.drawCircle(Offset.zero, p.size, paint); }
        else if (p.type == 1) { canvas.drawRect(Rect.fromCenter(center: Offset.zero, width: p.size * 2, height: p.size * 2), paint); }
        else { var path = Path()..moveTo(0, -p.size)..lineTo(p.size, p.size)..lineTo(-p.size, p.size)..close(); canvas.drawPath(path, paint); }
      }
      canvas.restore();
    }
  }
  @override bool shouldRepaint(covariant _VFXPainter oldDelegate) => true;
}

class _BouncingEmoji extends StatefulWidget {
  final String emoji; const _BouncingEmoji({required this.emoji});
  @override State<_BouncingEmoji> createState() => _BouncingEmojiState();
}
class _BouncingEmojiState extends State<_BouncingEmoji> with SingleTickerProviderStateMixin {
  late AnimationController _ctrl; late Animation<double> _anim;
  @override void initState() { super.initState(); _ctrl = AnimationController(vsync: this, duration: const Duration(milliseconds: 500))..repeat(reverse: true); _anim = Tween<double>(begin: -10, end: 10).animate(CurvedAnimation(parent: _ctrl, curve: Curves.easeInOut)); }
  @override void dispose() { _ctrl.dispose(); super.dispose(); }
  @override Widget build(BuildContext context) { return AnimatedBuilder(animation: _anim, builder: (ctx, child) => Transform.translate(offset: Offset(0, _anim.value), child: Container(padding: const EdgeInsets.all(8), decoration: const BoxDecoration(color: Colors.white, shape: BoxShape.circle, boxShadow: [BoxShadow(color: Colors.black26, blurRadius: 5)]), child: Text(widget.emoji, style: const TextStyle(fontSize: 32))))); }
}

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;
}

class BlitzBackgroundEffect extends StatefulWidget {
  final int timeLeft; final Color color; final AppThemeType themeType;
  const BlitzBackgroundEffect({super.key, required this.timeLeft, required this.color, required this.themeType});
  @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: _getTextStyle(widget.themeType, TextStyle(fontSize: 300, fontWeight: FontWeight.w900, color: widget.color.withOpacity(0.35 + (0.3 * _controller.value)), height: 1.0)))))); }); }
}

class SpecialEventBackgroundEffect extends StatefulWidget {
  final String text; final Color color; final AppThemeType themeType;
  const SpecialEventBackgroundEffect({super.key, required this.text, required this.color, required this.themeType});
  @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, textAlign: TextAlign.center, style: _getTextStyle(widget.themeType, TextStyle(fontSize: 150, fontWeight: FontWeight.w900, color: widget.color, height: 1.0))))))); }); }
}
// ===========================================================================
// FILE: lib/ui/game/score_board.dart
// ===========================================================================

// ===========================================================================
// FILE: lib/ui/game/score_board.dart
// ===========================================================================

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:google_fonts/google_fonts.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';
import '../../services/storage_service.dart';
import '../home/dialog.dart'; // <--- IMPORTANTE: Importa il TutorialDialog

TextStyle _getTextStyle(AppThemeType themeType, TextStyle baseStyle) {
  if (themeType == AppThemeType.doodle) {
    return GoogleFonts.permanentMarker(textStyle: baseStyle);
  } else if (themeType == AppThemeType.arcade) {
    return GoogleFonts.pressStart2p(textStyle: baseStyle.copyWith(
      fontSize: baseStyle.fontSize != null ? baseStyle.fontSize! * 0.75 : null,
      letterSpacing: 0.5,
    ));
  } else if (themeType == AppThemeType.grimorio) {
    return GoogleFonts.cinzelDecorative(textStyle: baseStyle.copyWith(fontWeight: FontWeight.bold));
  }
  return baseStyle;
}

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;

    String myName = StorageService.instance.playerName.toUpperCase();
    if (myName.isEmpty) myName = "TU";

    String nameRed = myName;
    String nameBlue = themeType == AppThemeType.cyberpunk || themeType == AppThemeType.arcade ? "VERDE" : "BLU";

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

    return Container(
      padding: const EdgeInsets.only(top: 10, bottom: 20, left: 20, right: 20),
      decoration: BoxDecoration(
        color: themeType == AppThemeType.doodle ? theme.background : 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, themeType: themeType),

          Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Text(
                  "TETRAQ",
                  style: _getTextStyle(themeType, TextStyle(
                      fontSize: 24,
                      fontWeight: FontWeight.w900,
                      color: theme.text,
                      letterSpacing: 4,
                      shadows: themeType == AppThemeType.doodle
                          ? [
                        // EFFETTO RILIEVO (Luce in alto a sx, ombra in basso a dx)
                        const Shadow(color: Colors.white, offset: Offset(-1.5, -1.5), blurRadius: 1),
                        Shadow(color: Colors.black.withOpacity(0.25), offset: const Offset(1.5, 1.5), blurRadius: 2),
                      ]
                          : [Shadow(color: Colors.black.withOpacity(0.3), offset: const Offset(1, 2), blurRadius: 2)]
                  ))
              ),
              const SizedBox(height: 8),

              // --- ROW DEI PULSANTI AGGIORNATA ---
              Row(
                mainAxisSize: MainAxisSize.min,
                children: [
                  // TASTO AUDIO CON CONTORNO
                  GestureDetector(
                    behavior: HitTestBehavior.opaque,
                    onTap: () {
                      setState(() {
                        AudioService.instance.toggleMute();
                      });
                    },
                    child: Container(
                      padding: const EdgeInsets.all(6),
                      decoration: BoxDecoration(
                        color: themeType == AppThemeType.doodle ? Colors.transparent : theme.text.withOpacity(0.05),
                        borderRadius: BorderRadius.circular(8),
                        border: Border.all(color: themeType == AppThemeType.doodle ? const Color(0xFF111122) : theme.text.withOpacity(0.3), width: 1.5),
                      ),
                      child: Icon(
                          isMuted ? Icons.volume_off : Icons.volume_up,
                          color: themeType == AppThemeType.doodle ? const Color(0xFF111122) : theme.text.withOpacity(0.8),
                          size: 16
                      ),
                    ),
                  ),

                  const SizedBox(width: 10),

                  // TASTO INFORMAZIONI (TUTORIAL) CON CONTORNO
                  GestureDetector(
                    behavior: HitTestBehavior.opaque,
                    onTap: () {
                      showDialog(context: context, builder: (ctx) => const TutorialDialog());
                    },
                    child: Container(
                      padding: const EdgeInsets.all(6),
                      decoration: BoxDecoration(
                        color: themeType == AppThemeType.doodle ? Colors.transparent : theme.text.withOpacity(0.05),
                        borderRadius: BorderRadius.circular(8),
                        border: Border.all(color: themeType == AppThemeType.doodle ? const Color(0xFF111122) : theme.text.withOpacity(0.3), width: 1.5),
                      ),
                      child: Icon(
                          Icons.info_outline,
                          color: themeType == AppThemeType.doodle ? const Color(0xFF111122) : theme.text.withOpacity(0.8),
                          size: 16
                      ),
                    ),
                  ),
                ],
              ),
            ],
          ),

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

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

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

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Text(title, style: _getTextStyle(themeType, 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: _getTextStyle(themeType, TextStyle(fontSize: 22, fontWeight: FontWeight.bold, color: isTurn ? Colors.white : textColor.withOpacity(0.5)))),
        ),
      ],
    );
  }
}
// ===========================================================================
// FILE: lib/ui/home/dialog.dart
// ===========================================================================

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

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';

import '../../core/theme_manager.dart';
import '../../core/app_colors.dart';
import '../../l10n/app_localizations.dart';
import '../../widgets/painters.dart';
import '../../widgets/cyber_border.dart';
import '../../services/storage_service.dart';

// ===========================================================================
// 1. DIALOGO MISSIONI (QUESTS)
// ===========================================================================
class QuestsDialog extends StatelessWidget {
  const QuestsDialog({super.key});

  @override
  Widget build(BuildContext context) {
    final themeManager = context.watch<ThemeManager>();
    final theme = themeManager.currentColors;
    final themeType = themeManager.currentThemeType;
    final loc = AppLocalizations.of(context)!;

    return FutureBuilder<SharedPreferences>(
        future: SharedPreferences.getInstance(),
        builder: (context, snapshot) {
          if (!snapshot.hasData) return const SizedBox();
          final prefs = snapshot.data!;

          return Dialog(
            backgroundColor: Colors.transparent,
            insetPadding: const EdgeInsets.all(20),
            child: Container(
              padding: const EdgeInsets.all(25.0),
              decoration: BoxDecoration(
                  gradient: LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [theme.background.withOpacity(0.95), theme.background.withOpacity(0.8)]),
                  borderRadius: BorderRadius.circular(25),
                  border: Border.all(color: theme.playerBlue.withOpacity(0.5), width: 2),
                  boxShadow: [BoxShadow(color: theme.playerBlue.withOpacity(0.2), blurRadius: 20, spreadRadius: 5)]
              ),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Icon(Icons.assignment_turned_in, size: 50, color: theme.playerBlue),
                  const SizedBox(height: 10),
                  Text(loc.questsTitle, style: getSharedTextStyle(themeType, TextStyle(fontSize: 22, fontWeight: FontWeight.w900, color: theme.text, letterSpacing: 1.5))),
                  const SizedBox(height: 25),

                  ...List.generate(3, (index) {
                    int i = index + 1;
                    int type = prefs.getInt('q${i}_type') ?? 0;
                    int prog = prefs.getInt('q${i}_prog') ?? 0;
                    int target = prefs.getInt('q${i}_target') ?? 1;

                    String title = "";
                    IconData icon = Icons.star;
                    if (type == 0) { title = "Vinci partite Online"; icon = Icons.public; }
                    else if (type == 1) { title = "Vinci contro la CPU"; icon = Icons.smart_toy; }
                    else { title = "Gioca in Arene Speciali"; icon = Icons.extension; }

                    bool completed = prog >= target;
                    double percent = (prog / target).clamp(0.0, 1.0);

                    return Container(
                      margin: const EdgeInsets.only(bottom: 15),
                      padding: const EdgeInsets.all(12),
                      decoration: BoxDecoration(
                        color: completed ? Colors.green.withOpacity(0.1) : theme.text.withOpacity(0.05),
                        borderRadius: BorderRadius.circular(15),
                        border: Border.all(color: completed ? Colors.green : theme.gridLine.withOpacity(0.3)),
                      ),
                      child: Row(
                        children: [
                          Icon(icon, color: completed ? Colors.green : theme.text.withOpacity(0.6), size: 30),
                          const SizedBox(width: 15),
                          Expanded(
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                Text(title, style: getSharedTextStyle(themeType, TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: completed ? Colors.green : theme.text))),
                                const SizedBox(height: 6),
                                ClipRRect(
                                  borderRadius: BorderRadius.circular(10),
                                  child: LinearProgressIndicator(value: percent, backgroundColor: theme.gridLine.withOpacity(0.2), color: completed ? Colors.green : theme.playerBlue, minHeight: 8),
                                )
                              ],
                            ),
                          ),
                          const SizedBox(width: 10),
                          Text("$prog / $target", style: getSharedTextStyle(themeType, TextStyle(fontWeight: FontWeight.bold, color: theme.text.withOpacity(0.6)))),
                        ],
                      ),
                    );
                  }),

                  const SizedBox(height: 15),
                  SizedBox(
                    width: double.infinity, height: 50,
                    child: ElevatedButton(
                      style: ElevatedButton.styleFrom(backgroundColor: theme.playerBlue, foregroundColor: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15))),
                      onPressed: () => Navigator.pop(context),
                      child: const Text("CHIUDI", style: TextStyle(fontSize: 16, fontWeight: FontWeight.w900, letterSpacing: 2)),
                    ),
                  )
                ],
              ),
            ),
          );
        }
    );
  }
}

// ===========================================================================
// 2. DIALOGO CLASSIFICA (LEADERBOARD) CON CALLBACK SFIDA
// ===========================================================================
class LeaderboardDialog extends StatelessWidget {
  final Function(String uid, String name)? onChallenge; // <-- Aggiunto Callback per inviare i dati alla HomeScreen

  const LeaderboardDialog({super.key, this.onChallenge});

  @override
  Widget build(BuildContext context) {
    final themeManager = context.watch<ThemeManager>();
    final theme = themeManager.currentColors;
    final themeType = themeManager.currentThemeType;
    final loc = AppLocalizations.of(context)!;

    Widget content = Container(
      padding: const EdgeInsets.all(20.0),
      decoration: BoxDecoration(
          gradient: LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [theme.background.withOpacity(0.95), theme.background.withOpacity(0.8)]),
          borderRadius: BorderRadius.circular(25),
          border: Border.all(color: Colors.amber.withOpacity(0.8), width: 2),
          boxShadow: [BoxShadow(color: Colors.amber.withOpacity(0.2), blurRadius: 20, spreadRadius: 5)]
      ),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          const Icon(Icons.emoji_events, size: 50, color: Colors.amber),
          const SizedBox(height: 10),
          Text(loc.leaderboardTitle, style: getSharedTextStyle(themeType, TextStyle(fontSize: 20, fontWeight: FontWeight.w900, color: theme.text, letterSpacing: 1.5))),
          const SizedBox(height: 20),

          SizedBox(
            height: 350,
            child: StreamBuilder<QuerySnapshot>(
                stream: FirebaseFirestore.instance.collection('leaderboard').orderBy('xp', descending: true).limit(50).snapshots(),
                builder: (context, snapshot) {
                  if (snapshot.connectionState == ConnectionState.waiting) {
                    return Center(child: CircularProgressIndicator(color: theme.playerBlue));
                  }
                  if (!snapshot.hasData || snapshot.data!.docs.isEmpty) {
                    return Center(child: Text("Ancora nessun campione...", style: TextStyle(color: theme.text.withOpacity(0.5))));
                  }

                  final rawDocs = snapshot.data!.docs;
                  final filteredDocs = rawDocs.where((doc) {
                    var data = doc.data() as Map<String, dynamic>;
                    String name = (data['name'] ?? '').toString().toUpperCase();
                    return name != 'PAOLO';
                  }).toList();

                  if (filteredDocs.isEmpty) {
                    return Center(child: Text("Ancora nessun campione...", style: TextStyle(color: theme.text.withOpacity(0.5))));
                  }

                  return ListView.builder(
                      physics: const BouncingScrollPhysics(),
                      itemCount: filteredDocs.length,
                      itemBuilder: (context, index) {
                        var doc = filteredDocs[index];
                        var data = doc.data() as Map<String, dynamic>;
                        String? myUid = FirebaseAuth.instance.currentUser?.uid;
                        bool isMe = doc.id == myUid;
                        String playerName = data['name'] ?? 'Unknown';

                        bool isOnline = false;
                        if (data['lastActive'] != null) {
                          Timestamp lastActive = data['lastActive'];
                          int diffInSeconds = DateTime.now().difference(lastActive.toDate()).inSeconds;
                          if (diffInSeconds.abs() < 180) isOnline = true;
                        }

                        return StatefulBuilder(
                            builder: (context, setStateItem) {
                              bool isFav = StorageService.instance.isFavorite(doc.id);

                              return Container(
                                margin: const EdgeInsets.only(bottom: 8),
                                padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
                                decoration: BoxDecoration(
                                    color: isMe ? theme.playerBlue.withOpacity(0.2) : theme.text.withOpacity(0.05),
                                    borderRadius: BorderRadius.circular(10),
                                    border: isMe ? Border.all(color: theme.playerBlue, width: 1.5) : null
                                ),
                                child: Row(
                                  children: [
                                    Text("#${index + 1}", style: getSharedTextStyle(themeType, TextStyle(fontWeight: FontWeight.w900, color: index == 0 ? Colors.amber : (index == 1 ? Colors.grey.shade400 : (index == 2 ? Colors.brown.shade300 : theme.text.withOpacity(0.5)))))),
                                    const SizedBox(width: 15),

                                    Expanded(
                                      child: Row(
                                        mainAxisSize: MainAxisSize.min,
                                        children: [
                                          Flexible(
                                              child: Text(
                                                playerName,
                                                style: getSharedTextStyle(themeType, TextStyle(fontSize: 16, fontWeight: isMe ? FontWeight.w900 : FontWeight.bold, color: theme.text)),
                                                overflow: TextOverflow.ellipsis,
                                              )
                                          ),

                                          if (isFav && !isMe && isOnline) ...[
                                            const SizedBox(width: 8),
                                            PulsingChallengeButton(
                                              themeType: themeType,
                                              onTap: () {
                                                Navigator.pop(context);
                                                // Chiama la funzione passata dalla HomeScreen!
                                                if (onChallenge != null) {
                                                  onChallenge!(doc.id, playerName);
                                                }
                                              },
                                            ),
                                          ]
                                        ],
                                      ),
                                    ),

                                    const SizedBox(width: 10),
                                    Column(
                                      crossAxisAlignment: CrossAxisAlignment.end,
                                      children: [
                                        Text("Lv. ${data['level'] ?? 1}", style: TextStyle(color: theme.playerRed, fontWeight: FontWeight.bold, fontSize: 12)),
                                        Text("${data['xp'] ?? 0} XP", style: TextStyle(color: theme.text.withOpacity(0.6), fontSize: 10)),
                                      ],
                                    ),

                                    if (!isMe) ...[
                                      const SizedBox(width: 8),
                                      GestureDetector(
                                        onTap: () async {
                                          await StorageService.instance.toggleFavorite(doc.id, playerName);
                                          setStateItem(() {});
                                        },
                                        child: Icon(isFav ? Icons.star : Icons.star_border, color: Colors.amber, size: 24),
                                      )
                                    ]
                                  ],
                                ),
                              );
                            }
                        );
                      }
                  );
                }
            ),
          ),

          const SizedBox(height: 15),
          SizedBox(
            width: double.infinity, height: 50,
            child: ElevatedButton(
              style: ElevatedButton.styleFrom(backgroundColor: Colors.amber.shade700, foregroundColor: Colors.black, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15))),
              onPressed: () => Navigator.pop(context),
              child: const Text("CHIUDI", style: TextStyle(fontSize: 16, fontWeight: FontWeight.w900, letterSpacing: 2)),
            ),
          )
        ],
      ),
    );

    if (themeType == AppThemeType.cyberpunk || themeType == AppThemeType.music) {
      content = AnimatedCyberBorder(child: content);
    }

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

// ===========================================================================
// 3. DIALOGO TUTORIAL
// ===========================================================================
class TutorialDialog extends StatelessWidget {
  const TutorialDialog({super.key});

  @override
  Widget build(BuildContext context) {
    final themeManager = context.watch<ThemeManager>();
    final theme = themeManager.currentColors;
    final themeType = themeManager.currentThemeType;
    Color inkColor = const Color(0xFF111122);

    String goldLabel = "ORO:";
    String bombLabel = "BOMBA:";
    String swapLabel = "SCAMBIO:";
    String jokerLabel = "JOLLY:";
    String iceLabel = "GHIACCIO:";
    String multiplierLabel = "x2:";
    String blockLabel = "BUCO NERO:";

    if (themeType == AppThemeType.grimorio) {
      goldLabel = "CORONA:";
      bombLabel = "STREGA:";
      jokerLabel = "GIULLARE:";
      swapLabel = "TORNADO:";
      multiplierLabel = "FULMINE:";
      blockLabel = "METEORITE:";
    } else if (themeType == AppThemeType.music) {
      goldLabel = "DISCO D'ORO:";
      bombLabel = "MUTO:";
      jokerLabel = "DJ:";
      swapLabel = "MIXER:";
      iceLabel = "NOTA:";
      multiplierLabel = "AVANTI VELOCE:";
      blockLabel = "PAUSA:";
    } else if (themeType == AppThemeType.arcade) {
      goldLabel = "GETTONE:";
      bombLabel = "FANTASMA:";
      jokerLabel = "GAMEPAD:";
      swapLabel = "SHUFFLE:";
      blockLabel = "POWER OFF:";
    } else if (themeType == AppThemeType.cyberpunk) {
      goldLabel = "CHIP:";
      bombLabel = "VIRUS:";
      jokerLabel = "BOT:";
      swapLabel = "NETWORK:";
      blockLabel = "FIREWALL:";
    } else if (themeType == AppThemeType.doodle) {
      bombLabel = "VIRUS:";
    }

    Widget dialogContent = themeType == AppThemeType.doodle
        ? Transform.rotate(
      angle: -0.01,
      child: CustomPaint(
        painter: DoodleBackgroundPainter(fillColor: Colors.yellow.shade50, strokeColor: inkColor, seed: 400),
        child: Padding(
          padding: const EdgeInsets.all(25.0),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Center(child: Text("COME GIOCARE", style: getSharedTextStyle(themeType, TextStyle(fontSize: 28, fontWeight: FontWeight.w900, color: inkColor, letterSpacing: 2)))),
              const SizedBox(height: 20),
              TutorialStep(icon: Icons.line_axis, text: "Chiudi i 4 lati di un quadrato per conquistare 1 punto e avere una mossa extra!", themeType: themeType, inkColor: inkColor, theme: theme),
              const SizedBox(height: 15),
              TutorialStep(icon: Icons.lens_blur, text: "Ma presta attenzione! Ogni quadrato nasconde un'insidia o un regalo!", themeType: themeType, inkColor: inkColor, theme: theme),
              const SizedBox(height: 15),
              const Divider(color: Colors.black26, thickness: 2),
              const SizedBox(height: 10),
              Center(child: Text("GLOSSARIO ARENA", style: getSharedTextStyle(themeType, TextStyle(fontSize: 18, fontWeight: FontWeight.w900, color: inkColor)))),
              const SizedBox(height: 10),

              TutorialStep(icon: ThemeIcons.gold(themeType), iconColor: Colors.amber.shade700, text: "$goldLabel Chiudilo per ottenere +2 Punti.", themeType: themeType, inkColor: inkColor, theme: theme),
              const SizedBox(height: 10),
              TutorialStep(icon: ThemeIcons.bomb(themeType), iconColor: Colors.deepPurple, text: "$bombLabel Non chiuderlo! Perderai -1 Punto.", themeType: themeType, inkColor: inkColor, theme: theme),
              const SizedBox(height: 10),
              TutorialStep(icon: ThemeIcons.swap(themeType), iconColor: Colors.purpleAccent, text: "$swapLabel Inverte istantaneamente i punteggi dei giocatori.", themeType: themeType, inkColor: inkColor, theme: theme),
              const SizedBox(height: 10),
              TutorialStep(icon: ThemeIcons.joker(themeType), iconColor: Colors.green.shade600, text: "$jokerLabel Scegli dove nasconderlo a inizio partita. Se lo chiudi tu +2, se lo chiude l'avversario -1!", themeType: themeType, inkColor: inkColor, theme: theme),
              const SizedBox(height: 10),
              TutorialStep(icon: ThemeIcons.ice(themeType), iconColor: Colors.cyanAccent, text: "$iceLabel Devi cliccarlo due volte per poterlo rompere e chiudere.", themeType: themeType, inkColor: inkColor, theme: theme),
              const SizedBox(height: 10),
              TutorialStep(icon: ThemeIcons.multiplier(themeType), iconColor: Colors.yellowAccent, text: "$multiplierLabel Non dà punti, ma raddoppia il punteggio della prossima casella che chiudi!", themeType: themeType, inkColor: inkColor, theme: theme),
              const SizedBox(height: 10),
              TutorialStep(icon: ThemeIcons.block(themeType), iconColor: Colors.grey, text: "$blockLabel Questa casella non esiste. Se la chiudi perdi il turno.", themeType: themeType, inkColor: inkColor, theme: theme),

              const SizedBox(height: 25),
              Center(
                child: GestureDetector(
                  onTap: () => Navigator.pop(context),
                  child: CustomPaint(
                    painter: DoodleBackgroundPainter(fillColor: Colors.red.shade200, strokeColor: inkColor, seed: 401),
                    child: Container(
                      height: 50, width: 150, alignment: Alignment.center,
                      child: Text("HO CAPITO!", style: getSharedTextStyle(themeType, TextStyle(fontSize: 18, fontWeight: FontWeight.w900, color: inkColor))),
                    ),
                  ),
                ),
              )
            ],
          ),
        ),
      ),
    )
        : Container(
      padding: const EdgeInsets.all(25.0),
      decoration: BoxDecoration(
        gradient: LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [theme.background.withOpacity(0.95), theme.background.withOpacity(0.8)]),
        borderRadius: BorderRadius.circular(25),
        border: themeType == AppThemeType.cyberpunk || themeType == AppThemeType.arcade || themeType == AppThemeType.music ? null : Border.all(color: Colors.white.withOpacity(0.15), width: 1.5),
        boxShadow: themeType == AppThemeType.cyberpunk || themeType == AppThemeType.arcade || themeType == AppThemeType.music ? [] : [BoxShadow(color: Colors.black.withOpacity(0.5), blurRadius: 20, offset: const Offset(4, 10))],
      ),
      child: SingleChildScrollView(
        physics: const BouncingScrollPhysics(),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Center(child: Text("COME GIOCARE", style: getSharedTextStyle(themeType, TextStyle(fontSize: 24, fontWeight: FontWeight.w900, color: theme.text, letterSpacing: 2)))),
            const SizedBox(height: 20),
            TutorialStep(icon: Icons.grid_4x4, text: "Chiudi i 4 lati di un quadrato per conquistare 1 punto e avere una mossa extra!", themeType: themeType, inkColor: inkColor, theme: theme),
            const SizedBox(height: 15),
            TutorialStep(icon: Icons.lens_blur, text: "Ma presta attenzione! Ogni quadrato nasconde un'insidia o un regalo!", themeType: themeType, inkColor: inkColor, theme: theme),
            const SizedBox(height: 15),
            const Divider(color: Colors.white24, thickness: 1.5),
            const SizedBox(height: 10),
            Center(child: Text("GLOSSARIO ARENA", style: getSharedTextStyle(themeType, TextStyle(fontSize: 16, fontWeight: FontWeight.w900, color: theme.text.withOpacity(0.7), letterSpacing: 1.5)))),
            const SizedBox(height: 15),

            TutorialStep(icon: ThemeIcons.gold(themeType), iconColor: Colors.amber, text: "$goldLabel Chiudilo per ottenere +2 Punti.", themeType: themeType, inkColor: inkColor, theme: theme),
            const SizedBox(height: 10),
            TutorialStep(icon: ThemeIcons.bomb(themeType), iconColor: themeType == AppThemeType.cyberpunk || themeType == AppThemeType.arcade ? Colors.greenAccent : Colors.deepPurple, text: "$bombLabel Non chiuderlo! Perderai -1 Punto.", themeType: themeType, inkColor: inkColor, theme: theme),
            const SizedBox(height: 10),
            TutorialStep(icon: ThemeIcons.swap(themeType), iconColor: Colors.purpleAccent, text: "$swapLabel Inverte istantaneamente i punteggi dei giocatori.", themeType: themeType, inkColor: inkColor, theme: theme),
            const SizedBox(height: 10),
            TutorialStep(icon: ThemeIcons.joker(themeType), iconColor: theme.playerBlue, text: "$jokerLabel Scegli dove nasconderlo a inizio partita. Se lo chiudi tu +2, se lo chiude l'avversario -1!", themeType: themeType, inkColor: inkColor, theme: theme),
            const SizedBox(height: 10),
            TutorialStep(icon: ThemeIcons.ice(themeType), iconColor: Colors.cyanAccent, text: "$iceLabel Devi cliccarlo due volte per poterlo rompere e chiudere.", themeType: themeType, inkColor: inkColor, theme: theme),
            const SizedBox(height: 10),
            TutorialStep(icon: ThemeIcons.multiplier(themeType), iconColor: Colors.yellowAccent, text: "$multiplierLabel Non dà punti, ma raddoppia il punteggio della prossima casella che chiudi!", themeType: themeType, inkColor: inkColor, theme: theme),
            const SizedBox(height: 10),
            TutorialStep(icon: ThemeIcons.block(themeType), iconColor: Colors.grey, text: "$blockLabel Questa casella non esiste. Se la chiudi perdi il turno.", themeType: themeType, inkColor: inkColor, theme: theme),

            const SizedBox(height: 30),
            SizedBox(
              width: double.infinity, height: 50,
              child: ElevatedButton(
                style: ElevatedButton.styleFrom(backgroundColor: theme.playerBlue, foregroundColor: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15))),
                onPressed: () => Navigator.pop(context),
                child: const Text("CHIUDI", style: TextStyle(fontSize: 16, fontWeight: FontWeight.w900, letterSpacing: 2)),
              ),
            )
          ],
        ),
      ),
    );

    if (themeType == AppThemeType.cyberpunk || themeType == AppThemeType.music) {
      dialogContent = AnimatedCyberBorder(child: dialogContent);
    }

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

class TutorialStep extends StatelessWidget {
  final IconData icon;
  final Color? iconColor;
  final String text;
  final AppThemeType themeType;
  final Color inkColor;
  final ThemeColors theme;

  const TutorialStep({super.key, required this.icon, this.iconColor, required this.text, required this.themeType, required this.inkColor, required this.theme});

  @override
  Widget build(BuildContext context) {
    return Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Icon(icon, color: iconColor ?? (themeType == AppThemeType.doodle ? inkColor : theme.playerBlue), size: 28),
        const SizedBox(width: 15),
        Expanded(
          child: Text(text, style: getSharedTextStyle(themeType, TextStyle(fontSize: 14, color: themeType == AppThemeType.doodle ? inkColor : theme.text.withOpacity(0.8), height: 1.3))),
        ),
      ],
    );
  }
}

// ===========================================================================
// 4. WIDGET ANIMATO PER TASTO SFIDA
// ===========================================================================
class PulsingChallengeButton extends StatefulWidget {
  final VoidCallback onTap;
  final AppThemeType themeType;

  const PulsingChallengeButton({super.key, required this.onTap, required this.themeType});

  @override
  State<PulsingChallengeButton> createState() => _PulsingChallengeButtonState();
}

class _PulsingChallengeButtonState extends State<PulsingChallengeButton> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this, duration: const Duration(milliseconds: 900))..repeat(reverse: true);
    _animation = Tween<double>(begin: 0.3, end: 1.0).animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut));
  }

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

  @override
  Widget build(BuildContext context) {
    final Color softGreen = Colors.green.shade400;

    return GestureDetector(
      onTap: widget.onTap,
      child: FadeTransition(
        opacity: _animation,
        child: Container(
          padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
          decoration: BoxDecoration(
            color: softGreen.withOpacity(0.15),
            border: Border.all(color: softGreen, width: 1.5),
            borderRadius: BorderRadius.circular(6),
          ),
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              Icon(Icons.circle, color: softGreen, size: 8),
              const SizedBox(width: 4),
              Text(
                  "SFIDA",
                  style: getSharedTextStyle(widget.themeType, TextStyle(color: softGreen, fontSize: 10, fontWeight: FontWeight.bold))
              ),
            ],
          ),
        ),
      ),
    );
  }
}
// ===========================================================================
// 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_modals.dart
// ===========================================================================

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

import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../../core/theme_manager.dart';
import '../../core/app_colors.dart';
import '../../logic/game_controller.dart';
import '../../models/game_board.dart';
import '../../services/storage_service.dart';
import '../../services/multiplayer_service.dart';
import '../../l10n/app_localizations.dart';
import '../../widgets/painters.dart';
import '../../widgets/cyber_border.dart';
import '../game/game_screen.dart';
import '../multiplayer/lobby_screen.dart';
import '../multiplayer/lobby_widgets.dart';

class HomeModals {

  static void showNameDialog(BuildContext context, VoidCallback onSuccess) {
    final TextEditingController nameController = TextEditingController(text: StorageService.instance.playerName);
    final TextEditingController passController = TextEditingController();
    bool isLoadingAuth = false;
    bool obscurePassword = true;
    String errorMessage = "";

    showDialog(
      context: context,
      barrierDismissible: false,
      barrierColor: Colors.black.withOpacity(0.8),
      builder: (dialogContext) {
        final themeManager = dialogContext.watch<ThemeManager>();
        final themeType = themeManager.currentThemeType;
        Color inkColor = const Color(0xFF111122);
        final loc = AppLocalizations.of(dialogContext)!;

        return StatefulBuilder(
          builder: (context, setStateDialog) {

            Future<void> handleAuth(bool isLogin) async {
              final name = nameController.text.trim();
              final password = passController.text.trim();

              setStateDialog(() { errorMessage = ""; isLoadingAuth = true; });

              if (name.isEmpty || password.isEmpty) {
                setStateDialog(() { errorMessage = "Inserisci Nome e Password!"; isLoadingAuth = false; });
                return;
              }
              if (password.length < 6) {
                setStateDialog(() { errorMessage = "La password deve avere almeno 6 caratteri!"; isLoadingAuth = false; });
                return;
              }

              final fakeEmail = "${name.toLowerCase().replaceAll(' ', '')}@tetraq.game";
              final currentUser = FirebaseAuth.instance.currentUser;

              // CATTURIAMO IL FANTASMA: Se siamo in un account anonimo provvisorio, ci salviamo il suo ID
              final ghostUid = (currentUser != null && currentUser.isAnonymous) ? currentUser.uid : null;

              try {
                if (isLogin) {
                  // ==========================================
                  // 1. TENTA IL LOGIN UFFICIALE
                  // ==========================================

                  // --- LA MOSSA DEL NINJA: ELIMINIAMO IL GHOST PRIMA DEL LOGIN ---
                  // Lo eliminiamo ORA perché abbiamo ancora i permessi dell'utente anonimo.
                  if (ghostUid != null) {
                    await FirebaseFirestore.instance.collection('leaderboard').doc(ghostUid).delete().catchError((e) => null);
                  }

                  // Ora effettuiamo l'accesso
                  await FirebaseAuth.instance.signInWithEmailAndPassword(email: fakeEmail, password: password);

                  // Recupera i dati storici dal Cloud per sovrascrivere quelli in locale
                  final doc = await FirebaseFirestore.instance.collection('leaderboard').doc(FirebaseAuth.instance.currentUser!.uid).get();
                  if (doc.exists) {
                    final data = doc.data() as Map<String, dynamic>;
                    final prefs = await SharedPreferences.getInstance();
                    await prefs.setInt('totalXP', data['xp'] ?? 0);
                    await prefs.setInt('wins', data['wins'] ?? 0);
                    await prefs.setInt('losses', data['losses'] ?? 0);
                    if (context.mounted) ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Bentornato $name! Dati sincronizzati."), backgroundColor: Colors.green));
                  } else {
                    StorageService.instance.syncLeaderboard();
                    if (context.mounted) ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Bentornato $name! Profilo ripristinato."), backgroundColor: Colors.green));
                  }

                } else {
                  // ==========================================
                  // 2. TENTA LA REGISTRAZIONE / UPGRADE
                  // ==========================================
                  if (currentUser != null && currentUser.isAnonymous) {
                    // L'utente aveva un account anonimo, lo promuoviamo ad account con password
                    final credential = EmailAuthProvider.credential(email: fakeEmail, password: password);
                    await currentUser.linkWithCredential(credential);
                    if (context.mounted) ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Profilo Cloud protetto con successo!"), backgroundColor: Colors.green));
                  } else {
                    // Se per caso si trova senza nessun account, ne creiamo uno nuovo
                    await FirebaseAuth.instance.createUserWithEmailAndPassword(email: fakeEmail, password: password);
                    if (context.mounted) ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Account creato con successo!"), backgroundColor: Colors.green));
                  }
                }

                // Salva il nome e lancia il sync
                await StorageService.instance.savePlayerName(name);
                StorageService.instance.syncLeaderboard();

                if (context.mounted) Navigator.of(dialogContext).pop();
                onSuccess();

              } on FirebaseAuthException catch (e) {
                String msg = "Errore di autenticazione.";
                if (e.code == 'email-already-in-use' || e.code == 'credential-already-in-use') {
                  msg = "Nome già registrato!\nSe sei tu, clicca su ACCEDI.";
                } else if (e.code == 'user-not-found' || e.code == 'wrong-password' || e.code == 'invalid-credential') {
                  msg = "Nome o Password errati!";
                  // Siccome avevamo cancellato il ghost prima, se il login fallisce lo ricreiamo per non perdere i dati locali
                  if (isLogin && ghostUid != null) StorageService.instance.syncLeaderboard();
                } else if (e.code == 'requires-recent-login') {
                  msg = "Errore di sessione. Riavvia l'app.";
                }
                setStateDialog(() { errorMessage = msg; isLoadingAuth = false; });
              } catch (e) {
                setStateDialog(() { errorMessage = "Errore imprevisto: $e"; isLoadingAuth = false; });
                if (isLogin && ghostUid != null) StorageService.instance.syncLeaderboard();
              }
            }

            Widget dialogContent = themeType == AppThemeType.doodle
                ? CustomPaint(
              painter: DoodleBackgroundPainter(fillColor: Colors.yellow.shade100, strokeColor: inkColor, seed: 100),
              child: SingleChildScrollView(
                physics: const BouncingScrollPhysics(),
                child: Padding(
                  padding: const EdgeInsets.symmetric(vertical: 20.0, horizontal: 20.0),
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Text(loc.welcomeTitle, style: getSharedTextStyle(themeType, TextStyle(color: inkColor, fontWeight: FontWeight.w900, fontSize: 24, letterSpacing: 2.0)), textAlign: TextAlign.center),
                      const SizedBox(height: 10),
                      Text('Scegli una Password per il Cloud.\nI tuoi XP e il tuo Livello saranno protetti e non li perderai mai!', style: getSharedTextStyle(themeType, TextStyle(color: inkColor.withOpacity(0.8), fontSize: 13, fontWeight: FontWeight.bold)), textAlign: TextAlign.center),
                      const SizedBox(height: 15),
                      TextField(
                        controller: nameController, textCapitalization: TextCapitalization.characters, textAlign: TextAlign.center, maxLength: 8,
                        style: getSharedTextStyle(themeType, TextStyle(color: inkColor, fontSize: 24, fontWeight: FontWeight.bold, letterSpacing: 4)),
                        decoration: InputDecoration(
                            hintText: loc.nameHint, hintStyle: getSharedTextStyle(themeType, TextStyle(color: inkColor.withOpacity(0.3), letterSpacing: 4)),
                            filled: false, counterText: "",
                            enabledBorder: UnderlineInputBorder(borderSide: BorderSide(color: inkColor, width: 3)),
                            focusedBorder: UnderlineInputBorder(borderSide: BorderSide(color: Colors.red.shade200, width: 5))
                        ),
                      ),
                      const SizedBox(height: 8),
                      TextField(
                        controller: passController, obscureText: obscurePassword, textAlign: TextAlign.center, maxLength: 20,
                        style: getSharedTextStyle(themeType, TextStyle(color: inkColor, fontSize: 20, fontWeight: FontWeight.bold, letterSpacing: 8)),
                        decoration: InputDecoration(
                          hintText: "PASSWORD", hintStyle: getSharedTextStyle(themeType, TextStyle(color: inkColor.withOpacity(0.3), letterSpacing: 4)),
                          filled: false, counterText: "",
                          enabledBorder: UnderlineInputBorder(borderSide: BorderSide(color: inkColor, width: 3)),
                          focusedBorder: UnderlineInputBorder(borderSide: BorderSide(color: Colors.red.shade200, width: 5)),
                          suffixIcon: IconButton(
                            icon: Icon(obscurePassword ? Icons.visibility : Icons.visibility_off, color: inkColor.withOpacity(0.6)),
                            onPressed: () { setStateDialog(() { obscurePassword = !obscurePassword; }); },
                          ),
                        ),
                      ),
                      const SizedBox(height: 15),
                      if (errorMessage.isNotEmpty)
                        Padding(padding: const EdgeInsets.only(bottom: 10), child: Text(errorMessage, style: getSharedTextStyle(themeType, const TextStyle(color: Colors.red, fontSize: 14, fontWeight: FontWeight.bold)), textAlign: TextAlign.center)),
                      Text("💡 Usa una password facile da ricordare!", style: getSharedTextStyle(themeType, TextStyle(color: inkColor.withOpacity(0.6), fontSize: 11, height: 1.3)), textAlign: TextAlign.center),
                      const SizedBox(height: 15),
                      isLoadingAuth ? CircularProgressIndicator(color: inkColor) : Row(
                        children: [
                          Expanded(child: GestureDetector(onTap: () => handleAuth(true), child: CustomPaint(painter: DoodleBackgroundPainter(fillColor: Colors.blue.shade200, strokeColor: inkColor, seed: 101), child: Container(height: 45, alignment: Alignment.center, child: Text("ACCEDI", style: getSharedTextStyle(themeType, TextStyle(color: inkColor, fontSize: 14, fontWeight: FontWeight.bold, letterSpacing: 1.5))))))),
                          const SizedBox(width: 10),
                          Expanded(child: GestureDetector(onTap: () => handleAuth(false), child: CustomPaint(painter: DoodleBackgroundPainter(fillColor: Colors.green.shade200, strokeColor: inkColor, seed: 102), child: Container(height: 45, alignment: Alignment.center, child: Text("REGISTRATI", style: getSharedTextStyle(themeType, TextStyle(color: inkColor, fontSize: 14, fontWeight: FontWeight.bold, letterSpacing: 1.5))))))),
                        ],
                      ),
                    ],
                  ),
                ),
              ),
            )
                : Container(
              decoration: BoxDecoration(color: themeManager.currentColors.background, borderRadius: BorderRadius.circular(25), border: Border.all(color: themeManager.currentColors.playerBlue.withOpacity(0.5), width: 2), boxShadow: [BoxShadow(color: themeManager.currentColors.playerBlue.withOpacity(0.3), blurRadius: 20, spreadRadius: 5)]),
              child: SingleChildScrollView(
                physics: const BouncingScrollPhysics(),
                child: Padding(
                  padding: const EdgeInsets.symmetric(vertical: 20.0, horizontal: 20.0),
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Text(loc.welcomeTitle, style: getSharedTextStyle(themeType, TextStyle(color: themeManager.currentColors.text, fontWeight: FontWeight.w900, fontSize: 20, letterSpacing: 1.5)), textAlign: TextAlign.center),
                      const SizedBox(height: 10),
                      Text('Scegli una Password per il Cloud.\nI tuoi XP e il tuo Livello saranno protetti e non li perderai mai!', style: getSharedTextStyle(themeType, TextStyle(color: themeManager.currentColors.text.withOpacity(0.8), fontSize: 13, fontWeight: FontWeight.bold)), textAlign: TextAlign.center),
                      const SizedBox(height: 15),
                      TextField(
                        controller: nameController, textCapitalization: TextCapitalization.characters, textAlign: TextAlign.center, maxLength: 8,
                        style: getSharedTextStyle(themeType, TextStyle(color: themeManager.currentColors.text, fontSize: 24, fontWeight: FontWeight.bold, letterSpacing: 4)),
                        decoration: InputDecoration(
                            hintText: loc.nameHint, hintStyle: getSharedTextStyle(themeType, TextStyle(color: themeManager.currentColors.text.withOpacity(0.3), letterSpacing: 4)),
                            filled: true, fillColor: themeManager.currentColors.text.withOpacity(0.05), counterText: "",
                            enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: themeManager.currentColors.gridLine.withOpacity(0.5), width: 2), borderRadius: BorderRadius.circular(15)),
                            focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: themeManager.currentColors.playerBlue, width: 3), borderRadius: BorderRadius.circular(15))
                        ),
                      ),
                      const SizedBox(height: 10),
                      TextField(
                        controller: passController, obscureText: obscurePassword, textAlign: TextAlign.center, maxLength: 20,
                        style: getSharedTextStyle(themeType, TextStyle(color: themeManager.currentColors.text, fontSize: 20, fontWeight: FontWeight.bold, letterSpacing: 8)),
                        decoration: InputDecoration(
                          hintText: "PASSWORD", hintStyle: getSharedTextStyle(themeType, TextStyle(color: themeManager.currentColors.text.withOpacity(0.3), letterSpacing: 4)),
                          filled: true, fillColor: themeManager.currentColors.text.withOpacity(0.05), counterText: "",
                          enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: themeManager.currentColors.gridLine.withOpacity(0.5), width: 2), borderRadius: BorderRadius.circular(15)),
                          focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: themeManager.currentColors.playerBlue, width: 3), borderRadius: BorderRadius.circular(15)),
                          suffixIcon: IconButton(
                            icon: Icon(obscurePassword ? Icons.visibility : Icons.visibility_off, color: themeManager.currentColors.text.withOpacity(0.6)),
                            onPressed: () { setStateDialog(() { obscurePassword = !obscurePassword; }); },
                          ),
                        ),
                      ),
                      const SizedBox(height: 15),
                      if (errorMessage.isNotEmpty)
                        Padding(padding: const EdgeInsets.only(bottom: 10), child: Text(errorMessage, style: getSharedTextStyle(themeType, const TextStyle(color: Colors.redAccent, fontSize: 14, fontWeight: FontWeight.bold)), textAlign: TextAlign.center)),
                      Text("💡 Usa una password facile da ricordare!", style: getSharedTextStyle(themeType, TextStyle(color: themeManager.currentColors.text.withOpacity(0.6), fontSize: 11, height: 1.3)), textAlign: TextAlign.center),
                      const SizedBox(height: 20),
                      isLoadingAuth ? CircularProgressIndicator(color: themeManager.currentColors.playerBlue) : Row(
                        children: [
                          Expanded(child: SizedBox(height: 45, child: ElevatedButton(style: ElevatedButton.styleFrom(backgroundColor: themeManager.currentColors.text.withOpacity(0.1), foregroundColor: themeManager.currentColors.text, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)), side: BorderSide(color: themeManager.currentColors.playerBlue, width: 1.5)), onPressed: () => handleAuth(true), child: Text("ACCEDI", style: getSharedTextStyle(themeType, const TextStyle(fontSize: 13, fontWeight: FontWeight.bold, letterSpacing: 1.0)))))),
                          const SizedBox(width: 10),
                          Expanded(child: SizedBox(height: 45, child: ElevatedButton(style: ElevatedButton.styleFrom(backgroundColor: themeManager.currentColors.playerBlue, foregroundColor: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15))), onPressed: () => handleAuth(false), child: Text("REGISTRATI", style: getSharedTextStyle(themeType, const TextStyle(fontSize: 13, fontWeight: FontWeight.bold, letterSpacing: 1.0)))))),
                        ],
                      ),
                    ],
                  ),
                ),
              ),
            );

            if (themeType == AppThemeType.cyberpunk || themeType == AppThemeType.music) dialogContent = AnimatedCyberBorder(child: dialogContent);

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

  static Widget _buildTimeOption(String label, String sub, String value, String current, ThemeColors theme, AppThemeType type, VoidCallback onTap) {
    bool isSel = value == current;
    return Expanded(
      child: GestureDetector(
        onTap: onTap,
        child: Container(
          margin: const EdgeInsets.symmetric(horizontal: 4),
          height: 50,
          decoration: BoxDecoration(
            color: isSel ? Colors.orange.shade600 : (type == AppThemeType.doodle ? Colors.white : theme.text.withOpacity(0.05)),
            borderRadius: BorderRadius.circular(12),
            border: Border.all(color: isSel ? Colors.orange.shade800 : (type == AppThemeType.doodle ? const Color(0xFF111122) : Colors.white24), width: isSel ? 2 : 1.5),
            boxShadow: isSel && type != AppThemeType.doodle ? [BoxShadow(color: Colors.orange.withOpacity(0.5), blurRadius: 8)] : [],
          ),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(label, style: getSharedTextStyle(type, TextStyle(color: isSel ? Colors.white : (type == AppThemeType.doodle ? const Color(0xFF111122) : theme.text), fontWeight: FontWeight.w900, fontSize: 13))),
              if (sub.isNotEmpty) Text(sub, style: getSharedTextStyle(type, TextStyle(color: isSel ? Colors.white70 : (type == AppThemeType.doodle ? Colors.black54 : theme.text.withOpacity(0.5)), fontWeight: FontWeight.bold, fontSize: 8))),
            ],
          ),
        ),
      ),
    );
  }

  static void showChallengeSetupDialog(BuildContext context, String targetName, Function(int radius, ArenaShape shape, String timeMode) onStart) {
    int localRadius = 4; ArenaShape localShape = ArenaShape.classic; String localTimeMode = 'fixed';
    bool isChaosUnlocked = StorageService.instance.playerLevel >= 7;

    showDialog(
        context: context, barrierColor: Colors.black.withOpacity(0.8),
        builder: (ctx) {
          final themeManager = ctx.watch<ThemeManager>();
          final theme = themeManager.currentColors; final themeType = themeManager.currentThemeType;
          Color inkColor = const Color(0xFF111122);

          return StatefulBuilder(
            builder: (context, setStateDialog) {
              Widget dialogContent = themeType == AppThemeType.doodle
                  ? Transform.rotate(
                angle: 0.015,
                child: CustomPaint(
                  painter: DoodleBackgroundPainter(fillColor: Colors.white.withOpacity(0.95), strokeColor: inkColor, seed: 200),
                  child: SingleChildScrollView(
                    physics: const BouncingScrollPhysics(),
                    child: Padding(
                      padding: const EdgeInsets.all(25.0),
                      child: Column(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          Text("SFIDA $targetName", textAlign: TextAlign.center, style: getSharedTextStyle(themeType, TextStyle(fontSize: 26, fontWeight: FontWeight.w900, color: theme.playerRed, letterSpacing: 2))),
                          const SizedBox(height: 10),
                          Text("IMPOSTAZIONI STANZA", style: getSharedTextStyle(themeType, TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: inkColor.withOpacity(0.6), letterSpacing: 1.5))),
                          const SizedBox(height: 25),

                          Text("FORMA ARENA", style: getSharedTextStyle(themeType, TextStyle(fontSize: 14, fontWeight: FontWeight.w900, color: inkColor.withOpacity(0.6), letterSpacing: 1.5))), const SizedBox(height: 15),
                          Wrap(
                            spacing: 12, runSpacing: 12, alignment: WrapAlignment.center,
                            children: [
                              NeonShapeButton(icon: Icons.diamond_outlined, label: 'Rombo', isSelected: localShape == ArenaShape.classic, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localShape = ArenaShape.classic)),
                              NeonShapeButton(icon: Icons.add, label: 'Croce', isSelected: localShape == ArenaShape.cross, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localShape = ArenaShape.cross)),
                              NeonShapeButton(icon: Icons.donut_large, label: 'Buco', isSelected: localShape == ArenaShape.donut, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localShape = ArenaShape.donut)),
                              NeonShapeButton(icon: Icons.hourglass_bottom, label: 'Clessidra', isSelected: localShape == ArenaShape.hourglass, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localShape = ArenaShape.hourglass)),
                              NeonShapeButton(icon: Icons.all_inclusive, label: 'Caos', isSelected: localShape == ArenaShape.chaos, theme: theme, themeType: themeType, isSpecial: true, isLocked: !isChaosUnlocked, onTap: () => setStateDialog(() => localShape = ArenaShape.chaos)),
                            ],
                          ),
                          const SizedBox(height: 25), Divider(color: inkColor.withOpacity(0.3), thickness: 2.5), const SizedBox(height: 20),

                          Text("GRANDEZZA", style: getSharedTextStyle(themeType, TextStyle(fontSize: 14, fontWeight: FontWeight.w900, color: inkColor.withOpacity(0.6), letterSpacing: 1.5))), const SizedBox(height: 15),
                          Row(
                            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                            children: [
                              NeonSizeButton(label: 'S', isSelected: localRadius == 3, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localRadius = 3)),
                              NeonSizeButton(label: 'M', isSelected: localRadius == 4, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localRadius = 4)),
                              NeonSizeButton(label: 'L', isSelected: localRadius == 5, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localRadius = 5)),
                              NeonSizeButton(label: 'MAX', isSelected: localRadius == 6, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localRadius = 6)),
                            ],
                          ),
                          const SizedBox(height: 25), Divider(color: inkColor.withOpacity(0.3), thickness: 2.5), const SizedBox(height: 20),

                          Text("TEMPO E OPZIONI", style: getSharedTextStyle(themeType, TextStyle(fontSize: 14, fontWeight: FontWeight.w900, color: inkColor.withOpacity(0.6), letterSpacing: 1.5))), const SizedBox(height: 10),
                          Row(
                            children: [
                              _buildTimeOption('10s', 'FISSO', 'fixed', localTimeMode, theme, themeType, () => setStateDialog(() => localTimeMode = 'fixed')),
                              _buildTimeOption('RELAX', 'INFINITO', 'relax', localTimeMode, theme, themeType, () => setStateDialog(() => localTimeMode = 'relax')),
                              _buildTimeOption('DINAMICO', '-2s A PARTITA', 'dynamic', localTimeMode, theme, themeType, () => setStateDialog(() => localTimeMode = 'dynamic')),
                            ],
                          ),
                          const SizedBox(height: 35),

                          Row(
                            children: [
                              Expanded(
                                child: GestureDetector(
                                  onTap: () {
                                    Navigator.pop(ctx);
                                    onStart(localRadius, localShape, localTimeMode);
                                  },
                                  child: CustomPaint(painter: DoodleBackgroundPainter(fillColor: theme.playerRed, strokeColor: inkColor, seed: 300), child: Container(height: 55, alignment: Alignment.center, child: Text("AVVIA", style: getSharedTextStyle(themeType, const TextStyle(fontSize: 18, fontWeight: FontWeight.w900, letterSpacing: 2.0, color: Colors.white))))),
                                ),
                              ),
                              const SizedBox(width: 15),
                              Expanded(
                                child: GestureDetector(
                                  onTap: () => Navigator.pop(ctx),
                                  child: CustomPaint(painter: DoodleBackgroundPainter(fillColor: Colors.grey.shade400, strokeColor: inkColor, seed: 301), child: Container(height: 55, alignment: Alignment.center, child: Text("ANNULLA", style: getSharedTextStyle(themeType, const TextStyle(fontSize: 18, fontWeight: FontWeight.w900, letterSpacing: 2.0, color: Colors.white))))),
                                ),
                              ),
                            ],
                          )
                        ],
                      ),
                    ),
                  ),
                ),
              )
                  : Container(
                decoration: BoxDecoration(
                  gradient: LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [theme.background.withOpacity(0.95), theme.background.withOpacity(0.8)]),
                  borderRadius: BorderRadius.circular(25), border: themeType == AppThemeType.cyberpunk || themeType == AppThemeType.arcade || themeType == AppThemeType.music ? null : Border.all(color: Colors.white.withOpacity(0.15), width: 1.5),
                  boxShadow: themeType == AppThemeType.cyberpunk || themeType == AppThemeType.arcade || themeType == AppThemeType.music ? [] : [BoxShadow(color: Colors.black.withOpacity(0.5), blurRadius: 20, offset: const Offset(4, 10))],
                ),
                child: SingleChildScrollView(
                  physics: const BouncingScrollPhysics(),
                  child: Padding(
                    padding: const EdgeInsets.all(20.0),
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        Text("SFIDA $targetName", textAlign: TextAlign.center, style: getSharedTextStyle(themeType, TextStyle(fontSize: 24, fontWeight: FontWeight.w900, color: theme.playerRed, letterSpacing: 2))),
                        const SizedBox(height: 10),
                        Text("IMPOSTAZIONI STANZA", style: getSharedTextStyle(themeType, TextStyle(fontSize: 12, fontWeight: FontWeight.bold, color: theme.text.withOpacity(0.5), letterSpacing: 1.5))),
                        const SizedBox(height: 20),

                        Text("FORMA ARENA", style: getSharedTextStyle(themeType, TextStyle(fontSize: 12, 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: localShape == ArenaShape.classic, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localShape = ArenaShape.classic)),
                            NeonShapeButton(icon: Icons.add, label: 'Croce', isSelected: localShape == ArenaShape.cross, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localShape = ArenaShape.cross)),
                            NeonShapeButton(icon: Icons.donut_large, label: 'Buco', isSelected: localShape == ArenaShape.donut, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localShape = ArenaShape.donut)),
                            NeonShapeButton(icon: Icons.hourglass_bottom, label: 'Clessidra', isSelected: localShape == ArenaShape.hourglass, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localShape = ArenaShape.hourglass)),
                            NeonShapeButton(icon: Icons.all_inclusive, label: 'Caos', isSelected: localShape == ArenaShape.chaos, theme: theme, themeType: themeType, isSpecial: true, isLocked: !isChaosUnlocked, onTap: () => setStateDialog(() => localShape = ArenaShape.chaos)),
                          ],
                        ),
                        const SizedBox(height: 20), Divider(color: Colors.white.withOpacity(0.05), thickness: 2), const SizedBox(height: 20),

                        Text("GRANDEZZA", style: getSharedTextStyle(themeType, TextStyle(fontSize: 12, fontWeight: FontWeight.w900, color: theme.text.withOpacity(0.5), letterSpacing: 1.5))), const SizedBox(height: 10),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                          children: [
                            NeonSizeButton(label: 'S', isSelected: localRadius == 3, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localRadius = 3)),
                            NeonSizeButton(label: 'M', isSelected: localRadius == 4, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localRadius = 4)),
                            NeonSizeButton(label: 'L', isSelected: localRadius == 5, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localRadius = 5)),
                            NeonSizeButton(label: 'MAX', isSelected: localRadius == 6, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localRadius = 6)),
                          ],
                        ),
                        const SizedBox(height: 20), Divider(color: Colors.white.withOpacity(0.05), thickness: 2), const SizedBox(height: 20),

                        Text("TEMPO E OPZIONI", style: getSharedTextStyle(themeType, TextStyle(fontSize: 12, fontWeight: FontWeight.w900, color: theme.text.withOpacity(0.5), letterSpacing: 1.5))), const SizedBox(height: 10),
                        Row(
                          children: [
                            _buildTimeOption('10s', 'FISSO', 'fixed', localTimeMode, theme, themeType, () => setStateDialog(() => localTimeMode = 'fixed')),
                            _buildTimeOption('RELAX', 'INFINITO', 'relax', localTimeMode, theme, themeType, () => setStateDialog(() => localTimeMode = 'relax')),
                            _buildTimeOption('DINAMICO', '-2s A PARTITA', 'dynamic', localTimeMode, theme, themeType, () => setStateDialog(() => localTimeMode = 'dynamic')),
                          ],
                        ),
                        const SizedBox(height: 30),

                        Row(
                          children: [
                            Expanded(
                              child: SizedBox(
                                height: 55,
                                child: ElevatedButton(
                                  style: ElevatedButton.styleFrom(backgroundColor: theme.playerRed, foregroundColor: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15))),
                                  onPressed: () {
                                    Navigator.pop(ctx);
                                    onStart(localRadius, localShape, localTimeMode);
                                  },
                                  child: const Text("AVVIA", style: TextStyle(fontSize: 16, fontWeight: FontWeight.w900, letterSpacing: 2)),
                                ),
                              ),
                            ),
                            const SizedBox(width: 15),
                            Expanded(
                              child: SizedBox(
                                height: 55,
                                child: ElevatedButton(
                                  style: ElevatedButton.styleFrom(backgroundColor: Colors.grey.shade800, foregroundColor: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15))),
                                  onPressed: () => Navigator.pop(ctx),
                                  child: const Text("ANNULLA", style: TextStyle(fontSize: 16, fontWeight: FontWeight.w900, letterSpacing: 2)),
                                ),
                              ),
                            ),
                          ],
                        )
                      ],
                    ),
                  ),
                ),
              );

              if (themeType == AppThemeType.cyberpunk || themeType == AppThemeType.music) {
                dialogContent = AnimatedCyberBorder(child: dialogContent);
              }

              return Dialog(backgroundColor: Colors.transparent, insetPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 20), child: dialogContent);
            },
          );
        }
    );
  }

  static void showMatchSetupDialog(BuildContext context, bool isVsCPU) {
    int localRadius = 4; ArenaShape localShape = ArenaShape.classic; String localTimeMode = 'fixed';
    bool isChaosUnlocked = StorageService.instance.playerLevel >= 7;
    final loc = AppLocalizations.of(context)!;

    showDialog(
        context: context, barrierColor: Colors.black.withOpacity(0.8),
        builder: (ctx) {
          final themeManager = ctx.watch<ThemeManager>();
          final theme = themeManager.currentColors; final themeType = themeManager.currentThemeType;
          Color inkColor = const Color(0xFF111122);

          return StatefulBuilder(
            builder: (context, setStateDialog) {
              Widget dialogContent = themeType == AppThemeType.doodle
                  ? Transform.rotate(
                angle: 0.015,
                child: CustomPaint(
                  painter: DoodleBackgroundPainter(fillColor: Colors.white.withOpacity(0.95), strokeColor: inkColor, seed: 200),
                  child: SingleChildScrollView(
                    physics: const BouncingScrollPhysics(),
                    child: Padding(
                      padding: const EdgeInsets.all(25.0),
                      child: Column(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          Row(children: [ SizedBox(width: 40, child: IconButton(padding: EdgeInsets.zero, alignment: Alignment.centerLeft, icon: Icon(Icons.arrow_back_ios_new, color: inkColor, size: 26), onPressed: () => Navigator.pop(ctx))), Expanded(child: Text(isVsCPU ? loc.cpuTitle : loc.localTitle, textAlign: TextAlign.center, style: getSharedTextStyle(themeType, TextStyle(fontSize: 26, fontWeight: FontWeight.w900, color: inkColor, letterSpacing: 2)))), const SizedBox(width: 40) ]),
                          const SizedBox(height: 25),

                          if (isVsCPU) ...[
                            Icon(Icons.smart_toy, size: 50, color: inkColor.withOpacity(0.6)), const SizedBox(height: 10),
                            Text("MODALITÀ CAMPAGNA", style: getSharedTextStyle(themeType, TextStyle(fontSize: 16, fontWeight: FontWeight.w900, color: inkColor))), const SizedBox(height: 10),
                            Text("Livello CPU: ${StorageService.instance.cpuLevel}\nForma e tempo si adatteranno alla tua bravura!", textAlign: TextAlign.center, style: getSharedTextStyle(themeType, TextStyle(fontSize: 13, color: inkColor.withOpacity(0.8), height: 1.4))), const SizedBox(height: 25),
                            Divider(color: inkColor.withOpacity(0.3), thickness: 2.5), const SizedBox(height: 20),
                          ] else ...[
                            Text("FORMA ARENA", style: getSharedTextStyle(themeType, TextStyle(fontSize: 14, fontWeight: FontWeight.w900, color: inkColor.withOpacity(0.6), letterSpacing: 1.5))), const SizedBox(height: 15),
                            Wrap(
                              spacing: 12, runSpacing: 12, alignment: WrapAlignment.center,
                              children: [
                                NeonShapeButton(icon: Icons.diamond_outlined, label: 'Rombo', isSelected: localShape == ArenaShape.classic, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localShape = ArenaShape.classic)),
                                NeonShapeButton(icon: Icons.add, label: 'Croce', isSelected: localShape == ArenaShape.cross, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localShape = ArenaShape.cross)),
                                NeonShapeButton(icon: Icons.donut_large, label: 'Buco', isSelected: localShape == ArenaShape.donut, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localShape = ArenaShape.donut)),
                                NeonShapeButton(icon: Icons.hourglass_bottom, label: 'Clessidra', isSelected: localShape == ArenaShape.hourglass, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localShape = ArenaShape.hourglass)),
                                NeonShapeButton(icon: Icons.all_inclusive, label: 'Caos', isSelected: localShape == ArenaShape.chaos, theme: theme, themeType: themeType, isSpecial: true, isLocked: !isChaosUnlocked, onTap: () => setStateDialog(() => localShape = ArenaShape.chaos)),
                              ],
                            ),
                            const SizedBox(height: 25), Divider(color: inkColor.withOpacity(0.3), thickness: 2.5), const SizedBox(height: 20),

                            Text("GRANDEZZA", style: getSharedTextStyle(themeType, TextStyle(fontSize: 14, fontWeight: FontWeight.w900, color: inkColor.withOpacity(0.6), letterSpacing: 1.5))), const SizedBox(height: 15),
                            Row(
                              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                              children: [
                                NeonSizeButton(label: 'S', isSelected: localRadius == 3, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localRadius = 3)),
                                NeonSizeButton(label: 'M', isSelected: localRadius == 4, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localRadius = 4)),
                                NeonSizeButton(label: 'L', isSelected: localRadius == 5, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localRadius = 5)),
                                NeonSizeButton(label: 'MAX', isSelected: localRadius == 6, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localRadius = 6)),
                              ],
                            ),
                            const SizedBox(height: 25), Divider(color: inkColor.withOpacity(0.3), thickness: 2.5), const SizedBox(height: 20),

                            // TEMPO È ORA ESCLUSIVO PER IL MULTIPLAYER
                            Text("TEMPO", style: getSharedTextStyle(themeType, TextStyle(fontSize: 14, fontWeight: FontWeight.w900, color: inkColor.withOpacity(0.6), letterSpacing: 1.5))), const SizedBox(height: 10),
                            Row(
                              children: [
                                _buildTimeOption('10s', 'FISSO', 'fixed', localTimeMode, theme, themeType, () => setStateDialog(() => localTimeMode = 'fixed')),
                                _buildTimeOption('RELAX', 'INFINITO', 'relax', localTimeMode, theme, themeType, () => setStateDialog(() => localTimeMode = 'relax')),
                                _buildTimeOption('DINAMICO', '-2s A PARTITA', 'dynamic', localTimeMode, theme, themeType, () => setStateDialog(() => localTimeMode = 'dynamic')),
                              ],
                            ), const SizedBox(height: 35),
                          ],

                          Transform.rotate(
                            angle: -0.02,
                            child: GestureDetector(
                              onTap: () { Navigator.pop(ctx); context.read<GameController>().startNewGame(localRadius, vsCPU: isVsCPU, shape: localShape, timeMode: localTimeMode); Navigator.push(context, MaterialPageRoute(builder: (_) => const GameScreen())); },
                              child: CustomPaint(painter: DoodleBackgroundPainter(fillColor: Colors.green.shade200, strokeColor: inkColor, seed: 300), child: Container(height: 65, width: double.infinity, alignment: Alignment.center, child: Text(loc.startGame, style: getSharedTextStyle(themeType, TextStyle(fontSize: 22, fontWeight: FontWeight.w900, letterSpacing: 3.0, color: inkColor))))),
                            ),
                          )
                        ],
                      ),
                    ),
                  ),
                ),
              )
                  : Container(
                decoration: BoxDecoration(
                  gradient: LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [theme.background.withOpacity(0.95), theme.background.withOpacity(0.8)]),
                  borderRadius: BorderRadius.circular(25), border: themeType == AppThemeType.cyberpunk || themeType == AppThemeType.arcade || themeType == AppThemeType.music ? null : Border.all(color: Colors.white.withOpacity(0.15), width: 1.5),
                  boxShadow: themeType == AppThemeType.cyberpunk || themeType == AppThemeType.arcade || themeType == AppThemeType.music ? [] : [BoxShadow(color: Colors.black.withOpacity(0.5), blurRadius: 20, offset: const Offset(4, 10))],
                ),
                child: SingleChildScrollView(
                  physics: const BouncingScrollPhysics(),
                  child: Padding(
                    padding: const EdgeInsets.all(20.0),
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        Row(children: [ SizedBox(width: 40, child: IconButton(padding: EdgeInsets.zero, alignment: Alignment.centerLeft, icon: Icon(Icons.arrow_back_ios_new, color: theme.text, size: 26), onPressed: () => Navigator.pop(ctx))), Expanded(child: Text(isVsCPU ? loc.cpuTitle : loc.localTitle, textAlign: TextAlign.center, style: getSharedTextStyle(themeType, TextStyle(fontSize: 24, fontWeight: FontWeight.w900, color: theme.text, letterSpacing: 2)))), const SizedBox(width: 40) ]),
                        const SizedBox(height: 20),

                        if (isVsCPU) ...[
                          Icon(Icons.smart_toy, size: 50, color: theme.playerBlue), const SizedBox(height: 10),
                          Text("MODALITÀ CAMPAGNA", style: getSharedTextStyle(themeType, TextStyle(fontSize: 16, fontWeight: FontWeight.w900, color: theme.text, letterSpacing: 1.5))), const SizedBox(height: 10),
                          Text("Livello CPU: ${StorageService.instance.cpuLevel}\nForma e tempo si adatteranno alla tua bravura!", textAlign: TextAlign.center, style: getSharedTextStyle(themeType, TextStyle(fontSize: 13, color: theme.text.withOpacity(0.7), height: 1.4))), const SizedBox(height: 20),
                          Divider(color: Colors.white.withOpacity(0.05), thickness: 2), const SizedBox(height: 20),
                        ] else ...[
                          Text("FORMA ARENA", style: getSharedTextStyle(themeType, TextStyle(fontSize: 12, 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: localShape == ArenaShape.classic, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localShape = ArenaShape.classic)),
                              NeonShapeButton(icon: Icons.add, label: 'Croce', isSelected: localShape == ArenaShape.cross, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localShape = ArenaShape.cross)),
                              NeonShapeButton(icon: Icons.donut_large, label: 'Buco', isSelected: localShape == ArenaShape.donut, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localShape = ArenaShape.donut)),
                              NeonShapeButton(icon: Icons.hourglass_bottom, label: 'Clessidra', isSelected: localShape == ArenaShape.hourglass, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localShape = ArenaShape.hourglass)),
                              NeonShapeButton(icon: Icons.all_inclusive, label: 'Caos', isSelected: localShape == ArenaShape.chaos, theme: theme, themeType: themeType, isSpecial: true, isLocked: !isChaosUnlocked, onTap: () => setStateDialog(() => localShape = ArenaShape.chaos)),
                            ],
                          ),
                          const SizedBox(height: 20), Divider(color: Colors.white.withOpacity(0.05), thickness: 2), const SizedBox(height: 20),

                          Text("GRANDEZZA", style: getSharedTextStyle(themeType, TextStyle(fontSize: 12, fontWeight: FontWeight.w900, color: theme.text.withOpacity(0.5), letterSpacing: 1.5))), const SizedBox(height: 10),
                          Row(
                            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                            children: [
                              NeonSizeButton(label: 'S', isSelected: localRadius == 3, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localRadius = 3)),
                              NeonSizeButton(label: 'M', isSelected: localRadius == 4, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localRadius = 4)),
                              NeonSizeButton(label: 'L', isSelected: localRadius == 5, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localRadius = 5)),
                              NeonSizeButton(label: 'MAX', isSelected: localRadius == 6, theme: theme, themeType: themeType, onTap: () => setStateDialog(() => localRadius = 6)),
                            ],
                          ),
                          const SizedBox(height: 20), Divider(color: Colors.white.withOpacity(0.05), thickness: 2), const SizedBox(height: 20),

                          Text("TEMPO", style: getSharedTextStyle(themeType, TextStyle(fontSize: 12, fontWeight: FontWeight.w900, color: theme.text.withOpacity(0.5), letterSpacing: 1.5))), const SizedBox(height: 10),
                          Row(
                            children: [
                              _buildTimeOption('10s', 'FISSO', 'fixed', localTimeMode, theme, themeType, () => setStateDialog(() => localTimeMode = 'fixed')),
                              _buildTimeOption('RELAX', 'INFINITO', 'relax', localTimeMode, theme, themeType, () => setStateDialog(() => localTimeMode = 'relax')),
                              _buildTimeOption('DINAMICO', '-2s A PARTITA', 'dynamic', localTimeMode, theme, themeType, () => setStateDialog(() => localTimeMode = 'dynamic')),
                            ],
                          ), const SizedBox(height: 30),
                        ],

                        SizedBox(
                          width: double.infinity, height: 60,
                          child: ElevatedButton(
                            style: ElevatedButton.styleFrom(backgroundColor: isVsCPU ? Colors.purple.shade400 : theme.playerRed, foregroundColor: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20))),
                            onPressed: () { Navigator.pop(ctx); context.read<GameController>().startNewGame(localRadius, vsCPU: isVsCPU, shape: localShape, timeMode: localTimeMode); Navigator.push(context, MaterialPageRoute(builder: (_) => const GameScreen())); },
                            child: Text(loc.startGame, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w900, letterSpacing: 2)),
                          ),
                        )
                      ],
                    ),
                  ),
                ),
              );

              if (themeType == AppThemeType.cyberpunk || themeType == AppThemeType.music) {
                dialogContent = AnimatedCyberBorder(child: dialogContent);
              }

              return Dialog(backgroundColor: Colors.transparent, insetPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 20), child: dialogContent);
            },
          );
        }
    );
  }

  static void showWaitingDialog({
    required BuildContext context,
    required String code,
    required bool isPublicRoom,
    required int selectedRadius,
    required ArenaShape selectedShape,
    required String selectedTimeMode,
    required MultiplayerService multiplayerService,
    required VoidCallback onRoomStarted,
    required VoidCallback onCleanup,
  }) {
    showDialog(
        context: context,
        barrierDismissible: false,
        builder: (dialogContext) {
          final theme = dialogContext.watch<ThemeManager>().currentColors;
          final themeType = dialogContext.read<ThemeManager>().currentThemeType;

          Widget dialogContent = Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              CircularProgressIndicator(color: theme.playerRed), const SizedBox(height: 25),
              Text("CODICE STANZA", style: getSharedTextStyle(themeType, TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: theme.text.withOpacity(0.6), letterSpacing: 2))),
              Text(code, style: getSharedTextStyle(themeType, TextStyle(fontSize: 40, fontWeight: FontWeight.w900, color: theme.playerRed, letterSpacing: 8, shadows: themeType == AppThemeType.doodle ? [] : [Shadow(color: theme.playerRed.withOpacity(0.5), blurRadius: 10)]))),
              const SizedBox(height: 25),
              Transform.rotate(
                angle: themeType == AppThemeType.doodle ? 0.02 : 0,
                child: Container(
                  padding: const EdgeInsets.all(18),
                  decoration: BoxDecoration(
                      color: themeType == AppThemeType.doodle ? Colors.white : theme.text.withOpacity(0.05),
                      borderRadius: BorderRadius.circular(20),
                      border: Border.all(color: themeType == AppThemeType.doodle ? theme.text : theme.playerBlue.withOpacity(0.3), width: themeType == AppThemeType.doodle ? 2 : 1.5),
                      boxShadow: themeType == AppThemeType.doodle
                          ? [BoxShadow(color: theme.text.withOpacity(0.8), offset: const Offset(4, 4))]
                          : [BoxShadow(color: theme.playerBlue.withOpacity(0.1), blurRadius: 10)]
                  ),
                  child: Column(
                    children: [
                      Icon(isPublicRoom ? Icons.podcasts : Icons.share, color: theme.playerBlue, size: 32), const SizedBox(height: 12),
                      Text(isPublicRoom ? "Sei in Bacheca!" : "Invito inviato", textAlign: TextAlign.center, style: getSharedTextStyle(themeType, TextStyle(color: theme.text, fontWeight: FontWeight.w900, fontSize: 18))),
                      const SizedBox(height: 8),
                      Text(isPublicRoom ? "Aspettiamo che uno sfidante si unisca dalla lobby pubblica." : "Attendi che il tuo amico accetti la sfida. Non chiudere questa finestra.", textAlign: TextAlign.center, style: getSharedTextStyle(themeType, TextStyle(color: themeType == AppThemeType.doodle ? theme.text : theme.text.withOpacity(0.8), fontSize: 14, height: 1.5))),
                    ],
                  ),
                ),
              ),
            ],
          );

          if (themeType == AppThemeType.cyberpunk || themeType == AppThemeType.music) {
            dialogContent = AnimatedCyberBorder(child: dialogContent);
          } else {
            dialogContent = Container(
                padding: const EdgeInsets.all(20),
                decoration: BoxDecoration(
                    color: themeType == AppThemeType.doodle ? Colors.white.withOpacity(0.95) : theme.background,
                    borderRadius: BorderRadius.circular(25),
                    border: Border.all(color: themeType == AppThemeType.doodle ? theme.text : theme.gridLine.withOpacity(0.5), width: 2),
                    boxShadow: themeType == AppThemeType.doodle ? [BoxShadow(color: theme.text.withOpacity(0.6), offset: const Offset(8, 8))] : []
                ),
                child: dialogContent
            );
          }

          return StreamBuilder<DocumentSnapshot>(
            stream: multiplayerService.listenToRoom(code),
            builder: (ctx, snapshot) {
              if (snapshot.hasData && snapshot.data!.exists) {
                var data = snapshot.data!.data() as Map<String, dynamic>;
                if (data['status'] == 'playing') {
                  onRoomStarted();
                  WidgetsBinding.instance.addPostFrameCallback((_) {
                    Navigator.pop(ctx);
                    context.read<GameController>().startNewGame(selectedRadius, isOnline: true, roomCode: code, isHost: true, shape: selectedShape, timeMode: selectedTimeMode);
                    Navigator.push(context, MaterialPageRoute(builder: (_) => const GameScreen()));
                  });
                }
              }

              return PopScope(
                canPop: false,
                onPopInvoked: (didPop) {
                  if (didPop) return;
                  onCleanup();
                  Navigator.pop(ctx);
                },
                child: Dialog(
                  backgroundColor: Colors.transparent,
                  insetPadding: const EdgeInsets.all(20),
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      dialogContent,
                      const SizedBox(height: 20),
                      TextButton(
                        onPressed: () {
                          onCleanup();
                          Navigator.pop(ctx);
                        },
                        child: Text("ANNULLA", style: getSharedTextStyle(themeType, TextStyle(color: Colors.red, fontWeight: FontWeight.w900, fontSize: 20, letterSpacing: 2.0, shadows: themeType == AppThemeType.doodle ? [] : [const Shadow(color: Colors.black, blurRadius: 2)]))),
                      ),
                    ],
                  ),
                ),
              );
            },
          );
        }
    );
  }

  static void showJoinPromptDialog(BuildContext context, String roomCode, Function(String) onConfirm) {
    showDialog(
        context: context,
        builder: (context) {
          final themeManager = context.watch<ThemeManager>();
          final theme = themeManager.currentColors;
          final themeType = themeManager.currentThemeType;
          return AlertDialog(
            backgroundColor: themeType == AppThemeType.doodle ? Colors.white : theme.background,
            shape: themeType == AppThemeType.doodle ? RoundedRectangleBorder(borderRadius: BorderRadius.circular(15), side: BorderSide(color: theme.text, width: 2)) : null,
            title: Text("Invito Trovato!", style: getSharedTextStyle(themeType, TextStyle(color: theme.text, fontWeight: FontWeight.bold))),
            content: Text("Vuoi unirti alla stanza $roomCode?", style: getSharedTextStyle(themeType, TextStyle(color: theme.text))),
            actions: [
              TextButton(onPressed: () => Navigator.pop(context), child: Text("No", style: getSharedTextStyle(themeType, const TextStyle(color: Colors.red)))),
              ElevatedButton(
                style: ElevatedButton.styleFrom(backgroundColor: themeType == AppThemeType.doodle ? Colors.transparent : theme.playerBlue, elevation: 0, side: themeType == AppThemeType.doodle ? BorderSide(color: theme.text, width: 1.5) : BorderSide.none),
                onPressed: () {
                  Navigator.of(context).pop();
                  onConfirm(roomCode);
                },
                child: Text(AppLocalizations.of(context)!.joinMatch, style: getSharedTextStyle(themeType, TextStyle(color: themeType == AppThemeType.doodle ? theme.text : Colors.white, fontWeight: FontWeight.bold))),
              ),
            ],
          );
        }
    );
  }

  static void showFavoritesDialog(BuildContext context, Function(String, String) onInvite) {
    final favs = StorageService.instance.favorites;

    showDialog(
        context: context,
        builder: (ctx) {
          final themeManager = ctx.watch<ThemeManager>();
          final theme = themeManager.currentColors;
          final themeType = themeManager.currentThemeType;

          return AlertDialog(
            backgroundColor: theme.background,
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(20),
            ),
            title: Text("I TUOI PREFERITI", style: getLobbyTextStyle(themeType, TextStyle(color: theme.text, fontWeight: FontWeight.bold))),
            content: Container(
              width: double.maxFinite,
              height: 300,
              decoration: BoxDecoration(
                  border: Border.all(color: theme.playerRed, width: 2),
                  borderRadius: BorderRadius.circular(10)
              ),
              child: favs.isEmpty
                  ? Center(child: Padding(
                padding: const EdgeInsets.all(20.0),
                child: Text("Non hai ancora aggiunto nessun preferito dalla Classifica!", textAlign: TextAlign.center, style: getLobbyTextStyle(themeType, TextStyle(color: theme.text.withOpacity(0.6)))),
              ))
                  : ListView.builder(
                itemCount: favs.length,
                itemBuilder: (c, i) {
                  return ListTile(
                    title: Text(favs[i]['name']!, style: getLobbyTextStyle(themeType, TextStyle(color: theme.text, fontSize: 18, fontWeight: FontWeight.bold))),
                    trailing: ElevatedButton(
                      style: ElevatedButton.styleFrom(backgroundColor: theme.playerBlue, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))),
                      onPressed: () {
                        Navigator.pop(ctx);
                        onInvite(favs[i]['uid']!, favs[i]['name']!);
                      },
                      child: Text("SFIDA", style: getLobbyTextStyle(themeType, const TextStyle(color: Colors.white, fontWeight: FontWeight.bold))),
                    ),
                  );
                },
              ),
            ),
            actions: [
              TextButton(
                onPressed: () => Navigator.pop(ctx),
                child: Text("CHIUDI", style: getLobbyTextStyle(themeType, TextStyle(color: theme.playerRed, fontWeight: FontWeight.bold))),
              ),
            ],
          );
        }
    );
  }
}
// ===========================================================================
// FILE: lib/ui/home/home_screen.dart
// ===========================================================================

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

import 'dart:ui';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter/services.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'dart:async';
import 'package:app_links/app_links.dart';

import '../../logic/game_controller.dart';
import '../../core/theme_manager.dart';
import '../../core/app_colors.dart';
import '../../services/storage_service.dart';
import '../../services/audio_service.dart';
import '../../services/multiplayer_service.dart';
import '../multiplayer/lobby_screen.dart';
import '../admin/admin_screen.dart';
import '../settings/settings_screen.dart';
import '../game/game_screen.dart';
import 'package:tetraq/l10n/app_localizations.dart';

import '../../widgets/painters.dart';
import '../../widgets/cyber_border.dart';
import '../../widgets/music_theme_widgets.dart';
import '../../widgets/home_buttons.dart';
import 'dialog.dart';
import 'home_modals.dart';

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

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

class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {

  int _debugTapCount = 0;
  late AppLinks _appLinks;
  StreamSubscription<Uri>? _linkSubscription;
  StreamSubscription<QuerySnapshot>? _favoritesSubscription;
  StreamSubscription<QuerySnapshot>? _invitesSubscription;

  Map<String, DateTime> _lastOnlineNotifications = {};

  final int _selectedRadius = 4;
  final ArenaShape _selectedShape = ArenaShape.classic;
  final bool _isPublicRoom = true;

  bool _isLoading = false;
  String? _myRoomCode;
  bool _roomStarted = false;

  final MultiplayerService _multiplayerService = MultiplayerService();

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    WidgetsBinding.instance.addPostFrameCallback((_) {
      // MODIFICA QUI: Invece di currentUser == null, controlliamo se il nome è vuoto!
      if (StorageService.instance.playerName.isEmpty) {
        HomeModals.showNameDialog(context, () {
          StorageService.instance.syncLeaderboard();
          _listenToInvites();
          setState(() {});
        });
      } else {
        StorageService.instance.syncLeaderboard();
        _listenToInvites();
      }
      _checkThemeSafety();
    });
    _checkClipboardForInvite();
    _initDeepLinks();
    _listenToFavoritesOnline();
  }
  void _checkThemeSafety() {
    String themeStr = StorageService.instance.getTheme();
    bool exists = AppThemeType.values.any((e) => e.toString() == themeStr);
    if (!exists) {
      context.read<ThemeManager>().setTheme(AppThemeType.doodle);
    }
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    _cleanupGhostRoom();
    _linkSubscription?.cancel();
    _favoritesSubscription?.cancel();
    _invitesSubscription?.cancel();
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      _checkClipboardForInvite();
      _listenToFavoritesOnline();
    } else if (state == AppLifecycleState.paused || state == AppLifecycleState.detached) {
      _cleanupGhostRoom();
    }
  }

  void _cleanupGhostRoom() {
    if (_myRoomCode != null && !_roomStarted) {
      FirebaseFirestore.instance.collection('games').doc(_myRoomCode).delete();
      _myRoomCode = null;
    }
  }

  Future<void> _initDeepLinks() async {
    _appLinks = AppLinks();
    try {
      final initialUri = await _appLinks.getInitialLink();
      if (initialUri != null) _handleDeepLink(initialUri);
    } catch (e) { debugPrint("Errore lettura link iniziale: $e"); }
    _linkSubscription = _appLinks.uriLinkStream.listen((uri) { _handleDeepLink(uri); }, onError: (err) { debugPrint("Errore stream link: $err"); });
  }

  void _handleDeepLink(Uri uri) {
    if (uri.scheme == 'tetraq' && uri.host == 'join') {
      String? code = uri.queryParameters['code'];
      if (code != null && code.length == 5) {
        Future.delayed(const Duration(milliseconds: 500), () {
          if (mounted) HomeModals.showJoinPromptDialog(context, code.toUpperCase(), _joinRoomByCode);
        });
      }
    }
  }

  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) {
            HomeModals.showJoinPromptDialog(context, roomCode, _joinRoomByCode);
          }
        }
      }
    } catch (e) { debugPrint("Errore lettura appunti: $e"); }
  }

  void _listenToFavoritesOnline() {
    _favoritesSubscription?.cancel();
    final favs = StorageService.instance.favorites;
    if (favs.isEmpty) return;

    List<String> favUids = favs.map((f) => f['uid']!).toList();
    if (favUids.length > 10) favUids = favUids.sublist(0, 10);

    _favoritesSubscription = FirebaseFirestore.instance
        .collection('leaderboard')
        .where(FieldPath.documentId, whereIn: favUids)
        .snapshots()
        .listen((snapshot) {
      if (!mounted) return;

      for (var change in snapshot.docChanges) {
        if (change.type == DocumentChangeType.modified || change.type == DocumentChangeType.added) {
          var data = change.doc.data();
          if (data != null && data['lastActive'] != null) {
            Timestamp lastActive = data['lastActive'];
            int diffInSeconds = DateTime.now().difference(lastActive.toDate()).inSeconds;

            if (diffInSeconds.abs() < 180) {
              String name = data['name'] ?? 'Un amico';
              _showFavoriteOnlinePopup(name);
            }
          }
        }
      }
    });
  }

  void _showFavoriteOnlinePopup(String name) {
    if (!mounted) return;

    if (_lastOnlineNotifications.containsKey(name)) {
      if (DateTime.now().difference(_lastOnlineNotifications[name]!).inMinutes < 1) return;
    }
    _lastOnlineNotifications[name] = DateTime.now();

    final overlay = Overlay.of(context);
    late OverlayEntry entry;
    bool removed = false;

    // --- FIX OVERLAP POPUP: Più in basso (85) ---
    entry = OverlayEntry(
      builder: (context) => Positioned(
        top: MediaQuery.of(context).padding.top + 85,
        left: 20,
        right: 20,
        child: FavoriteOnlinePopup(
          name: name,
          onDismiss: () {
            if (!removed) {
              removed = true;
              entry.remove();
            }
          },
        ),
      ),
    );
    overlay.insert(entry);
  }

  void _listenToInvites() {
    final user = FirebaseAuth.instance.currentUser;
    if (user == null) return;

    _invitesSubscription?.cancel();
    _invitesSubscription = FirebaseFirestore.instance
        .collection('invites')
        .where('toUid', isEqualTo: user.uid)
        .snapshots()
        .listen((snapshot) {
      if (!mounted) return;

      for (var change in snapshot.docChanges) {
        if (change.type == DocumentChangeType.added) {
          var data = change.doc.data();
          if (data != null) {
            String code = data['roomCode'];
            String from = data['fromName'];
            String inviteId = change.doc.id;

            Timestamp? ts = data['timestamp'];
            if (ts != null) {
              if (DateTime.now().difference(ts.toDate()).inMinutes > 2) {
                FirebaseFirestore.instance.collection('invites').doc(inviteId).delete();
                continue;
              }
            }
            _showInvitePopup(from, code, inviteId);
          }
        }
      }
    });
  }

  void _showInvitePopup(String fromName, String roomCode, String inviteId) {
    final themeType = context.read<ThemeManager>().currentThemeType;
    final theme = context.read<ThemeManager>().currentColors;

    showDialog(
        context: context,
        barrierDismissible: false,
        builder: (ctx) => AlertDialog(
          backgroundColor: themeType == AppThemeType.doodle ? Colors.white : theme.background,
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20), side: BorderSide(color: theme.playerRed, width: 2)),
          title: Row(
            children: [
              Icon(Icons.warning_amber_rounded, color: theme.playerRed),
              const SizedBox(width: 10),
              Text("SFIDA IN ARRIVO!", style: getSharedTextStyle(themeType, TextStyle(color: theme.playerRed, fontWeight: FontWeight.bold, fontSize: 18))),
            ],
          ),
          content: Text("$fromName ti ha sfidato a duello!\nAccetti la sfida?", style: getSharedTextStyle(themeType, TextStyle(color: theme.text, fontSize: 16))),
          actions: [
            TextButton(
              onPressed: () {
                FirebaseFirestore.instance.collection('invites').doc(inviteId).delete();
                Navigator.pop(ctx);
              },
              child: Text("RIFIUTA", style: getSharedTextStyle(themeType, const TextStyle(color: Colors.grey, fontWeight: FontWeight.bold))),
            ),
            ElevatedButton(
              style: ElevatedButton.styleFrom(backgroundColor: theme.playerBlue, foregroundColor: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))),
              onPressed: () {
                FirebaseFirestore.instance.collection('invites').doc(inviteId).delete();
                Navigator.pop(ctx);
                _joinRoomByCode(roomCode);
              },
              child: Text("ACCETTA!", style: getSharedTextStyle(themeType, const TextStyle(fontWeight: FontWeight.bold))),
            ),
          ],
        )
    );
  }

  void _startDirectChallengeFlow(String targetUid, String targetName) {
    HomeModals.showChallengeSetupDialog(
        context,
        targetName,
            (int radius, ArenaShape shape, String timeMode) {
          _executeSendChallenge(targetUid, targetName, radius, shape, timeMode);
        }
    );
  }

  Future<void> _executeSendChallenge(String targetUid, String targetName, int radius, ArenaShape shape, String timeMode) async {
    setState(() => _isLoading = true);

    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    final rnd = Random();
    String roomCode = String.fromCharCodes(Iterable.generate(5, (_) => chars.codeUnitAt(rnd.nextInt(chars.length))));

    try {
      int gameSeed = rnd.nextInt(9999999);

      await FirebaseFirestore.instance.collection('games').doc(roomCode).set({
        'status': 'waiting',
        'hostName': StorageService.instance.playerName,
        'hostUid': FirebaseAuth.instance.currentUser?.uid,
        'radius': radius,
        'shape': shape.name,
        'timeMode': timeMode,
        'isPublic': false,
        'createdAt': FieldValue.serverTimestamp(),
        'players': [FirebaseAuth.instance.currentUser?.uid],
        'turn': 0,
        'moves': [],
        'seed': gameSeed,
      });

      await FirebaseFirestore.instance.collection('invites').add({
        'toUid': targetUid,
        'fromName': StorageService.instance.playerName,
        'roomCode': roomCode,
        'timestamp': FieldValue.serverTimestamp(),
      });

      setState(() => _isLoading = false);

      if (mounted) {
        HomeModals.showWaitingDialog(
            context: context,
            code: roomCode,
            isPublicRoom: false,
            selectedRadius: radius,
            selectedShape: shape,
            selectedTimeMode: timeMode,
            multiplayerService: _multiplayerService,
            onRoomStarted: () {},
            onCleanup: () {
              FirebaseFirestore.instance.collection('games').doc(roomCode).delete();
            }
        );
      }
    } catch (e) {
      setState(() => _isLoading = false);
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Errore: $e", style: const TextStyle(color: Colors.white)), backgroundColor: Colors.red));
      }
    }
  }

  Future<void> _joinRoomByCode(String code) async {
    if (_isLoading) return;
    FocusScope.of(context).unfocus();
    setState(() => _isLoading = true);

    try {
      String playerName = StorageService.instance.playerName;
      if (playerName.isEmpty) playerName = "GUEST";

      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("La sfida inizierà a breve..."), backgroundColor: Colors.green));

        int hostRadius = roomData['radius'] ?? 4;
        String shapeStr = roomData['shape'] ?? 'classic';
        ArenaShape hostShape = ArenaShape.values.firstWhere((e) => e.name == shapeStr, orElse: () => ArenaShape.classic);

        String hostTimeMode = roomData['timeMode'] is String ? roomData['timeMode'] : (roomData['timeMode'] == true ? 'fixed' : 'relax');

        context.read<GameController>().startNewGame(hostRadius, isOnline: true, roomCode: code, isHost: false, shape: hostShape, timeMode: hostTimeMode);
        Navigator.push(context, MaterialPageRoute(builder: (_) => const GameScreen()));
      } else {
        ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Stanza non trovata, piena o partita già iniziata.", style: TextStyle(color: Colors.white)), backgroundColor: Colors.red));
      }
    } catch (e) {
      if (mounted) {
        setState(() => _isLoading = false);
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Errore di connessione: $e", style: const TextStyle(color: Colors.white)), backgroundColor: Colors.red));
      }
    }
  }

  BoxDecoration _glassBoxDecoration(ThemeColors theme, AppThemeType themeType) {
    return BoxDecoration(
      color: themeType == AppThemeType.doodle ? Colors.white : null,
      gradient: themeType == AppThemeType.doodle ? null : LinearGradient(
        begin: Alignment.topLeft,
        end: Alignment.bottomRight,
        colors: [
          Colors.white.withOpacity(0.25),
          Colors.white.withOpacity(0.05),
        ],
      ),
      borderRadius: BorderRadius.circular(25),
      border: Border.all(
        color: themeType == AppThemeType.doodle ? theme.text : Colors.white.withOpacity(0.3),
        width: themeType == AppThemeType.doodle ? 2 : 1.5,
      ),
      boxShadow: themeType == AppThemeType.doodle
          ? [BoxShadow(color: theme.text.withOpacity(0.8), offset: const Offset(4, 4), blurRadius: 0)]
          : [BoxShadow(color: Colors.black.withOpacity(0.2), blurRadius: 10)],
    );
  }

  Widget _buildTopBar(BuildContext context, ThemeColors theme, AppThemeType themeType, String playerName, int playerLevel) {
    Color inkColor = const Color(0xFF111122);

    return Padding(
      padding: const EdgeInsets.only(top: 5.0, left: 15.0, right: 15.0, bottom: 10.0),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          GestureDetector(
            onTap: () => HomeModals.showNameDialog(context, () => setState(() {})),
            child: Container(
              padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
              decoration: _glassBoxDecoration(theme, themeType),
              child: Row(
                mainAxisSize: MainAxisSize.min,
                children: [
                  CircleAvatar(
                    radius: 18,
                    backgroundColor: theme.playerBlue.withOpacity(0.2),
                    child: Icon(Icons.person, color: theme.playerBlue, size: 20),
                  ),
                  const SizedBox(width: 10),
                  Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Text(
                        playerName.toUpperCase(),
                        style: getSharedTextStyle(themeType, TextStyle(color: themeType == AppThemeType.doodle ? inkColor : theme.text, fontWeight: FontWeight.bold, fontSize: 16)),
                        overflow: TextOverflow.visible,
                        softWrap: false,
                      ),
                      Text(
                        "LIV. $playerLevel",
                        style: getSharedTextStyle(themeType, TextStyle(color: themeType == AppThemeType.doodle ? inkColor.withOpacity(0.8) : theme.playerBlue, fontWeight: FontWeight.bold, fontSize: 11)),
                        overflow: TextOverflow.visible,
                        softWrap: false,
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ),

          // --- BOX STATISTICHE ---
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
            decoration: _glassBoxDecoration(theme, themeType),
            child: Row(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                Icon(themeType == AppThemeType.music ? FontAwesomeIcons.microphone : Icons.emoji_events, color: Colors.amber.shade600, size: 16),
                const SizedBox(width: 6),

                Text(
                  "${StorageService.instance.wins}",
                  style: getSharedTextStyle(themeType, TextStyle(
                    color: themeType == AppThemeType.doodle ? inkColor : theme.text,
                    fontWeight: FontWeight.w900,
                    fontSize: 16,
                  )),
                  overflow: TextOverflow.visible,
                  softWrap: false,
                ),

                const SizedBox(width: 10),
                Icon(themeType == AppThemeType.music ? FontAwesomeIcons.compactDisc : Icons.sentiment_very_dissatisfied, color: theme.playerRed.withOpacity(0.8), size: 16),
                const SizedBox(width: 6),

                Text(
                  "${StorageService.instance.losses}",
                  style: getSharedTextStyle(themeType, TextStyle(
                    color: themeType == AppThemeType.doodle ? inkColor : theme.text,
                    fontWeight: FontWeight.w900,
                    fontSize: 16,
                  )),
                  overflow: TextOverflow.visible,
                  softWrap: false,
                ),

                const SizedBox(width: 10),
                Container(width: 1, height: 20, color: (themeType == AppThemeType.doodle ? inkColor : Colors.white).withOpacity(0.2)),
                const SizedBox(width: 10),

                AnimatedBuilder(
                    animation: AudioService.instance,
                    builder: (context, child) {
                      bool isMuted = AudioService.instance.isMuted;
                      return GestureDetector(
                        behavior: HitTestBehavior.opaque,
                        onTap: () {
                          AudioService.instance.toggleMute();
                        },
                        child: Icon(
                          isMuted ? Icons.volume_off : Icons.volume_up,
                          color: isMuted ? theme.playerRed : (themeType == AppThemeType.doodle ? inkColor : theme.text),
                          size: 20,
                        ),
                      );
                    }
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildCyberCard(Widget card, AppThemeType themeType) {
    if (themeType == AppThemeType.cyberpunk) return AnimatedCyberBorder(child: card);
    return card;
  }

  @override
  Widget build(BuildContext context) {
    SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
    SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);

    final themeManager = context.watch<ThemeManager>();
    final themeType = themeManager.currentThemeType;
    final theme = themeManager.currentColors;
    Color inkColor = const Color(0xFF111122);
    final loc = AppLocalizations.of(context)!;

    String? bgImage;
    if (themeType == AppThemeType.doodle) bgImage = 'assets/images/doodle_bg.jpg';
    if (themeType == AppThemeType.cyberpunk) bgImage = 'assets/images/cyber_bg.jpg';
    if (themeType == AppThemeType.music) bgImage = 'assets/images/music_bg.jpg';
    if (themeType == AppThemeType.arcade) bgImage = 'assets/images/arcade.jpg';
    if (themeType == AppThemeType.grimorio) bgImage = 'assets/images/grimorio.jpg';

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

    final double screenHeight = MediaQuery.of(context).size.height;
    final double vScale = (screenHeight / 920.0).clamp(0.50, 1.0);

    Widget uiContent = SafeArea(
      child: Column(
        children: [
          _buildTopBar(context, theme, themeType, playerName, playerLevel),

          Expanded(
            child: SingleChildScrollView(
              physics: const BouncingScrollPhysics(),
              child: Padding(
                padding: const EdgeInsets.symmetric(horizontal: 20.0),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    SizedBox(height: 20 * vScale),
                    Center(
                      child: Transform.rotate(
                        angle: themeType == AppThemeType.doodle ? -0.04 : 0,
                        child: GestureDetector(
                          onTap: () {
                            if (playerName.toUpperCase() == 'PAOLO') {
                              _debugTapCount++;
                              if (_debugTapCount == 5) {
                                StorageService.instance.addXP(2000);
                                setState(() {});
                                ScaffoldMessenger.of(context).showSnackBar(
                                    SnackBar(content: Text("🛠 DEBUG MODE: +20 Livelli!", style: getSharedTextStyle(themeType, const TextStyle(color: Colors.white, fontWeight: FontWeight.bold))), backgroundColor: Colors.purpleAccent, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)))
                                );
                              } else if (_debugTapCount >= 7) {
                                _debugTapCount = 0;
                                Navigator.push(context, MaterialPageRoute(builder: (_) => AdminScreen()));
                              }
                            }
                          },
                          child: FittedBox(
                            fit: BoxFit.scaleDown,
                            child: Text(
                              loc.appTitle.toUpperCase(),
                              style: getSharedTextStyle(themeType, TextStyle(
                                  fontSize: 65 * vScale,
                                  fontWeight: FontWeight.w900,
                                  color: themeType == AppThemeType.doodle ? inkColor : theme.text,
                                  letterSpacing: 10 * vScale,
                                  shadows: themeType == AppThemeType.doodle
                                      ? [const Shadow(color: Colors.white, offset: Offset(2.5, 2.5), blurRadius: 2), const Shadow(color: Colors.white, offset: Offset(-2.5, -2.5), blurRadius: 2)]
                                      : [Shadow(color: Colors.black.withOpacity(0.8), offset: const Offset(3, 4), blurRadius: 8), Shadow(color: theme.playerBlue.withOpacity(0.4), offset: const Offset(0, 0), blurRadius: 20)]
                              )),
                              overflow: TextOverflow.visible,
                              softWrap: false,
                            ),
                          ),
                        ),
                      ),
                    ),
                    SizedBox(height: 40 * vScale),

                    if (themeType == AppThemeType.music) ...[
                      MusicCassetteCard(title: loc.onlineTitle, subtitle: loc.onlineSub, neonColor: Colors.blueAccent, angle: -0.04, leftIcon: FontAwesomeIcons.sliders, rightIcon: FontAwesomeIcons.globe, themeType: themeType, onTap: () { Navigator.push(context, MaterialPageRoute(builder: (_) => LobbyScreen())); }),
                      SizedBox(height: 12 * vScale),
                      MusicCassetteCard(title: loc.cpuTitle, subtitle: loc.cpuSub, neonColor: Colors.purpleAccent, angle: 0.03, leftIcon: FontAwesomeIcons.desktop, rightIcon: FontAwesomeIcons.music, themeType: themeType, onTap: () => HomeModals.showMatchSetupDialog(context, true)),
                      SizedBox(height: 12 * vScale),
                      MusicCassetteCard(title: loc.localTitle, subtitle: loc.localSub, neonColor: Colors.deepPurpleAccent, angle: -0.02, leftIcon: FontAwesomeIcons.headphones, rightIcon: FontAwesomeIcons.headphones, themeType: themeType, onTap: () => HomeModals.showMatchSetupDialog(context, false)),
                      SizedBox(height: 30 * vScale),
                      Row(
                        mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Expanded(child: MusicKnobCard(title: loc.leaderboardTitle, icon: FontAwesomeIcons.compactDisc, iconColor: Colors.amber, themeType: themeType, onTap: () => showDialog(context: context, builder: (ctx) => LeaderboardDialog(onChallenge: _startDirectChallengeFlow)))),
                          Expanded(child: MusicKnobCard(title: loc.questsTitle, icon: FontAwesomeIcons.microphoneLines, themeType: themeType, onTap: () => showDialog(context: context, builder: (ctx) => const QuestsDialog()))),
                          Expanded(child: MusicKnobCard(title: loc.themesTitle, icon: FontAwesomeIcons.palette, themeType: themeType, onTap: () => Navigator.push(context, MaterialPageRoute(builder: (_) => SettingsScreen())))),
                          Expanded(child: MusicKnobCard(title: loc.tutorialTitle, icon: FontAwesomeIcons.bookOpen, themeType: themeType, onTap: () => showDialog(context: context, builder: (ctx) => const TutorialDialog()))),
                        ],
                      ),
                    ] else ...[
                      Column(
                        crossAxisAlignment: CrossAxisAlignment.stretch,
                        children: [
                          _buildCyberCard(FeatureCard(title: loc.onlineTitle, subtitle: loc.onlineSub, icon: Icons.public, color: Colors.lightBlue.shade200, theme: theme, themeType: themeType, isFeatured: true, onTap: () { Navigator.push(context, MaterialPageRoute(builder: (_) => LobbyScreen())); }), themeType),
                          SizedBox(height: 12 * vScale),
                          _buildCyberCard(FeatureCard(title: loc.cpuTitle, subtitle: loc.cpuSub, icon: Icons.smart_toy, color: Colors.purple.shade200, theme: theme, themeType: themeType, onTap: () => HomeModals.showMatchSetupDialog(context, true)), themeType),
                          SizedBox(height: 12 * vScale),
                          _buildCyberCard(FeatureCard(title: loc.localTitle, subtitle: loc.localSub, icon: Icons.people_alt, color: Colors.red.shade200, theme: theme, themeType: themeType, onTap: () => HomeModals.showMatchSetupDialog(context, false)), themeType),
                          SizedBox(height: 12 * vScale),

                          Row(
                            children: [
                              Expanded(child: _buildCyberCard(FeatureCard(title: loc.leaderboardTitle, subtitle: "Top 50 Globale", icon: Icons.leaderboard, color: Colors.amber.shade200, theme: theme, themeType: themeType, onTap: () => showDialog(context: context, builder: (ctx) => LeaderboardDialog(onChallenge: _startDirectChallengeFlow)), compact: true), themeType)),
                              const SizedBox(width: 12),
                              Expanded(child: _buildCyberCard(FeatureCard(title: loc.questsTitle, subtitle: "Missioni", icon: Icons.assignment_turned_in, color: Colors.green.shade200, theme: theme, themeType: themeType, onTap: () => showDialog(context: context, builder: (ctx) => const QuestsDialog()), compact: true), themeType)),
                            ],
                          ),

                          SizedBox(height: 12 * vScale),

                          Row(
                            children: [
                              Expanded(child: _buildCyberCard(FeatureCard(title: loc.themesTitle, subtitle: "Personalizza", icon: Icons.palette, color: Colors.teal.shade200, theme: theme, themeType: themeType, onTap: () => Navigator.push(context, MaterialPageRoute(builder: (_) => SettingsScreen())), compact: true), themeType)),
                              const SizedBox(width: 12),
                              Expanded(child: _buildCyberCard(FeatureCard(title: loc.tutorialTitle, subtitle: "Come giocare", icon: Icons.school, color: Colors.indigo.shade200, theme: theme, themeType: themeType, onTap: () => showDialog(context: context, builder: (ctx) => const TutorialDialog()), compact: true), themeType)),
                            ],
                          ),
                        ],
                      ),
                    ],
                    SizedBox(height: 40 * vScale),
                  ],
                ),
              ),
            ),
          ),
        ],
      ),
    );

    return Scaffold(
      backgroundColor: bgImage != null ? Colors.transparent : theme.background,
      extendBodyBehindAppBar: true,
      body: Stack(
        children: [
          Container(color: themeType == AppThemeType.doodle ? Colors.white : theme.background),

          if (themeType == AppThemeType.doodle)
            Positioned.fill(
              child: CustomPaint(
                painter: FullScreenGridPainter(Colors.blue.withOpacity(0.15)),
              ),
            ),

          if (bgImage != null)
            Positioned.fill(
              child: Container(
                decoration: BoxDecoration(
                  image: DecorationImage(
                    image: AssetImage(bgImage!),
                    fit: BoxFit.cover,
                    colorFilter: themeType == AppThemeType.doodle
                        ? ColorFilter.mode(Colors.white.withOpacity(0.5), BlendMode.lighten)
                        : null,
                  ),
                ),
              ),
            ),

          if (bgImage != null && (themeType == AppThemeType.cyberpunk || themeType == AppThemeType.music || themeType == AppThemeType.arcade || themeType == AppThemeType.grimorio))
            Positioned.fill(
              child: Container(
                decoration: BoxDecoration(
                    gradient: LinearGradient(
                        begin: Alignment.topCenter, end: Alignment.bottomCenter,
                        colors: [Colors.black.withOpacity(0.4), Colors.black.withOpacity(0.8)]
                    )
                ),
              ),
            ),

          if (themeType == AppThemeType.music)
            Positioned.fill(
              child: IgnorePointer(
                child: CustomPaint(
                  painter: AudioCablesPainter(),
                ),
              ),
            ),

          Positioned.fill(child: uiContent),
        ],
      ),
    );
  }
}

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;
}

class FavoriteOnlinePopup extends StatefulWidget {
  final String name;
  final VoidCallback onDismiss;

  const FavoriteOnlinePopup({super.key, required this.name, required this.onDismiss});

  @override
  State<FavoriteOnlinePopup> createState() => _FavoriteOnlinePopupState();
}

class _FavoriteOnlinePopupState extends State<FavoriteOnlinePopup> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<Offset> _offsetAnimation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this, duration: const Duration(milliseconds: 400));
    _offsetAnimation = Tween<Offset>(begin: const Offset(0.0, -1.5), end: Offset.zero)
        .animate(CurvedAnimation(parent: _controller, curve: Curves.easeOutBack));

    _controller.forward();

    Future.delayed(const Duration(seconds: 3), () {
      if (mounted) {
        _controller.reverse().then((_) => widget.onDismiss());
      }
    });
  }

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

  @override
  Widget build(BuildContext context) {
    final themeManager = context.watch<ThemeManager>();
    final themeType = themeManager.currentThemeType;
    final theme = themeManager.currentColors;
    Color inkColor = const Color(0xFF111122);

    return SlideTransition(
      position: _offsetAnimation,
      child: Material(
        color: Colors.transparent,
        // --- FIX OVERLAP POPUP: Aggiunta Elevation Altissima (100) ---
        elevation: 100,
        child: Container(
          padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
          decoration: BoxDecoration(
            color: themeType == AppThemeType.doodle ? Colors.white : theme.background,
            borderRadius: BorderRadius.circular(20),
            border: Border.all(
                color: themeType == AppThemeType.doodle ? inkColor : theme.playerBlue,
                width: 2
            ),
            boxShadow: [
              BoxShadow(
                  color: Colors.black.withOpacity(0.3),
                  blurRadius: 10,
                  offset: const Offset(0, 5)
              )
            ],
          ),
          child: Row(
            mainAxisSize: MainAxisSize.min,
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Icon(Icons.circle, color: Colors.greenAccent, size: 14),
              const SizedBox(width: 10),
              Text(
                "${widget.name} è online!",
                style: getSharedTextStyle(
                    themeType,
                    TextStyle(
                        color: themeType == AppThemeType.doodle ? inkColor : theme.text,
                        fontWeight: FontWeight.bold,
                        fontSize: 15
                    )
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
// ===========================================================================
// FILE: lib/ui/multiplayer/lobby_screen.dart
// ===========================================================================

// ===========================================================================
// FILE: lib/ui/multiplayer/lobby_screen.dart
// ===========================================================================

import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';

import '../../logic/game_controller.dart';
import '../../models/game_board.dart';
import '../../core/theme_manager.dart';
import '../../core/app_colors.dart';
import '../../services/multiplayer_service.dart';
import '../../services/storage_service.dart';
import '../game/game_screen.dart';
import '../../widgets/painters.dart';
import '../../widgets/cyber_border.dart';
import 'lobby_widgets.dart';

class LobbyScreen extends StatefulWidget {
  final String? initialRoomCode;

  const LobbyScreen({super.key, this.initialRoomCode});

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

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

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

  bool _isCreatingRoom = false;

  int _selectedRadius = 4;
  ArenaShape _selectedShape = ArenaShape.classic;

  String _timeModeSetting = 'fixed';

  bool _isPublicRoom = true;

  bool _roomStarted = false;

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

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

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

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.paused || state == AppLifecycleState.detached) {
      _cleanupGhostRoom();
    }
  }

  void _cleanupGhostRoom() {
    if (_myRoomCode != null && !_roomStarted) {
      FirebaseFirestore.instance.collection('games').doc(_myRoomCode).delete();
      _myRoomCode = null;
    }
  }

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

    try {
      String code = await _multiplayerService.createGameRoom(
          _selectedRadius, _playerName, _selectedShape.name, _timeModeSetting, isPublic: _isPublicRoom
      );

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

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

  Future<void> _createRoomAndInvite(String targetUid, String targetName) async {
    if (_isLoading) return;
    setState(() => _isLoading = true);

    try {
      String code = await _multiplayerService.createGameRoom(
          _selectedRadius, _playerName, _selectedShape.name, _timeModeSetting, isPublic: _isPublicRoom
      );

      await _multiplayerService.sendInvite(targetUid, code, _playerName);

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

      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Sfida inviata a $targetName!"), backgroundColor: Colors.green));
      _showWaitingDialog(code);

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

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

    code = code.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'] ?? 4;
        String shapeStr = roomData['shape'] ?? 'classic';
        ArenaShape hostShape = ArenaShape.values.firstWhere((e) => e.name == shapeStr, orElse: () => ArenaShape.classic);

        String hostTimeMode = roomData['timeMode'] is String ? roomData['timeMode'] : (roomData['timeMode'] == true ? 'fixed' : 'relax');

        context.read<GameController>().startNewGame(hostRadius, isOnline: true, roomCode: code, isHost: false, shape: hostShape, timeMode: hostTimeMode);
        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 _showFavoritesDialogForCreation() {
    final favs = StorageService.instance.favorites;

    showDialog(
        context: context,
        builder: (ctx) {
          final themeManager = ctx.watch<ThemeManager>();
          final theme = themeManager.currentColors;
          final themeType = themeManager.currentThemeType;

          return AlertDialog(
            backgroundColor: theme.background,
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(20),
            ),
            title: Text("I TUOI PREFERITI", style: getLobbyTextStyle(themeType, TextStyle(color: theme.text, fontWeight: FontWeight.bold))),
            content: Container(
              width: double.maxFinite,
              height: 300,
              decoration: BoxDecoration(
                  border: Border.all(color: theme.playerRed, width: 2),
                  borderRadius: BorderRadius.circular(10)
              ),
              child: favs.isEmpty
                  ? Center(child: Padding(
                padding: const EdgeInsets.all(20.0),
                child: Text("Non hai ancora aggiunto nessun preferito dalla Classifica!", textAlign: TextAlign.center, style: getLobbyTextStyle(themeType, TextStyle(color: theme.text.withOpacity(0.6)))),
              ))
                  : ListView.builder(
                itemCount: favs.length,
                itemBuilder: (c, i) {
                  return ListTile(
                    title: Text(favs[i]['name']!, style: getLobbyTextStyle(themeType, TextStyle(color: theme.text, fontSize: 18, fontWeight: FontWeight.bold))),
                    trailing: ElevatedButton(
                      style: ElevatedButton.styleFrom(backgroundColor: theme.playerBlue, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))),
                      onPressed: () {
                        Navigator.pop(ctx);
                        _createRoomAndInvite(favs[i]['uid']!, favs[i]['name']!);
                      },
                      child: Text("SFIDA", style: getLobbyTextStyle(themeType, const TextStyle(color: Colors.white, fontWeight: FontWeight.bold))),
                    ),
                  );
                },
              ),
            ),
            actions: [
              TextButton(onPressed: () => Navigator.pop(ctx), child: Text("CHIUDI", style: getLobbyTextStyle(themeType, TextStyle(color: theme.playerRed))))
            ],
          );
        }
    );
  }

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

          Widget dialogContent = Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              CircularProgressIndicator(color: theme.playerRed), const SizedBox(height: 25),
              Text("CODICE STANZA", style: getLobbyTextStyle(themeType, TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: theme.text.withOpacity(0.6), letterSpacing: 2))),
              Text(code, style: getLobbyTextStyle(themeType, TextStyle(fontSize: 40, fontWeight: FontWeight.w900, color: theme.playerRed, letterSpacing: 8, shadows: themeType == AppThemeType.doodle ? [] : [Shadow(color: theme.playerRed.withOpacity(0.5), blurRadius: 10)]))),
              const SizedBox(height: 25),
              Transform.rotate(
                angle: themeType == AppThemeType.doodle ? 0.02 : 0,
                child: Container(
                  padding: const EdgeInsets.all(18),
                  decoration: BoxDecoration(
                      color: themeType == AppThemeType.doodle ? Colors.white : theme.text.withOpacity(0.05),
                      borderRadius: BorderRadius.circular(20),
                      border: Border.all(color: themeType == AppThemeType.doodle ? theme.text : theme.playerBlue.withOpacity(0.3), width: themeType == AppThemeType.doodle ? 2 : 1.5),
                      boxShadow: themeType == AppThemeType.doodle
                          ? [BoxShadow(color: theme.text.withOpacity(0.8), offset: const Offset(4, 4))]
                          : [BoxShadow(color: theme.playerBlue.withOpacity(0.1), blurRadius: 10)]
                  ),
                  child: Column(
                    children: [
                      Icon(_isPublicRoom ? Icons.podcasts : Icons.share, color: theme.playerBlue, size: 32), const SizedBox(height: 12),
                      Text(_isPublicRoom ? "Sei in Bacheca!" : "Condividi link", textAlign: TextAlign.center, style: getLobbyTextStyle(themeType, TextStyle(color: theme.text, fontWeight: FontWeight.w900, fontSize: 18))),
                      const SizedBox(height: 8),
                      Text(_isPublicRoom ? "Aspettiamo che uno sfidante si unisca dalla lobby pubblica." : "Condividi il codice. La partita inizierà appena si unirà.", textAlign: TextAlign.center, style: getLobbyTextStyle(themeType, TextStyle(color: themeType == AppThemeType.doodle ? theme.text : theme.text.withOpacity(0.8), fontSize: 14, height: 1.5))),
                    ],
                  ),
                ),
              ),
            ],
          );

          if (themeType == AppThemeType.cyberpunk || themeType == AppThemeType.music) {
            dialogContent = AnimatedCyberBorder(child: dialogContent);
          } else {
            dialogContent = Container(
                padding: const EdgeInsets.all(20),
                decoration: BoxDecoration(
                    color: themeType == AppThemeType.doodle ? Colors.white.withOpacity(0.95) : theme.background,
                    borderRadius: BorderRadius.circular(25),
                    border: Border.all(color: themeType == AppThemeType.doodle ? theme.text : theme.gridLine.withOpacity(0.5), width: 2),
                    boxShadow: themeType == AppThemeType.doodle ? [BoxShadow(color: theme.text.withOpacity(0.6), offset: const Offset(8, 8))] : []
                ),
                child: dialogContent
            );
          }

          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') {
                  _roomStarted = true;
                  WidgetsBinding.instance.addPostFrameCallback((_) {
                    Navigator.pop(context);
                    context.read<GameController>().startNewGame(_selectedRadius, isOnline: true, roomCode: code, isHost: true, shape: _selectedShape, timeMode: _timeModeSetting);
                    Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => const GameScreen()));
                  });
                }
              }

              return PopScope(
                canPop: false,
                onPopInvoked: (didPop) {
                  if (didPop) return;
                  _cleanupGhostRoom();
                  Navigator.pop(context);
                },
                child: Dialog(
                  backgroundColor: Colors.transparent,
                  insetPadding: const EdgeInsets.all(20),
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      dialogContent,
                      const SizedBox(height: 20),
                      TextButton(
                        onPressed: () {
                          _cleanupGhostRoom();
                          Navigator.pop(context);
                        },
                        child: Text("ANNULLA", style: getLobbyTextStyle(themeType, TextStyle(color: Colors.red, fontWeight: FontWeight.w900, fontSize: 20, letterSpacing: 2.0, shadows: themeType == AppThemeType.doodle ? [] : [const Shadow(color: Colors.black, blurRadius: 2)]))),
                      ),
                    ],
                  ),
                ),
              );
            },
          );
        }
    );
  }

  Widget _buildTimeOption(String label, String sub, String value, ThemeColors theme, AppThemeType type) {
    bool isSel = value == _timeModeSetting;
    return Expanded(
      child: GestureDetector(
        onTap: () => setState(() => _timeModeSetting = value),
        child: Container(
          margin: const EdgeInsets.symmetric(horizontal: 4),
          height: 50,
          decoration: BoxDecoration(
            color: isSel ? Colors.orange.shade600 : (type == AppThemeType.doodle ? Colors.white : theme.text.withOpacity(0.05)),
            borderRadius: BorderRadius.circular(12),
            border: Border.all(color: isSel ? Colors.orange.shade800 : (type == AppThemeType.doodle ? const Color(0xFF111122) : Colors.white24), width: isSel ? 2 : 1.5),
            boxShadow: isSel && type != AppThemeType.doodle ? [BoxShadow(color: Colors.orange.withOpacity(0.5), blurRadius: 8)] : [],
          ),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(label, style: getLobbyTextStyle(type, TextStyle(color: isSel ? Colors.white : (type == AppThemeType.doodle ? const Color(0xFF111122) : theme.text), fontWeight: FontWeight.w900, fontSize: 13))),
              if (sub.isNotEmpty) Text(sub, style: getLobbyTextStyle(type, TextStyle(color: isSel ? Colors.white70 : (type == AppThemeType.doodle ? Colors.black54 : theme.text.withOpacity(0.5)), fontWeight: FontWeight.bold, fontSize: 8))),
            ],
          ),
        ),
      ),
    );
  }

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

    String? bgImage;
    if (themeType == AppThemeType.doodle) bgImage = 'assets/images/doodle_bg.jpg';
    if (themeType == AppThemeType.cyberpunk) bgImage = 'assets/images/cyber_bg.jpg';
    if (themeType == AppThemeType.music) bgImage = 'assets/images/music_bg.jpg';
    if (themeType == AppThemeType.arcade) bgImage = 'assets/images/arcade.jpg';
    if (themeType == AppThemeType.grimorio) bgImage = 'assets/images/grimorio.jpg';

    bool isChaosUnlocked = StorageService.instance.playerLevel >= 7;

    Color panelBackgroundColor = Colors.transparent;
    if (themeType == AppThemeType.cyberpunk) {
      panelBackgroundColor = Colors.black.withOpacity(0.1);
    } else if (themeType == AppThemeType.doodle) {
      panelBackgroundColor = Colors.white.withOpacity(0.5);
    } else if (themeType == AppThemeType.grimorio) {
      panelBackgroundColor = Colors.white.withOpacity(0.2);
    } else if (themeType == AppThemeType.arcade) {
      panelBackgroundColor = Colors.black.withOpacity(0.4);
    }


    Widget hostPanel = Transform.rotate(
      angle: themeType == AppThemeType.doodle ? 0.01 : 0,
      child: Container(
        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 15),
        decoration: BoxDecoration(
          color: panelBackgroundColor,
          borderRadius: BorderRadius.only(
            topLeft: Radius.circular(themeType == AppThemeType.doodle ? 5 : 20),
            topRight: const Radius.circular(20),
            bottomLeft: const Radius.circular(20),
            bottomRight: Radius.circular(themeType == AppThemeType.doodle ? 5 : 20),
          ),
          border: themeType == AppThemeType.cyberpunk ? null : Border.all(color: themeType == AppThemeType.doodle ? theme.text.withOpacity(0.5) : Colors.white.withOpacity(0.15), width: themeType == AppThemeType.doodle ? 2 : 1.5),
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Center(child: Text("IMPOSTAZIONI STANZA", textAlign: TextAlign.center, style: getLobbyTextStyle(themeType, TextStyle(fontSize: 12, fontWeight: FontWeight.w900, color: themeType == AppThemeType.doodle ? theme.text : theme.text.withOpacity(0.6), letterSpacing: 2.0)))),
            const SizedBox(height: 10),

            Text("FORMA ARENA", style: getLobbyTextStyle(themeType, TextStyle(fontSize: 10, fontWeight: FontWeight.w900, color: themeType == AppThemeType.doodle ? theme.text : theme.text.withOpacity(0.5), letterSpacing: 1.5))),
            const SizedBox(height: 6),

            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Expanded(child: NeonShapeButton(icon: Icons.diamond_outlined, label: 'Rombo', isSelected: _selectedShape == ArenaShape.classic, theme: theme, themeType: themeType, onTap: () => setState(() => _selectedShape = ArenaShape.classic))),
                const SizedBox(width: 4),
                Expanded(child: NeonShapeButton(icon: Icons.add, label: 'Croce', isSelected: _selectedShape == ArenaShape.cross, theme: theme, themeType: themeType, onTap: () => setState(() => _selectedShape = ArenaShape.cross))),
                const SizedBox(width: 4),
                Expanded(child: NeonShapeButton(icon: Icons.donut_large, label: 'Buco', isSelected: _selectedShape == ArenaShape.donut, theme: theme, themeType: themeType, onTap: () => setState(() => _selectedShape = ArenaShape.donut))),
                const SizedBox(width: 4),
                Expanded(child: NeonShapeButton(icon: Icons.hourglass_bottom, label: 'Clessidra', isSelected: _selectedShape == ArenaShape.hourglass, theme: theme, themeType: themeType, onTap: () => setState(() => _selectedShape = ArenaShape.hourglass))),
                const SizedBox(width: 4),
                Expanded(child: NeonShapeButton(icon: Icons.all_inclusive, label: 'Caos', isSelected: _selectedShape == ArenaShape.chaos, theme: theme, themeType: themeType, isSpecial: true, isLocked: !isChaosUnlocked, onTap: () => setState(() => _selectedShape = ArenaShape.chaos))),
              ],
            ),

            const SizedBox(height: 12),
            Divider(color: themeType == AppThemeType.doodle ? theme.text.withOpacity(0.5) : Colors.white.withOpacity(0.05), thickness: themeType == AppThemeType.doodle ? 2.5 : 1.5),
            const SizedBox(height: 12),

            Text("GRANDEZZA", style: getLobbyTextStyle(themeType, TextStyle(fontSize: 10, fontWeight: FontWeight.w900, color: themeType == AppThemeType.doodle ? theme.text : theme.text.withOpacity(0.5), letterSpacing: 1.5))),
            const SizedBox(height: 8),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                NeonSizeButton(label: 'S', isSelected: _selectedRadius == 3, theme: theme, themeType: themeType, onTap: () => setState(() => _selectedRadius = 3)),
                NeonSizeButton(label: 'M', isSelected: _selectedRadius == 4, theme: theme, themeType: themeType, onTap: () => setState(() => _selectedRadius = 4)),
                NeonSizeButton(label: 'L', isSelected: _selectedRadius == 5, theme: theme, themeType: themeType, onTap: () => setState(() => _selectedRadius = 5)),
                NeonSizeButton(label: 'MAX', isSelected: _selectedRadius == 6, theme: theme, themeType: themeType, onTap: () => setState(() => _selectedRadius = 6)),
              ],
            ),

            const SizedBox(height: 12),
            Divider(color: themeType == AppThemeType.doodle ? theme.text.withOpacity(0.5) : Colors.white.withOpacity(0.05), thickness: themeType == AppThemeType.doodle ? 2.5 : 1.5),
            const SizedBox(height: 12),

            Text("TEMPO E OPZIONI", style: getLobbyTextStyle(themeType, TextStyle(fontSize: 10, fontWeight: FontWeight.w900, color: themeType == AppThemeType.doodle ? theme.text : theme.text.withOpacity(0.5), letterSpacing: 1.5))),
            const SizedBox(height: 8),

            Row(
              children: [
                _buildTimeOption('10s', 'FISSO', 'fixed', theme, themeType),
                _buildTimeOption('RELAX', 'INFINITO', 'relax', theme, themeType),
                _buildTimeOption('DINAMICO', '-2s', 'dynamic', theme, themeType),
              ],
            ),
            const SizedBox(height: 10),

            Row(
              children: [
                Expanded(child: NeonPrivacySwitch(isPublic: _isPublicRoom, theme: theme, themeType: themeType, onTap: () => setState(() => _isPublicRoom = !_isPublicRoom))),
                const SizedBox(width: 8),
                Expanded(child: NeonInviteFavoriteButton(theme: theme, themeType: themeType, onTap: _showFavoritesDialogForCreation)),
              ],
            )
          ],
        ),
      ),
    );

    if (themeType == AppThemeType.cyberpunk || themeType == AppThemeType.music) {
      hostPanel = AnimatedCyberBorder(child: hostPanel);
    }

    Widget uiContent = SafeArea(
      child: SingleChildScrollView(
        physics: const BouncingScrollPhysics(),
        padding: EdgeInsets.only(left: 20.0, right: 20.0, top: 10.0, bottom: MediaQuery.of(context).padding.bottom + 60.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Row(
              children: [
                IconButton(
                  icon: Icon(Icons.arrow_back_ios_new, color: theme.text),
                  onPressed: () => Navigator.pop(context),
                ),
                Expanded(
                  child: Text("MULTIPLAYER", textAlign: TextAlign.center, style: getLobbyTextStyle(themeType, TextStyle(fontSize: 20, fontWeight: FontWeight.w900, color: theme.text, letterSpacing: 2))),
                ),
                const SizedBox(width: 48),
              ],
            ),
            const SizedBox(height: 20),

            AnimatedSize(
              duration: const Duration(milliseconds: 300),
              curve: Curves.easeInOut,
              alignment: Alignment.topCenter,
              child: _isCreatingRoom
                  ? Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  hostPanel,
                  const SizedBox(height: 15),
                  Row(
                    children: [
                      Expanded(
                        child: NeonActionButton(label: "AVVIA", color: theme.playerRed, onTap: _createRoom, theme: theme, themeType: themeType),
                      ),
                      const SizedBox(width: 10),
                      Expanded(
                        child: NeonActionButton(label: "ANNULLA", color: Colors.grey.shade600, onTap: () => setState(() => _isCreatingRoom = false), theme: theme, themeType: themeType),
                      ),
                    ],
                  ),
                ],
              )
                  : Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  NeonActionButton(label: "CREA PARTITA", color: theme.playerRed, onTap: () { FocusScope.of(context).unfocus(); setState(() => _isCreatingRoom = true); }, theme: theme, themeType: themeType),
                  const SizedBox(height: 20),
                  Row(
                    children: [
                      Expanded(child: Divider(color: theme.text.withOpacity(0.4), thickness: themeType == AppThemeType.doodle ? 2 : 1.0)),
                      Padding(padding: const EdgeInsets.symmetric(horizontal: 10), child: Text("OPPURE", style: getLobbyTextStyle(themeType, TextStyle(color: themeType == AppThemeType.doodle ? theme.text : theme.text.withOpacity(0.5), fontWeight: FontWeight.bold, letterSpacing: 2.0, fontSize: 13)))),
                      Expanded(child: Divider(color: theme.text.withOpacity(0.4), thickness: themeType == AppThemeType.doodle ? 2 : 1.0)),
                    ],
                  ),
                  const SizedBox(height: 20),

                  Transform.rotate(
                    angle: themeType == AppThemeType.doodle ? 0.02 : 0,
                    child: Container(
                      decoration: themeType == AppThemeType.doodle ? BoxDecoration(
                        color: Colors.white,
                        borderRadius: const BorderRadius.only(topLeft: Radius.circular(20), bottomRight: Radius.circular(20), topRight: Radius.circular(5), bottomLeft: Radius.circular(5)),
                        border: Border.all(color: theme.text, width: 2.5),
                        boxShadow: [BoxShadow(color: theme.text.withOpacity(0.8), offset: const Offset(5, 5), blurRadius: 0)],
                      ) : BoxDecoration(
                          boxShadow: [BoxShadow(color: theme.playerBlue.withOpacity(0.15), blurRadius: 15, spreadRadius: 1)]
                      ),
                      child: TextField(
                        controller: _codeController, textCapitalization: TextCapitalization.characters, textAlign: TextAlign.center, maxLength: 5,
                        style: getLobbyTextStyle(themeType, TextStyle(fontSize: 28, fontWeight: FontWeight.w900, color: theme.text, letterSpacing: 12, shadows: themeType == AppThemeType.doodle ? [] : [Shadow(color: theme.playerBlue.withOpacity(0.5), blurRadius: 8)])),
                        decoration: InputDecoration(
                          contentPadding: const EdgeInsets.symmetric(vertical: 12),
                          hintText: "CODICE", hintStyle: getLobbyTextStyle(themeType, TextStyle(color: theme.text.withOpacity(0.3), letterSpacing: 10, fontSize: 20)), counterText: "",
                          filled: themeType != AppThemeType.doodle,
                          fillColor: themeType == AppThemeType.cyberpunk ? Colors.black.withOpacity(0.85) : theme.text.withOpacity(0.05),
                          enabledBorder: themeType == AppThemeType.doodle ? InputBorder.none : OutlineInputBorder(borderSide: BorderSide(color: theme.gridLine.withOpacity(0.5), width: 2.0), borderRadius: BorderRadius.circular(15)),
                          focusedBorder: themeType == AppThemeType.doodle ? InputBorder.none : OutlineInputBorder(borderSide: BorderSide(color: theme.playerBlue, width: 3.0), borderRadius: BorderRadius.circular(15)),
                        ),
                      ),
                    ),
                  ),
                  const SizedBox(height: 15),
                  NeonActionButton(label: "UNISCITI", color: theme.playerBlue, onTap: () => _joinRoomByCode(_codeController.text), theme: theme, themeType: themeType),
                ],
              ),
            ),

            const SizedBox(height: 25),
            Row(
              children: [
                Expanded(child: Divider(color: theme.text.withOpacity(0.4), thickness: themeType == AppThemeType.doodle ? 2 : 1.0)),
                Padding(padding: const EdgeInsets.symmetric(horizontal: 10), child: Text("LOBBY PUBBLICA", style: getLobbyTextStyle(themeType, TextStyle(color: themeType == AppThemeType.doodle ? theme.text : theme.text.withOpacity(0.5), fontWeight: FontWeight.bold, letterSpacing: 2.0, fontSize: 13)))),
                Expanded(child: Divider(color: theme.text.withOpacity(0.4), thickness: themeType == AppThemeType.doodle ? 2 : 1.0)),
              ],
            ),
            const SizedBox(height: 15),

            StreamBuilder<QuerySnapshot>(
                stream: _multiplayerService.getPublicRooms(),
                builder: (context, snapshot) {
                  if (snapshot.connectionState == ConnectionState.waiting) {
                    return Padding(padding: const EdgeInsets.all(20), child: Center(child: CircularProgressIndicator(color: theme.playerBlue)));
                  }

                  if (!snapshot.hasData || snapshot.data!.docs.isEmpty) {
                    return Padding(
                      padding: const EdgeInsets.symmetric(vertical: 40.0),
                      child: Center(child: Text("Nessuna stanza pubblica al momento.\nCreane una tu!", textAlign: TextAlign.center, style: getLobbyTextStyle(themeType, TextStyle(color: theme.text.withOpacity(0.6), height: 1.5, fontSize: 16)))),
                    );
                  }

                  DateTime now = DateTime.now();
                  String? myUid = FirebaseAuth.instance.currentUser?.uid;

                  var docs = snapshot.data!.docs.where((doc) {
                    var data = doc.data() as Map<String, dynamic>;
                    if (data['isPublic'] != true) return false;
                    if (data['hostUid'] != null && data['hostUid'] == myUid) return false;

                    Timestamp? createdAt = data['createdAt'] as Timestamp?;
                    if (createdAt != null) {
                      int ageInMinutes = now.difference(createdAt.toDate()).inMinutes;
                      if (ageInMinutes > 15) {
                        FirebaseFirestore.instance.collection('games').doc(doc.id).delete();
                        return false;
                      }
                    }
                    return true;
                  }).toList();

                  if (docs.isEmpty) {
                    return Padding(
                      padding: const EdgeInsets.symmetric(vertical: 40.0),
                      child: Center(child: Text("Nessuna stanza pubblica al momento.\nCreane una tu!", textAlign: TextAlign.center, style: getLobbyTextStyle(themeType, TextStyle(color: theme.text.withOpacity(0.6), height: 1.5, fontSize: 16)))),
                    );
                  }

                  docs.sort((a, b) {
                    Timestamp? tA = (a.data() as Map<String, dynamic>)['createdAt'] as Timestamp?;
                    Timestamp? tB = (b.data() as Map<String, dynamic>)['createdAt'] as Timestamp?;
                    if (tA == null || tB == null) return 0;
                    return tB.compareTo(tA);
                  });

                  return ListView.builder(
                      shrinkWrap: true,
                      physics: const NeverScrollableScrollPhysics(),
                      padding: EdgeInsets.zero,
                      itemCount: docs.length,
                      itemBuilder: (context, index) {
                        var doc = docs[index];
                        var data = doc.data() as Map<String, dynamic>;
                        String host = data['hostName'] ?? 'Sconosciuto';
                        int r = data['radius'] ?? 4;
                        String shapeStr = data['shape'] ?? 'classic';

                        String tMode = data['timeMode'] is String ? data['timeMode'] : (data['timeMode'] == true ? 'fixed' : 'relax');
                        String prettyTime = "10s";
                        if (tMode == 'relax') prettyTime = "Relax";
                        else if (tMode == 'dynamic') prettyTime = "Dinamico";

                        String prettyShape = "Rombo";
                        if (shapeStr == 'cross') prettyShape = "Croce";
                        else if (shapeStr == 'donut') prettyShape = "Buco";
                        else if (shapeStr == 'hourglass') prettyShape = "Clessidra";
                        else if (shapeStr == 'chaos') prettyShape = "Caos";

                        return Transform.rotate(
                          angle: themeType == AppThemeType.doodle ? (index % 2 == 0 ? 0.01 : -0.01) : 0,
                          child: Container(
                            margin: const EdgeInsets.only(bottom: 15),
                            padding: const EdgeInsets.all(16),
                            decoration: BoxDecoration(
                              color: themeType == AppThemeType.doodle ? Colors.white : theme.text.withOpacity(0.05),
                              borderRadius: BorderRadius.circular(15),
                              border: Border.all(color: themeType == AppThemeType.doodle ? theme.text : theme.playerBlue.withOpacity(0.3), width: themeType == AppThemeType.doodle ? 2 : 1),
                              boxShadow: themeType == AppThemeType.doodle ? [BoxShadow(color: theme.text.withOpacity(0.6), offset: const Offset(3, 4))] : [],
                            ),
                            child: Row(
                              children: [
                                CircleAvatar(radius: 25, backgroundColor: theme.playerRed.withOpacity(0.2), child: Icon(Icons.person, color: theme.playerRed, size: 28)),
                                const SizedBox(width: 15),
                                Expanded(
                                  child: Column(
                                    crossAxisAlignment: CrossAxisAlignment.start,
                                    children: [
                                      Text("Stanza di $host", style: getLobbyTextStyle(themeType, TextStyle(color: theme.text, fontWeight: FontWeight.bold, fontSize: 18))),
                                      const SizedBox(height: 6),
                                      Text("Raggio: $r  •  $prettyShape  •  $prettyTime", style: getLobbyTextStyle(themeType, TextStyle(color: theme.text.withOpacity(0.6), fontSize: 12))),
                                    ],
                                  ),
                                ),
                                ElevatedButton(
                                  style: ElevatedButton.styleFrom(
                                    padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
                                    backgroundColor: theme.playerBlue, foregroundColor: Colors.white,
                                    shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
                                    elevation: themeType == AppThemeType.doodle ? 0 : 2,
                                    side: themeType == AppThemeType.doodle ? BorderSide(color: theme.text, width: 2) : BorderSide.none,
                                  ),
                                  onPressed: () => _joinRoomByCode(doc.id),
                                  child: Text("ENTRA", style: getLobbyTextStyle(themeType, const TextStyle(fontWeight: FontWeight.w900, letterSpacing: 1.0))),
                                )
                              ],
                            ),
                          ),
                        );
                      }
                  );
                }
            ),
          ],
        ),
      ),
    );

    return Scaffold(
      backgroundColor: bgImage != null ? Colors.transparent : theme.background,
      extendBodyBehindAppBar: true,
      body: Stack(
        children: [
          Container(color: themeType == AppThemeType.doodle ? Colors.white : theme.background),

          if (themeType == AppThemeType.doodle)
            Positioned.fill(
              child: CustomPaint(
                painter: FullScreenGridPainter(Colors.blue.withOpacity(0.15)),
              ),
            ),

          if (bgImage != null)
            Positioned.fill(
              child: Container(
                decoration: BoxDecoration(
                  image: DecorationImage(
                    image: AssetImage(bgImage!),
                    fit: BoxFit.cover,
                    colorFilter: themeType == AppThemeType.doodle
                        ? ColorFilter.mode(Colors.white.withOpacity(0.5), BlendMode.lighten)
                        : null,
                  ),
                ),
              ),
            ),

          if (bgImage != null && (themeType == AppThemeType.cyberpunk || themeType == AppThemeType.music || themeType == AppThemeType.arcade || themeType == AppThemeType.grimorio))
            Positioned.fill(
              child: Container(
                decoration: BoxDecoration(
                    gradient: LinearGradient(
                        begin: Alignment.topCenter, end: Alignment.bottomCenter,
                        colors: [Colors.black.withOpacity(0.4), Colors.black.withOpacity(0.8)]
                    )
                ),
              ),
            ),

          if (themeType == AppThemeType.music)
            Positioned.fill(
              child: IgnorePointer(
                child: CustomPaint(
                  painter: AudioCablesPainter(),
                ),
              ),
            ),

          Positioned.fill(child: uiContent),
        ],
      ),
    );
  }
}
// ===========================================================================
// FILE: lib/ui/multiplayer/lobby_widgets.dart
// ===========================================================================

// ===========================================================================
// FILE: lib/ui/multiplayer/lobby_widgets.dart
// ===========================================================================

import 'package:flutter/material.dart';
import 'dart:math' as math;
import 'package:google_fonts/google_fonts.dart';

import '../../core/theme_manager.dart';
import '../../core/app_colors.dart';

TextStyle getLobbyTextStyle(AppThemeType themeType, TextStyle baseStyle) {
  if (themeType == AppThemeType.doodle) {
    return GoogleFonts.permanentMarker(textStyle: baseStyle);
  } else if (themeType == AppThemeType.arcade) {
    return GoogleFonts.pressStart2p(textStyle: baseStyle.copyWith(
      fontSize: baseStyle.fontSize != null ? baseStyle.fontSize! * 0.75 : null,
      letterSpacing: 0.5,
    ));
  } else if (themeType == AppThemeType.grimorio) {
    return GoogleFonts.cinzelDecorative(textStyle: baseStyle.copyWith(fontWeight: FontWeight.bold));
  } else if (themeType == AppThemeType.music) {
    return GoogleFonts.audiowide(textStyle: baseStyle.copyWith(letterSpacing: 1.5));
  }
  return baseStyle;
}

class NeonShapeButton extends StatelessWidget {
  final IconData icon;
  final String label;
  final bool isSelected;
  final ThemeColors theme;
  final AppThemeType themeType;
  final VoidCallback onTap;
  final bool isLocked;
  final bool isSpecial;

  const NeonShapeButton({
    super.key, required this.icon, required this.label, required this.isSelected,
    required this.theme, required this.themeType, required this.onTap,
    this.isLocked = false, this.isSpecial = false
  });

  Color _getDoodleColor() {
    switch (label) {
      case 'Rombo': return Colors.blue.shade700;
      case 'Croce': return Colors.teal.shade700;
      case 'Buco': return Colors.pink.shade600;
      case 'Clessidra': return Colors.deepPurple.shade600;
      case 'Caos': return Colors.blueGrey.shade800;
      default: return Colors.blue.shade700;
    }
  }

  @override
  Widget build(BuildContext context) {
    if (themeType == AppThemeType.doodle) {
      Color doodleColor = isLocked ? Colors.grey : _getDoodleColor();
      double tilt = (label.length % 2 == 0) ? -0.03 : 0.04;

      return Transform.rotate(
        angle: tilt,
        child: GestureDetector(
          onTap: isLocked ? null : onTap,
          child: AnimatedContainer(
            duration: const Duration(milliseconds: 200),
            padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 6),
            transform: Matrix4.translationValues(0, isSelected ? 3 : 0, 0),
            decoration: BoxDecoration(
              color: isSelected ? doodleColor : Colors.white,
              borderRadius: const BorderRadius.only(
                topLeft: Radius.circular(15), topRight: Radius.circular(8),
                bottomLeft: Radius.circular(6), bottomRight: Radius.circular(18),
              ),
              border: Border.all(color: isSelected ? theme.text : doodleColor.withOpacity(0.5), width: isSelected ? 2.5 : 1.5),
              boxShadow: isSelected
                  ? [BoxShadow(color: theme.text.withOpacity(0.8), offset: const Offset(3, 4), blurRadius: 0)]
                  : [BoxShadow(color: doodleColor.withOpacity(0.2), offset: const Offset(2, 2), blurRadius: 0)],
            ),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Icon(isLocked ? Icons.lock : icon, color: isSelected ? Colors.white : doodleColor, size: 20),
                const SizedBox(height: 2),
                FittedBox(fit: BoxFit.scaleDown, child: Text(isLocked ? "Liv. 7" : label, style: getLobbyTextStyle(themeType, TextStyle(color: isSelected ? Colors.white : doodleColor, fontSize: 9, fontWeight: FontWeight.w900, letterSpacing: 0.2)))),
              ],
            ),
          ),
        ),
      );
    }

    Color mainColor = isSpecial && !isLocked ? Colors.purpleAccent : theme.playerBlue;
    return GestureDetector(
      onTap: isLocked ? null : onTap,
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 250),
        curve: Curves.easeOutCubic,
        padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8),
        transform: Matrix4.translationValues(0, isSelected ? 2 : 0, 0),
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(12),
          gradient: LinearGradient(
            begin: Alignment.topLeft,
            end: Alignment.bottomRight,
            colors: isLocked
                ? [Colors.grey.withOpacity(0.1), Colors.black.withOpacity(0.2)]
                : isSelected
                ? [mainColor.withOpacity(0.3), mainColor.withOpacity(0.1)]
                : [theme.text.withOpacity(0.1), theme.text.withOpacity(0.02)],
          ),
          border: Border.all(
            color: isLocked ? Colors.transparent : (isSelected ? mainColor : Colors.white.withOpacity(0.1)),
            width: isSelected ? 2 : 1,
          ),
          boxShadow: isLocked ? [] : isSelected
              ? [BoxShadow(color: mainColor.withOpacity(0.5), blurRadius: 15, spreadRadius: 1, offset: const Offset(0, 0))]
              : [
            BoxShadow(color: Colors.black.withOpacity(0.4), blurRadius: 6, offset: const Offset(2, 4)),
            BoxShadow(color: Colors.white.withOpacity(0.05), blurRadius: 2, offset: const Offset(-1, -1)),
          ],
        ),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(isLocked ? Icons.lock : icon, color: isLocked ? Colors.grey.withOpacity(0.5) : (isSelected ? Colors.white : theme.text.withOpacity(0.6)), size: 20),
            const SizedBox(height: 4),
            FittedBox(fit: BoxFit.scaleDown, child: Text(isLocked ? "Liv. 7" : label, style: getLobbyTextStyle(themeType, TextStyle(color: isLocked ? Colors.grey.withOpacity(0.5) : (isSelected ? Colors.white : theme.text.withOpacity(0.6)), fontSize: 9, fontWeight: isSelected ? FontWeight.w900 : FontWeight.bold)))),
          ],
        ),
      ),
    );
  }
}

class NeonSizeButton extends StatelessWidget {
  final String label;
  final bool isSelected;
  final ThemeColors theme;
  final AppThemeType themeType;
  final VoidCallback onTap;

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

  @override
  Widget build(BuildContext context) {
    if (themeType == AppThemeType.doodle) {
      Color doodleColor = label == 'MAX' ? Colors.red.shade700 : Colors.blueGrey.shade600;
      double tilt = (label == 'M' || label == 'MAX') ? 0.05 : -0.04;

      return Transform.rotate(
        angle: tilt,
        child: GestureDetector(
          onTap: onTap,
          child: AnimatedContainer(
            duration: const Duration(milliseconds: 200),
            width: 42, height: 40,
            transform: Matrix4.translationValues(0, isSelected ? 3 : 0, 0),
            decoration: BoxDecoration(
              color: isSelected ? doodleColor : Colors.white,
              borderRadius: const BorderRadius.all(Radius.elliptical(25, 20)),
              border: Border.all(color: isSelected ? theme.text : doodleColor.withOpacity(0.5), width: 2),
              boxShadow: isSelected
                  ? [BoxShadow(color: theme.text.withOpacity(0.8), offset: const Offset(3, 4), blurRadius: 0)]
                  : [BoxShadow(color: doodleColor.withOpacity(0.2), offset: const Offset(2, 2), blurRadius: 0)],
            ),
            child: Center(
              child: FittedBox(fit: BoxFit.scaleDown, child: Text(label, style: getLobbyTextStyle(themeType, TextStyle(color: isSelected ? Colors.white : doodleColor, fontSize: 13, fontWeight: FontWeight.w900)))),
            ),
          ),
        ),
      );
    }

    return GestureDetector(
      onTap: onTap,
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 250),
        curve: Curves.easeOutCubic,
        width: 42, height: 42,
        transform: Matrix4.translationValues(0, isSelected ? 2 : 0, 0),
        decoration: BoxDecoration(
          shape: BoxShape.circle,
          gradient: LinearGradient(
            begin: Alignment.topLeft,
            end: Alignment.bottomRight,
            colors: isSelected
                ? [theme.playerRed.withOpacity(0.3), theme.playerRed.withOpacity(0.1)]
                : [theme.text.withOpacity(0.1), theme.text.withOpacity(0.02)],
          ),
          border: Border.all(color: isSelected ? theme.playerRed : Colors.white.withOpacity(0.1), width: isSelected ? 2 : 1),
          boxShadow: isSelected
              ? [BoxShadow(color: theme.playerRed.withOpacity(0.5), blurRadius: 15, spreadRadius: 1)]
              : [
            BoxShadow(color: Colors.black.withOpacity(0.4), blurRadius: 6, offset: const Offset(2, 4)),
            BoxShadow(color: Colors.white.withOpacity(0.05), blurRadius: 2, offset: const Offset(-1, -1)),
          ],
        ),
        child: Center(
          child: FittedBox(fit: BoxFit.scaleDown, child: Text(label, style: getLobbyTextStyle(themeType, TextStyle(color: isSelected ? Colors.white : theme.text.withOpacity(0.6), fontSize: 12, fontWeight: isSelected ? FontWeight.w900 : FontWeight.bold)))),
        ),
      ),
    );
  }
}

class NeonTimeSwitch extends StatelessWidget {
  final bool isTimeMode;
  final ThemeColors theme;
  final AppThemeType themeType;
  final VoidCallback onTap;

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

  @override
  Widget build(BuildContext context) {
    if (themeType == AppThemeType.doodle) {
      Color doodleColor = Colors.orange.shade700;
      return Transform.rotate(
        angle: -0.015,
        child: GestureDetector(
          onTap: onTap,
          child: AnimatedContainer(
            duration: const Duration(milliseconds: 200),
            padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8),
            transform: Matrix4.translationValues(0, isTimeMode ? 3 : 0, 0),
            decoration: BoxDecoration(
              color: isTimeMode ? doodleColor : Colors.white,
              borderRadius: const BorderRadius.only(
                topLeft: Radius.circular(8), topRight: Radius.circular(15),
                bottomLeft: Radius.circular(15), bottomRight: Radius.circular(6),
              ),
              border: Border.all(color: isTimeMode ? theme.text : doodleColor.withOpacity(0.5), width: 2.5),
              boxShadow: isTimeMode
                  ? [BoxShadow(color: theme.text.withOpacity(0.8), offset: const Offset(4, 5), blurRadius: 0)]
                  : [BoxShadow(color: doodleColor.withOpacity(0.2), offset: const Offset(2, 2), blurRadius: 0)],
            ),
            child: Row(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Icon(isTimeMode ? Icons.timer : Icons.timer_off, color: isTimeMode ? Colors.white : doodleColor, size: 20),
                const SizedBox(width: 8),
                Flexible(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      FittedBox(fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text(isTimeMode ? 'A TEMPO' : 'RELAX', style: getLobbyTextStyle(themeType, TextStyle(color: isTimeMode ? Colors.white : doodleColor, fontWeight: FontWeight.w900, fontSize: 12, letterSpacing: 1.0)))),
                      FittedBox(fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text(isTimeMode ? '15s a mossa' : 'Senza limiti', style: getLobbyTextStyle(themeType, TextStyle(color: isTimeMode ? Colors.white : doodleColor.withOpacity(0.8), fontSize: 9, fontWeight: FontWeight.bold)))),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      );
    }

    return GestureDetector(
      onTap: onTap,
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeInOut,
        padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8),
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(15),
          gradient: LinearGradient(
            begin: Alignment.topLeft,
            end: Alignment.bottomRight,
            colors: isTimeMode
                ? [Colors.amber.withOpacity(0.25), Colors.amber.withOpacity(0.05)]
                : [theme.text.withOpacity(0.1), theme.text.withOpacity(0.02)],
          ),
          border: Border.all(color: isTimeMode ? Colors.amber : Colors.white.withOpacity(0.1), width: isTimeMode ? 2 : 1),
          boxShadow: isTimeMode
              ? [BoxShadow(color: Colors.amber.withOpacity(0.3), blurRadius: 15, spreadRadius: 2)]
              : [
            BoxShadow(color: Colors.black.withOpacity(0.4), blurRadius: 6, offset: const Offset(2, 4)),
            BoxShadow(color: Colors.white.withOpacity(0.05), blurRadius: 2, offset: const Offset(-1, -1)),
          ],
        ),
        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: 20),
            const SizedBox(width: 8),
            Flexible(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: [
                  FittedBox(fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text(isTimeMode ? 'A TEMPO' : 'RELAX', style: getLobbyTextStyle(themeType, TextStyle(color: isTimeMode ? Colors.white : theme.text.withOpacity(0.5), fontWeight: FontWeight.w900, fontSize: 11, letterSpacing: 1.5)))),
                  FittedBox(fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text(isTimeMode ? '15s a mossa' : 'Senza limiti', style: getLobbyTextStyle(themeType, TextStyle(color: isTimeMode ? Colors.amber.shade200 : theme.text.withOpacity(0.4), fontSize: 9, fontWeight: FontWeight.bold)))),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class NeonPrivacySwitch extends StatelessWidget {
  final bool isPublic;
  final ThemeColors theme;
  final AppThemeType themeType;
  final VoidCallback onTap;

  const NeonPrivacySwitch({super.key, required this.isPublic, required this.theme, required this.themeType, required this.onTap});

  @override
  Widget build(BuildContext context) {
    if (themeType == AppThemeType.doodle) {
      Color doodleColor = isPublic ? Colors.green.shade600 : Colors.red.shade600;
      return Transform.rotate(
        angle: 0.015,
        child: GestureDetector(
          onTap: onTap,
          child: AnimatedContainer(
            duration: const Duration(milliseconds: 200),
            padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8),
            transform: Matrix4.translationValues(0, isPublic ? 3 : 0, 0),
            decoration: BoxDecoration(
              color: isPublic ? doodleColor : Colors.white,
              borderRadius: const BorderRadius.only(
                topLeft: Radius.circular(15), topRight: Radius.circular(8),
                bottomLeft: Radius.circular(6), bottomRight: Radius.circular(15),
              ),
              border: Border.all(color: isPublic ? theme.text : doodleColor.withOpacity(0.5), width: 2.5),
              boxShadow: [BoxShadow(color: isPublic ? theme.text.withOpacity(0.8) : doodleColor.withOpacity(0.2), offset: const Offset(4, 5), blurRadius: 0)],
            ),
            child: Row(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Icon(isPublic ? Icons.public : Icons.lock, color: isPublic ? Colors.white : doodleColor, size: 20),
                const SizedBox(width: 8),
                Flexible(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      FittedBox(fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text(isPublic ? 'STANZA PUBBLICA' : 'STANZA PRIVATA', style: getLobbyTextStyle(themeType, TextStyle(color: isPublic ? Colors.white : doodleColor, fontWeight: FontWeight.w900, fontSize: 10, letterSpacing: 1.0)))),
                      FittedBox(fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text(isPublic ? 'In bacheca' : 'Invita con codice', style: getLobbyTextStyle(themeType, TextStyle(color: isPublic ? Colors.white : doodleColor.withOpacity(0.8), fontSize: 9, fontWeight: FontWeight.bold)))),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      );
    }

    return GestureDetector(
      onTap: onTap,
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeInOut,
        padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8),
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(15),
          gradient: LinearGradient(
            begin: Alignment.topLeft,
            end: Alignment.bottomRight,
            colors: isPublic
                ? [Colors.greenAccent.withOpacity(0.25), Colors.greenAccent.withOpacity(0.05)]
                : [theme.playerRed.withOpacity(0.25), theme.playerRed.withOpacity(0.05)],
          ),
          border: Border.all(color: isPublic ? Colors.greenAccent : theme.playerRed, width: isPublic ? 2 : 1),
          boxShadow: isPublic
              ? [BoxShadow(color: Colors.greenAccent.withOpacity(0.3), blurRadius: 15, spreadRadius: 2)]
              : [BoxShadow(color: Colors.black.withOpacity(0.4), blurRadius: 6, offset: const Offset(2, 4))],
        ),
        child: Row(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(isPublic ? Icons.public : Icons.lock, color: isPublic ? Colors.greenAccent : theme.playerRed, size: 20),
            const SizedBox(width: 8),
            Flexible(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: [
                  FittedBox(fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text(isPublic ? 'STANZA PUBBLICA' : 'STANZA PRIVATA', style: getLobbyTextStyle(themeType, TextStyle(color: isPublic ? Colors.white : theme.text.withOpacity(0.8), fontWeight: FontWeight.w900, fontSize: 10, letterSpacing: 1.0)))),
                  FittedBox(fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text(isPublic ? 'Tutti ti vedono' : 'Solo con Codice', style: getLobbyTextStyle(themeType, TextStyle(color: isPublic ? Colors.greenAccent.shade200 : theme.playerRed.withOpacity(0.7), fontSize: 9, fontWeight: FontWeight.bold)))),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class NeonInviteFavoriteButton extends StatelessWidget {
  final ThemeColors theme;
  final AppThemeType themeType;
  final VoidCallback onTap;

  const NeonInviteFavoriteButton({super.key, required this.theme, required this.themeType, required this.onTap});

  @override
  Widget build(BuildContext context) {
    if (themeType == AppThemeType.doodle) {
      Color doodleColor = Colors.pink.shade600;
      return Transform.rotate(
        angle: -0.015,
        child: GestureDetector(
          onTap: onTap,
          child: AnimatedContainer(
            duration: const Duration(milliseconds: 200),
            padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8),
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: const BorderRadius.only(
                topLeft: Radius.circular(8), topRight: Radius.circular(15),
                bottomLeft: Radius.circular(15), bottomRight: Radius.circular(6),
              ),
              border: Border.all(color: doodleColor.withOpacity(0.5), width: 2.5),
              boxShadow: [BoxShadow(color: doodleColor.withOpacity(0.2), offset: const Offset(4, 5), blurRadius: 0)],
            ),
            child: Row(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Icon(Icons.favorite, color: doodleColor, size: 20),
                const SizedBox(width: 8),
                Flexible(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      FittedBox(fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text('PREFERITI', style: getLobbyTextStyle(themeType, TextStyle(color: doodleColor, fontWeight: FontWeight.w900, fontSize: 12, letterSpacing: 1.0)))),
                      FittedBox(fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text('Invita amico', style: getLobbyTextStyle(themeType, TextStyle(color: doodleColor.withOpacity(0.8), fontSize: 9, fontWeight: FontWeight.bold)))),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      );
    }

    return GestureDetector(
      onTap: onTap,
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeInOut,
        padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8),
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(15),
          gradient: LinearGradient(
            begin: Alignment.topLeft,
            end: Alignment.bottomRight,
            colors: [Colors.pinkAccent.withOpacity(0.25), Colors.pinkAccent.withOpacity(0.05)],
          ),
          border: Border.all(color: Colors.pinkAccent, width: 1.5),
          boxShadow: [BoxShadow(color: Colors.pinkAccent.withOpacity(0.3), blurRadius: 15, spreadRadius: 2)],
        ),
        child: Row(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Icon(Icons.favorite, color: Colors.pinkAccent, size: 20),
            const SizedBox(width: 8),
            Flexible(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: [
                  FittedBox(fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text('PREFERITI', style: getLobbyTextStyle(themeType, const TextStyle(color: Colors.white, fontWeight: FontWeight.w900, fontSize: 11, letterSpacing: 1.5)))),
                  FittedBox(fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text('Invita amico', style: getLobbyTextStyle(themeType, TextStyle(color: Colors.pinkAccent.shade200, fontSize: 9, fontWeight: FontWeight.bold)))),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class NeonActionButton extends StatelessWidget {
  final String label;
  final Color color;
  final VoidCallback onTap;
  final ThemeColors theme;
  final AppThemeType themeType;

  const NeonActionButton({super.key, required this.label, required this.color, required this.onTap, required this.theme, required this.themeType});

  @override
  Widget build(BuildContext context) {
    if (themeType == AppThemeType.doodle) {
      double tilt = (label == "UNISCITI" || label == "ANNULLA") ? -0.015 : 0.02;
      return Transform.rotate(
        angle: tilt,
        child: GestureDetector(
          onTap: onTap,
          child: Container(
            height: 50,
            decoration: BoxDecoration(
              color: color,
              borderRadius: const BorderRadius.only(
                topLeft: Radius.circular(10), topRight: Radius.circular(20),
                bottomLeft: Radius.circular(25), bottomRight: Radius.circular(10),
              ),
              border: Border.all(color: theme.text, width: 3.0),
              boxShadow: [BoxShadow(color: theme.text.withOpacity(0.9), offset: const Offset(4, 4), blurRadius: 0)],
            ),
            child: Center(
              child: FittedBox(
                fit: BoxFit.scaleDown,
                child: Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 10.0),
                  child: Text(label, style: getLobbyTextStyle(themeType, const TextStyle(fontSize: 20, fontWeight: FontWeight.w900, letterSpacing: 3.0, color: Colors.white))),
                ),
              ),
            ),
          ),
        ),
      );
    }

    return GestureDetector(
      onTap: onTap,
      child: Container(
        height: 50,
        decoration: BoxDecoration(
          gradient: LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [color.withOpacity(0.9), color.withOpacity(0.6)]),
          borderRadius: BorderRadius.circular(15),
          border: Border.all(color: Colors.white.withOpacity(0.3), width: 1.5),
          boxShadow: [
            BoxShadow(color: Colors.black.withOpacity(0.5), offset: const Offset(4, 8), blurRadius: 12),
            BoxShadow(color: color.withOpacity(0.3), offset: const Offset(0, 0), blurRadius: 15, spreadRadius: 1),
          ],
        ),
        child: Center(
          child: FittedBox(
            fit: BoxFit.scaleDown,
            child: Padding(
              padding: const EdgeInsets.symmetric(horizontal: 10.0),
              child: Text(label, style: getLobbyTextStyle(themeType, const TextStyle(fontSize: 16, fontWeight: FontWeight.w900, letterSpacing: 2.0, color: Colors.white, shadows: [Shadow(color: Colors.black, blurRadius: 2, offset: Offset(1, 1))]))),
            ),
          ),
        ),
      ),
    );
  }
}
// ===========================================================================
// FILE: lib/ui/settings/settings_screen.dart
// ===========================================================================

// ===========================================================================
// FILE: lib/ui/settings/settings_screen.dart
// ===========================================================================

import 'dart:ui'; // <--- IMPORTANTE: Aggiunto per ImageFilter.blur
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../core/theme_manager.dart';
import '../../core/app_colors.dart';
import '../../services/storage_service.dart';
import '../../widgets/painters.dart';

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

  @override
  State<SettingsScreen> createState() => _SettingsScreenState();
}

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

    int playerLevel = StorageService.instance.playerLevel;

    final double screenHeight = MediaQuery.of(context).size.height;
    final double vScale = (screenHeight / 920.0).clamp(0.7, 1.2);

    return Scaffold(
      backgroundColor: theme.background,
      extendBodyBehindAppBar: true,
      appBar: AppBar(
        toolbarHeight: 80 * vScale,
        title: Container(
          padding: EdgeInsets.symmetric(horizontal: 24 * vScale, vertical: 10 * vScale),
          decoration: BoxDecoration(
            gradient: LinearGradient(
              begin: Alignment.topLeft,
              end: Alignment.bottomRight,
              colors: [
                Colors.white.withOpacity(0.3),
                Colors.white.withOpacity(0.05),
              ],
            ),
            borderRadius: BorderRadius.circular(15),
            border: Border.all(color: Colors.white.withOpacity(0.5), width: 1.5),
            boxShadow: [
              BoxShadow(
                color: Colors.black.withOpacity(0.2),
                blurRadius: 10,
                offset: const Offset(0, 4),
              )
            ],
          ),
          child: Text(
              "SELEZIONA TEMA",
              style: getSharedTextStyle(themeType, TextStyle(
                  fontWeight: FontWeight.w900,
                  color: Colors.white,
                  letterSpacing: 2.0,
                  fontSize: 20 * vScale,
                  shadows: [Shadow(color: Colors.black.withOpacity(0.8), blurRadius: 5, offset: const Offset(2, 2))]
              ))
          ),
        ),
        centerTitle: true,
        backgroundColor: Colors.transparent,
        elevation: 0,
        iconTheme: IconThemeData(color: Colors.white, size: 28 * vScale),
      ),
      body: Stack(
        children: [
          Container(color: themeType == AppThemeType.doodle ? Colors.white : theme.background),

          Positioned.fill(
            child: Container(
              decoration: BoxDecoration(
                image: DecorationImage(
                  image: const AssetImage('assets/images/sfondo_temi.jpg'),
                  fit: BoxFit.cover,
                  colorFilter: ColorFilter.mode(Colors.black.withOpacity(0.6), BlendMode.darken),
                ),
              ),
            ),
          ),

          ListView(
            padding: EdgeInsets.only(top: 120 * vScale, left: 20 * vScale, right: 20 * vScale, bottom: 40 * vScale),
            physics: const BouncingScrollPhysics(),
            children: [
              _ThemeCard(
                title: "Quaderno",
                subtitle: "Sfondo a quadretti, tratto a penna",
                type: AppThemeType.doodle,
                previewColors: AppColors.doodle,
                requiredLevel: 1,
                currentLevel: playerLevel,
                vScale: vScale,
              ),
              SizedBox(height: 25 * vScale),
              _ThemeCard(
                title: "Cyberpunk",
                subtitle: "Nero profondo, luci al neon",
                type: AppThemeType.cyberpunk,
                previewColors: AppColors.cyberpunk,
                requiredLevel: 3,
                currentLevel: playerLevel,
                vScale: vScale,
              ),
              SizedBox(height: 25 * vScale),
              _ThemeCard(
                title: "8-Bit Arcade",
                subtitle: "Sale giochi, fosfori verdi e pixel",
                type: AppThemeType.arcade,
                previewColors: AppColors.arcade,
                requiredLevel: 7,
                currentLevel: playerLevel,
                vScale: vScale,
              ),
              SizedBox(height: 25 * vScale),
              _ThemeCard(
                title: "Grimorio",
                subtitle: "Incantesimi antichi, rune magiche",
                type: AppThemeType.grimorio,
                previewColors: AppColors.grimorio,
                requiredLevel: 10,
                currentLevel: playerLevel,
                vScale: vScale,
              ),
              SizedBox(height: 25 * vScale),
              _ThemeCard(
                title: "Musica",
                subtitle: "Vinili, cassette e vibrazioni sonore",
                type: AppThemeType.music,
                previewColors: AppColors.music,
                requiredLevel: 15,
                currentLevel: playerLevel,
                vScale: vScale,
              ),
              SizedBox(height: 40 * vScale),
            ],
          ),
        ],
      ),
    );
  }
}

class _ThemeCard extends StatelessWidget {
  final String title;
  final String subtitle;
  final AppThemeType type;
  final ThemeColors previewColors;
  final int requiredLevel;
  final int currentLevel;
  final double vScale;

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

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

    String? bgImage;
    if (type == AppThemeType.doodle) bgImage = 'assets/images/doodle_bg.jpg';
    if (type == AppThemeType.cyberpunk) bgImage = 'assets/images/cyber_bg.jpg';
    if (type == AppThemeType.music) bgImage = 'assets/images/music_bg.jpg';
    if (type == AppThemeType.arcade) bgImage = 'assets/images/arcade.jpg';
    if (type == AppThemeType.grimorio) bgImage = 'assets/images/grimorio.jpg';

    Border border;
    List<BoxShadow> shadows = [
      BoxShadow(color: Colors.black.withOpacity(0.8), offset: const Offset(0, 10), blurRadius: 15)
    ];

    if (type == AppThemeType.doodle) {
      border = Border.all(color: isSelected ? previewColors.playerBlue : const Color(0xFF111122).withOpacity(0.8), width: isSelected ? 4 : 2);
      if (isSelected) shadows.add(const BoxShadow(color: Color(0xFF111122), offset: Offset(4, 5)));
    } else if (type == AppThemeType.cyberpunk || type == AppThemeType.music) {
      border = Border.all(color: isSelected ? previewColors.playerBlue : previewColors.gridLine.withOpacity(0.8), width: isSelected ? 3 : 1.5);
      if (isSelected) shadows.add(BoxShadow(color: previewColors.playerBlue.withOpacity(0.8), blurRadius: 25, spreadRadius: 3));
    } else if (type == AppThemeType.arcade) {
      border = Border.all(color: isSelected ? previewColors.gridLine : Colors.white54, width: isSelected ? 4 : 2);
      if (isSelected) shadows.add(BoxShadow(color: previewColors.gridLine.withOpacity(0.5), offset: const Offset(4, 4)));
    } else {
      border = Border.all(color: isSelected ? Colors.amber : previewColors.gridLine.withOpacity(0.8), width: isSelected ? 3 : 1.5);
      if (isSelected) shadows.add(BoxShadow(color: Colors.amber.withOpacity(0.6), blurRadius: 20));
    }

    return GestureDetector(
      onTap: () {
        if (isLocked) {
          ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(
                content: Text("Gioca per raggiungere il Liv. $requiredLevel e sbloccare questo tema!", style: const TextStyle(fontWeight: FontWeight.bold, color: Colors.white)),
                backgroundColor: Colors.redAccent,
                behavior: SnackBarBehavior.floating,
                shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
                duration: const Duration(seconds: 2),
              )
          );
          return;
        }
        themeManager.setTheme(type);
        Navigator.pop(context);
      },
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 300),
        height: 140 * vScale,
        padding: EdgeInsets.symmetric(horizontal: 20 * vScale, vertical: 15 * vScale),
        decoration: BoxDecoration(
          color: isLocked ? Colors.black87 : previewColors.background,
          borderRadius: BorderRadius.circular(20),
          border: border,
          boxShadow: shadows,
          image: bgImage != null ? DecorationImage(
            image: AssetImage(bgImage!),
            fit: BoxFit.cover,
            colorFilter: type == AppThemeType.doodle
                ? ColorFilter.mode(Colors.white.withOpacity(isLocked ? 0.9 : 0.4), BlendMode.lighten)
                : ColorFilter.mode(Colors.black.withOpacity(isLocked ? 0.85 : 0.5), BlendMode.darken),
          ) : null,
        ),
        child: Stack(
          alignment: Alignment.center,
          children: [
            Opacity(
              opacity: isLocked ? 0.3 : 1.0,
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  Expanded(
                    // --- CORNICE EFFETTO VETRO (GLASSMORPHISM) ---
                    child: ClipRRect(
                      borderRadius: BorderRadius.circular(12),
                      child: BackdropFilter(
                        filter: ImageFilter.blur(sigmaX: 6.0, sigmaY: 6.0),
                        child: Container(
                          padding: EdgeInsets.symmetric(horizontal: 15 * vScale, vertical: 10 * vScale),
                          decoration: BoxDecoration(
                            gradient: LinearGradient(
                              begin: Alignment.topLeft,
                              end: Alignment.bottomRight,
                              colors: [
                                Colors.white.withOpacity(0.5), // Più visibile in alto a sx
                                Colors.white.withOpacity(0.1), // Quasi trasparente in basso a dx
                              ],
                            ),
                            borderRadius: BorderRadius.circular(12),
                            border: Border.all(color: Colors.white.withOpacity(0.3), width: 1.5),
                          ),
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            mainAxisAlignment: MainAxisAlignment.center,
                            mainAxisSize: MainAxisSize.min,
                            children: [
                              FittedBox(
                                fit: BoxFit.scaleDown,
                                alignment: Alignment.centerLeft,
                                child: Text(
                                    title,
                                    style: getSharedTextStyle(
                                        type,
                                        TextStyle(
                                          fontSize: (type == AppThemeType.arcade ? 15 : 22) * vScale,
                                          fontWeight: FontWeight.w900,
                                          color: const Color(0xFF111122),
                                          letterSpacing: type == AppThemeType.music ? 1.5 : 0.5,
                                        )
                                    )
                                ),
                              ),
                              SizedBox(height: 4 * vScale),
                              FittedBox(
                                fit: BoxFit.scaleDown,
                                alignment: Alignment.centerLeft,
                                child: Text(
                                    subtitle,
                                    style: getSharedTextStyle(
                                        type,
                                        TextStyle(
                                          fontSize: (type == AppThemeType.arcade ? 8 : 12) * vScale,
                                          color: const Color(0xFF333344),
                                          fontWeight: FontWeight.bold,
                                        )
                                    )
                                ),
                              ),
                            ],
                          ),
                        ),
                      ),
                    ),
                  ),
                  SizedBox(width: 15 * vScale),
                  Container(
                      width: 28 * vScale, height: 28 * vScale,
                      decoration: BoxDecoration(
                          color: previewColors.playerRed,
                          shape: type == AppThemeType.arcade ? BoxShape.rectangle : BoxShape.circle,
                          border: Border.all(color: Colors.white, width: 2),
                          boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.5), blurRadius: 5, offset: const Offset(1, 2))]
                      )
                  ),
                  SizedBox(width: 12 * vScale),
                  Container(
                      width: 28 * vScale, height: 28 * vScale,
                      decoration: BoxDecoration(
                          color: previewColors.playerBlue,
                          shape: type == AppThemeType.arcade ? BoxShape.rectangle : BoxShape.circle,
                          border: Border.all(color: Colors.white, width: 2),
                          boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.5), blurRadius: 5, offset: const Offset(1, 2))]
                      )
                  ),
                ],
              ),
            ),
            if (isLocked)
              Container(
                padding: EdgeInsets.symmetric(horizontal: 16 * vScale, vertical: 10 * vScale),
                decoration: BoxDecoration(
                  color: Colors.black.withOpacity(0.95),
                  borderRadius: BorderRadius.circular(20),
                  border: Border.all(color: previewColors.playerRed.withOpacity(0.8), width: 2),
                  boxShadow: [BoxShadow(color: previewColors.playerRed.withOpacity(0.5), blurRadius: 20)],
                ),
                child: Row(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Icon(Icons.lock_rounded, color: Colors.white, size: 20 * vScale),
                    SizedBox(width: 8 * vScale),
                    Text(
                        "LIV. $requiredLevel",
                        style: getSharedTextStyle(type, TextStyle(color: Colors.white, fontWeight: FontWeight.w900, fontSize: 16 * vScale, letterSpacing: 2))
                    ),
                  ],
                ),
              ),
          ],
        ),
      ),
    );
  }
}
// ===========================================================================
// FILE: lib/widgets/custom_button.dart
// ===========================================================================


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

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

import 'package:flutter/material.dart';
import '../core/app_colors.dart';
import 'painters.dart'; // Importiamo i painter per i doodle e il font

class NeonShapeButton extends StatelessWidget {
  final IconData icon; final String label; final bool isSelected;
  final ThemeColors theme; final AppThemeType themeType; final VoidCallback onTap;
  final bool isLocked; final bool isSpecial;

  const NeonShapeButton({super.key, required this.icon, required this.label, required this.isSelected, required this.theme, required this.themeType, required this.onTap, this.isLocked = false, this.isSpecial = false});

  Color _getDoodleColor() {
    switch (label) {
      case 'Rombo': return Colors.lightBlue.shade200;
      case 'Croce': return Colors.green.shade200;
      case 'Buco': return Colors.pink.shade200;
      case 'Clessidra': return Colors.purple.shade200;
      case 'Caos': return Colors.grey.shade300;
      default: return Colors.lightBlue.shade200;
    }
  }

  @override
  Widget build(BuildContext context) {
    if (themeType == AppThemeType.doodle) {
      Color doodleColor = isLocked ? Colors.grey : _getDoodleColor();
      Color inkColor = const Color(0xFF111122);
      double tilt = (label.length % 2 == 0) ? -0.05 : 0.04;

      return Transform.rotate(
        angle: tilt,
        child: GestureDetector(
          onTap: isLocked ? null : onTap,
          child: CustomPaint(
            painter: DoodleBackgroundPainter(fillColor: isSelected ? doodleColor : Colors.white.withOpacity(0.8), strokeColor: inkColor, seed: label.length * 3),
            child: Container(
              padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Icon(isLocked ? Icons.lock : icon, color: inkColor, size: 24),
                  const SizedBox(height: 2),
                  Text(isLocked ? "Liv. 10" : label, style: getSharedTextStyle(themeType, TextStyle(color: inkColor, fontSize: 11, fontWeight: FontWeight.w900, letterSpacing: 0.5))),
                ],
              ),
            ),
          ),
        ),
      );
    }

    Color mainColor = isSpecial && !isLocked ? Colors.purpleAccent : theme.playerBlue;
    return GestureDetector(
      onTap: isLocked ? null : onTap,
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 250), curve: Curves.easeOutCubic, padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12), transform: Matrix4.translationValues(0, isSelected ? 2 : 0, 0),
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(15), border: Border.all(color: isLocked ? Colors.transparent : (isSelected ? mainColor : Colors.white.withOpacity(0.1)), width: isSelected ? 2 : 1),
          gradient: LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: isLocked ? [Colors.grey.withOpacity(0.1), Colors.black.withOpacity(0.2)] : isSelected ? [mainColor.withOpacity(0.3), mainColor.withOpacity(0.1)] : [theme.text.withOpacity(0.1), theme.text.withOpacity(0.02)]),
          boxShadow: isLocked ? [] : isSelected ? [BoxShadow(color: mainColor.withOpacity(0.5), blurRadius: 15, spreadRadius: 1, offset: const Offset(0, 0))] : [BoxShadow(color: Colors.black.withOpacity(0.4), blurRadius: 6, offset: const Offset(2, 4)), BoxShadow(color: Colors.white.withOpacity(0.05), blurRadius: 2, offset: const Offset(-1, -1))],
        ),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(isLocked ? Icons.lock : icon, color: isLocked ? Colors.grey.withOpacity(0.5) : (isSelected ? Colors.white : theme.text.withOpacity(0.6)), size: 24),
            const SizedBox(height: 6),
            Text(isLocked ? "Liv. 10" : label, style: getSharedTextStyle(themeType, TextStyle(color: isLocked ? Colors.grey.withOpacity(0.5) : (isSelected ? Colors.white : theme.text.withOpacity(0.6)), fontSize: 11, fontWeight: isSelected ? FontWeight.w900 : FontWeight.bold))),
          ],
        ),
      ),
    );
  }
}

class NeonSizeButton extends StatelessWidget {
  final String label; final bool isSelected; final ThemeColors theme; final AppThemeType themeType; final VoidCallback onTap;
  const NeonSizeButton({super.key, required this.label, required this.isSelected, required this.theme, required this.themeType, required this.onTap});

  @override
  Widget build(BuildContext context) {
    if (themeType == AppThemeType.doodle) {
      Color doodleColor = label == 'MAX' ? Colors.red.shade200 : Colors.cyan.shade100; Color inkColor = const Color(0xFF111122); double tilt = (label == 'M' || label == 'MAX') ? 0.05 : -0.04;
      return Transform.rotate(
        angle: tilt,
        child: GestureDetector(
          onTap: onTap,
          child: CustomPaint(painter: DoodleBackgroundPainter(fillColor: isSelected ? doodleColor : Colors.white.withOpacity(0.8), strokeColor: inkColor, seed: label.codeUnitAt(0), isCircle: true), child: SizedBox(width: 50, height: 50, child: Center(child: Text(label, style: getSharedTextStyle(themeType, TextStyle(color: inkColor, fontSize: 18, fontWeight: FontWeight.w900)))))),
        ),
      );
    }
    return GestureDetector(
      onTap: onTap,
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 250), curve: Curves.easeOutCubic, width: 50, height: 50, transform: Matrix4.translationValues(0, isSelected ? 2 : 0, 0),
        decoration: BoxDecoration(
          shape: BoxShape.circle, border: Border.all(color: isSelected ? theme.playerRed : Colors.white.withOpacity(0.1), width: isSelected ? 2 : 1),
          gradient: LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: isSelected ? [theme.playerRed.withOpacity(0.3), theme.playerRed.withOpacity(0.1)] : [theme.text.withOpacity(0.1), theme.text.withOpacity(0.02)]),
          boxShadow: isSelected ? [BoxShadow(color: theme.playerRed.withOpacity(0.5), blurRadius: 15, spreadRadius: 1)] : [BoxShadow(color: Colors.black.withOpacity(0.4), blurRadius: 6, offset: const Offset(2, 4)), BoxShadow(color: Colors.white.withOpacity(0.05), blurRadius: 2, offset: const Offset(-1, -1))],
        ),
        child: Center(child: Text(label, style: getSharedTextStyle(themeType, TextStyle(color: isSelected ? Colors.white : theme.text.withOpacity(0.6), fontSize: 14, fontWeight: isSelected ? FontWeight.w900 : FontWeight.bold)))),
      ),
    );
  }
}

class NeonTimeSwitch extends StatelessWidget {
  final bool isTimeMode; final ThemeColors theme; final AppThemeType themeType; final VoidCallback onTap;
  const NeonTimeSwitch({super.key, required this.isTimeMode, required this.theme, required this.themeType, required this.onTap});

  @override
  Widget build(BuildContext context) {
    if (themeType == AppThemeType.doodle) {
      Color doodleColor = Colors.orange.shade200; Color inkColor = const Color(0xFF111122);
      return Transform.rotate(
        angle: -0.015,
        child: GestureDetector(
          onTap: onTap,
          child: CustomPaint(
            painter: DoodleBackgroundPainter(fillColor: isTimeMode ? doodleColor : Colors.white.withOpacity(0.8), strokeColor: inkColor, seed: 42),
            child: Container(
              padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
              child: Row(
                mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Icon(isTimeMode ? Icons.timer : Icons.timer_off, color: inkColor, size: 28), const SizedBox(width: 12),
                  Column(crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [Text(isTimeMode ? 'A TEMPO' : 'RELAX', style: getSharedTextStyle(themeType, TextStyle(color: inkColor, fontWeight: FontWeight.w900, fontSize: 16, letterSpacing: 2.0))), Text(isTimeMode ? '15 sec a mossa' : 'Nessun limite', style: getSharedTextStyle(themeType, TextStyle(color: inkColor.withOpacity(0.8), fontSize: 13, fontWeight: FontWeight.bold)))]),
                ],
              ),
            ),
          ),
        ),
      );
    }
    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), border: Border.all(color: isTimeMode ? Colors.amber : Colors.white.withOpacity(0.1), width: isTimeMode ? 2 : 1),
          gradient: LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: isTimeMode ? [Colors.amber.withOpacity(0.25), Colors.amber.withOpacity(0.05)] : [theme.text.withOpacity(0.1), theme.text.withOpacity(0.02)]),
          boxShadow: isTimeMode ? [BoxShadow(color: Colors.amber.withOpacity(0.3), blurRadius: 15, spreadRadius: 2)] : [BoxShadow(color: Colors.black.withOpacity(0.4), blurRadius: 6, offset: const Offset(2, 4)), BoxShadow(color: Colors.white.withOpacity(0.05), blurRadius: 2, offset: const Offset(-1, -1))],
        ),
        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: getSharedTextStyle(themeType, TextStyle(color: isTimeMode ? Colors.white : theme.text.withOpacity(0.5), fontWeight: FontWeight.w900, fontSize: 14, letterSpacing: 1.5))), Text(isTimeMode ? '15 sec a mossa' : 'Nessun limite', style: getSharedTextStyle(themeType, TextStyle(color: isTimeMode ? Colors.amber.shade200 : theme.text.withOpacity(0.4), fontSize: 11, fontWeight: FontWeight.bold)))]),
          ],
        ),
      ),
    );
  }
}

class NeonPrivacySwitch extends StatelessWidget {
  final bool isPublic;
  final ThemeColors theme;
  final AppThemeType themeType;
  final VoidCallback onTap;

  const NeonPrivacySwitch({super.key, required this.isPublic, required this.theme, required this.themeType, required this.onTap});

  @override
  Widget build(BuildContext context) {
    if (themeType == AppThemeType.doodle) {
      Color doodleColor = isPublic ? Colors.green.shade600 : Colors.red.shade600;
      return Transform.rotate(
        angle: 0.015,
        child: GestureDetector(
          onTap: onTap,
          child: AnimatedContainer(
            duration: const Duration(milliseconds: 200),
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
            transform: Matrix4.translationValues(0, isPublic ? 3 : 0, 0),
            decoration: BoxDecoration(
              color: isPublic ? doodleColor : Colors.white,
              borderRadius: const BorderRadius.only(
                topLeft: Radius.circular(15), topRight: Radius.circular(8),
                bottomLeft: Radius.circular(6), bottomRight: Radius.circular(15),
              ),
              border: Border.all(color: isPublic ? theme.text : doodleColor.withOpacity(0.5), width: 2.5),
              boxShadow: [BoxShadow(color: isPublic ? theme.text.withOpacity(0.8) : doodleColor.withOpacity(0.2), offset: const Offset(4, 5), blurRadius: 0)],
            ),
            child: Row(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Icon(isPublic ? Icons.public : Icons.lock, color: isPublic ? Colors.white : doodleColor, size: 20),
                const SizedBox(width: 8),
                Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Text(isPublic ? 'PUBBLICA' : 'PRIVATA', style: getSharedTextStyle(themeType, TextStyle(color: isPublic ? Colors.white : doodleColor, fontWeight: FontWeight.w900, fontSize: 12, letterSpacing: 1.0))),
                    Text(isPublic ? 'In Bacheca' : 'Solo Codice', style: getSharedTextStyle(themeType, TextStyle(color: isPublic ? Colors.white : doodleColor.withOpacity(0.8), fontSize: 9, fontWeight: FontWeight.bold))),
                  ],
                ),
              ],
            ),
          ),
        ),
      );
    }

    return GestureDetector(
      onTap: onTap,
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeInOut,
        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(15),
          gradient: LinearGradient(
            begin: Alignment.topLeft,
            end: Alignment.bottomRight,
            colors: isPublic
                ? [Colors.greenAccent.withOpacity(0.25), Colors.greenAccent.withOpacity(0.05)]
                : [theme.playerRed.withOpacity(0.25), theme.playerRed.withOpacity(0.05)],
          ),
          border: Border.all(color: isPublic ? Colors.greenAccent : theme.playerRed, width: isPublic ? 2 : 1),
          boxShadow: isPublic
              ? [BoxShadow(color: Colors.greenAccent.withOpacity(0.3), blurRadius: 15, spreadRadius: 2)]
              : [BoxShadow(color: Colors.black.withOpacity(0.4), blurRadius: 6, offset: const Offset(2, 4))],
        ),
        child: Row(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(isPublic ? Icons.public : Icons.lock, color: isPublic ? Colors.greenAccent : theme.playerRed, size: 20),
            const SizedBox(width: 8),
            Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisSize: MainAxisSize.min,
              children: [
                Text(isPublic ? 'PUBBLICA' : 'PRIVATA', style: getSharedTextStyle(themeType, TextStyle(color: isPublic ? Colors.white : theme.text.withOpacity(0.8), fontWeight: FontWeight.w900, fontSize: 11, letterSpacing: 1.5))),
                Text(isPublic ? 'Tutti ti vedono' : 'Solo con Codice', style: getSharedTextStyle(themeType, TextStyle(color: isPublic ? Colors.greenAccent.shade200 : theme.playerRed.withOpacity(0.7), fontSize: 9, fontWeight: FontWeight.bold))),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

class NeonActionButton extends StatelessWidget {
  final String label;
  final Color color;
  final VoidCallback onTap;
  final ThemeColors theme;
  final AppThemeType themeType;

  const NeonActionButton({super.key, required this.label, required this.color, required this.onTap, required this.theme, required this.themeType});

  @override
  Widget build(BuildContext context) {
    if (themeType == AppThemeType.doodle) {
      double tilt = (label == "UNISCITI" || label == "ANNULLA") ? -0.015 : 0.02;
      return Transform.rotate(
        angle: tilt,
        child: GestureDetector(
          onTap: onTap,
          child: Container(
            height: 50,
            decoration: BoxDecoration(
              color: color,
              borderRadius: const BorderRadius.only(
                topLeft: Radius.circular(10), topRight: Radius.circular(20),
                bottomLeft: Radius.circular(25), bottomRight: Radius.circular(10),
              ),
              border: Border.all(color: theme.text, width: 3.0),
              boxShadow: [BoxShadow(color: theme.text.withOpacity(0.9), offset: const Offset(4, 4), blurRadius: 0)],
            ),
            child: Center(
              child: FittedBox(
                fit: BoxFit.scaleDown,
                child: Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 10.0),
                  child: Text(label, style: getSharedTextStyle(themeType, TextStyle(fontSize: 20, fontWeight: FontWeight.w900, letterSpacing: 3.0, color: Colors.white))),
                ),
              ),
            ),
          ),
        ),
      );
    }

    return GestureDetector(
      onTap: onTap,
      child: Container(
        height: 50,
        decoration: BoxDecoration(
          gradient: LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [color.withOpacity(0.9), color.withOpacity(0.6)]),
          borderRadius: BorderRadius.circular(15),
          border: Border.all(color: Colors.white.withOpacity(0.3), width: 1.5),
          boxShadow: [
            BoxShadow(color: Colors.black.withOpacity(0.5), offset: const Offset(4, 8), blurRadius: 12),
            BoxShadow(color: color.withOpacity(0.3), offset: const Offset(0, 0), blurRadius: 15, spreadRadius: 1),
          ],
        ),
        child: Center(
          child: FittedBox(
            fit: BoxFit.scaleDown,
            child: Padding(
              padding: const EdgeInsets.symmetric(horizontal: 10.0),
              child: Text(label, style: getSharedTextStyle(themeType, const TextStyle(fontSize: 16, fontWeight: FontWeight.w900, letterSpacing: 2.0, color: Colors.white, shadows: [Shadow(color: Colors.black, blurRadius: 2, offset: Offset(1, 1))]))),
            ),
          ),
        ),
      ),
    );
  }
}
// ===========================================================================
// FILE: lib/widgets/cyber_border.dart
// ===========================================================================

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../core/theme_manager.dart'; // Import aggiornato
import 'dart:math' as math;

class AnimatedCyberBorder extends StatefulWidget {
  final Widget child;
  const AnimatedCyberBorder({super.key, 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(15), 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(15));
    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/widgets/game_over_dialog.dart
// ===========================================================================

// ===========================================================================
// 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';
import '../services/storage_service.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;

    String myName = StorageService.instance.playerName.toUpperCase();
    if (myName.isEmpty) myName = "TU";

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

    if (game.isOnline) {
      nameRed = game.onlineHostName.toUpperCase();
      nameBlue = game.onlineGuestName.toUpperCase();
    } else if (game.isVsCPU) {
      nameRed = myName;
      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: SingleChildScrollView(
        physics: const BouncingScrollPhysics(),
        child: 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))),
            ],

            // --- SEZIONE LEVEL UP E ROADMAP DINAMICA ---
            if (game.hasLeveledUp && game.unlockedRewards.isNotEmpty) ...[
              const SizedBox(height: 30),
              const Divider(),
              const SizedBox(height: 15),
              Container(
                padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 20),
                decoration: BoxDecoration(
                    color: Colors.amber.withOpacity(0.2),
                    borderRadius: BorderRadius.circular(30),
                    border: Border.all(color: Colors.amber, width: 2)
                ),
                child: Text("🎉 LIVELLO ${game.newlyReachedLevel}! 🎉", style: const TextStyle(color: Colors.amber, fontWeight: FontWeight.w900, fontSize: 18)),
              ),
              const SizedBox(height: 15),

              ...game.unlockedRewards.map((reward) => Container(
                  margin: const EdgeInsets.only(bottom: 10),
                  padding: const EdgeInsets.all(12),
                  decoration: BoxDecoration(
                    color: (reward['color'] as Color).withOpacity(0.1),
                    borderRadius: BorderRadius.circular(12),
                    border: Border.all(color: (reward['color'] as Color).withOpacity(0.5), width: 1.5),
                  ),
                  child: Row(
                      children: [
                        Container(
                          padding: const EdgeInsets.all(8),
                          decoration: BoxDecoration(
                            color: (reward['color'] as Color).withOpacity(0.2),
                            shape: BoxShape.circle,
                          ),
                          child: Icon(reward['icon'], color: reward['color'], size: 28),
                        ),
                        const SizedBox(width: 15),
                        Expanded(
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                Text(reward['title'], style: TextStyle(color: reward['color'], fontWeight: FontWeight.w900, fontSize: 16)),
                                const SizedBox(height: 4),
                                Text(reward['desc'], style: TextStyle(color: theme.text.withOpacity(0.9), fontSize: 12, height: 1.3)),
                              ],
                            )
                        )
                      ]
                  )
              )),
            ]
            // ---------------------------------------------
          ],
        ),
      ),
      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)),
            ),
          ],
        )
      ],
    );
  }
}
// ===========================================================================
// FILE: lib/widgets/home_buttons.dart
// ===========================================================================

import 'package:flutter/material.dart';
import '../core/app_colors.dart'; // Import aggiornato
import 'painters.dart';

class FeatureCard extends StatelessWidget {
  final String title;
  final String subtitle;
  final IconData icon;
  final Color color;
  final ThemeColors theme;
  final AppThemeType themeType;
  final VoidCallback onTap;
  final bool isFeatured;
  final bool compact;

  const FeatureCard({super.key, required this.title, required this.subtitle, required this.icon, required this.color, required this.theme, required this.themeType, required this.onTap, this.isFeatured = false, this.compact = false});

  @override
  Widget build(BuildContext context) {
    if (themeType == AppThemeType.doodle) {
      double tilt = (title.length % 2 == 0) ? -0.015 : 0.02;
      Color inkColor = const Color(0xFF111122);

      return Transform.rotate(
        angle: tilt,
        child: GestureDetector(
          onTap: onTap,
          child: CustomPaint(
            painter: DoodleBackgroundPainter(fillColor: color, strokeColor: inkColor, seed: title.length * 5),
            child: Padding(
              padding: EdgeInsets.symmetric(horizontal: compact ? 12.0 : 22.0, vertical: compact ? 12.0 : 16.0),
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  Icon(icon, color: inkColor, size: compact ? 24 : 32),
                  const SizedBox(width: 12),
                  Expanded(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        FittedBox(fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text(title, style: getSharedTextStyle(themeType, TextStyle(color: inkColor, fontSize: compact ? 16 : 24, fontWeight: FontWeight.w900)))),
                        if (!compact) ...[ const SizedBox(height: 2), Text(subtitle, style: getSharedTextStyle(themeType, TextStyle(color: inkColor.withOpacity(0.8), fontSize: 14, fontWeight: FontWeight.bold))) ]
                      ],
                    ),
                  ),
                  if (!compact) Icon(Icons.chevron_right_rounded, color: inkColor.withOpacity(0.6), size: 32),
                ],
              ),
            ),
          ),
        ),
      );
    }

    return GestureDetector(
      onTap: onTap,
      child: Container(
        padding: EdgeInsets.symmetric(horizontal: compact ? 12.0 : 20.0, vertical: compact ? 10.0 : 14.0),
        decoration: BoxDecoration(
            gradient: LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: isFeatured ? [color.withOpacity(0.9), color.withOpacity(0.6)] : [color.withOpacity(0.25), color.withOpacity(0.05)]),
            borderRadius: BorderRadius.circular(15), border: Border.all(color: color.withOpacity(isFeatured ? 0.5 : 0.2), width: 1.5),
            boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.6), offset: const Offset(0, 8), blurRadius: 15), BoxShadow(color: color.withOpacity(isFeatured ? 0.3 : 0.05), offset: const Offset(-1, -1), blurRadius: 5)]
        ),
        child: Row(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Container(
              padding: EdgeInsets.all(compact ? 6 : 10),
              decoration: BoxDecoration(gradient: LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [Colors.white.withOpacity(0.3), Colors.white.withOpacity(0.05)]), shape: BoxShape.circle, border: Border.all(color: Colors.white.withOpacity(0.2)), boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.2), blurRadius: 5, offset: const Offset(2, 4))]),
              child: Icon(icon, color: isFeatured ? Colors.white : color, size: compact ? 20 : 26),
            ),
            SizedBox(width: compact ? 10 : 20),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  FittedBox(fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text(title, style: getSharedTextStyle(themeType, TextStyle(color: isFeatured ? Colors.white : theme.text, fontSize: compact ? 14 : 18, fontWeight: FontWeight.w900, shadows: [Shadow(color: Colors.black.withOpacity(0.5), offset: const Offset(1, 2), blurRadius: 2)])))),
                  if (!compact) ...[ const SizedBox(height: 2), Text(subtitle, style: getSharedTextStyle(themeType, TextStyle(color: isFeatured ? Colors.white.withOpacity(0.8) : theme.text.withOpacity(0.6), fontSize: 12, fontWeight: FontWeight.bold))) ]
                ],
              ),
            ),
            if (!compact) Icon(Icons.chevron_right_rounded, color: isFeatured ? Colors.white.withOpacity(0.7) : color.withOpacity(0.5), size: 30),
          ],
        ),
      ),
    );
  }
}
// ===========================================================================
// FILE: lib/widgets/music_theme_widgets.dart
// ===========================================================================

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

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

class MusicCassetteCard extends StatelessWidget {
  final String title;
  final String subtitle;
  final Color neonColor;
  final double angle;
  final IconData leftIcon;
  final IconData rightIcon;
  final VoidCallback onTap;
  final AppThemeType themeType;

  const MusicCassetteCard({
    super.key,
    required this.title,
    required this.subtitle,
    required this.neonColor,
    required this.angle,
    required this.leftIcon,
    required this.rightIcon,
    required this.onTap,
    required this.themeType
  });

  @override
  Widget build(BuildContext context) {
    // Calcoliamo la scala in base all'altezza dello schermo per strizzare la cassetta
    final double screenHeight = MediaQuery.of(context).size.height;
    final double vScale = (screenHeight / 850.0).clamp(0.65, 1.0);

    return Transform.rotate(
      angle: angle,
      child: GestureDetector(
        onTap: onTap,
        child: Container(
          height: 125 * vScale, // Altezza dinamica!
          margin: EdgeInsets.symmetric(vertical: 8 * vScale, horizontal: 10),
          padding: EdgeInsets.all(12 * vScale),
          decoration: BoxDecoration(
              color: const Color(0xFF22222A),
              borderRadius: BorderRadius.circular(8),
              border: Border.all(color: Colors.black87, width: 2),
              boxShadow: [
                BoxShadow(color: neonColor.withOpacity(0.5), blurRadius: 25, spreadRadius: 2),
                const BoxShadow(color: Colors.black54, offset: Offset(5, 10), blurRadius: 15)
              ]
          ),
          child: Column(
            children: [
              Expanded(
                child: Container(
                  decoration: BoxDecoration(
                      color: neonColor.withOpacity(0.15),
                      borderRadius: BorderRadius.circular(4),
                      border: Border.all(color: neonColor.withOpacity(0.5), width: 1.5)
                  ),
                  child: Row(
                    children: [
                      Padding(
                          padding: EdgeInsets.symmetric(horizontal: 12 * vScale),
                          child: Icon(leftIcon, color: neonColor, size: 28 * vScale)
                      ),
                      Expanded(
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          mainAxisSize: MainAxisSize.min,
                          children: [
                            Flexible(
                                child: FittedBox(
                                    fit: BoxFit.scaleDown,
                                    child: Text(title, style: getSharedTextStyle(themeType, TextStyle(color: Colors.white, fontSize: 20 * vScale, fontWeight: FontWeight.w900, shadows: [Shadow(color: neonColor, blurRadius: 10)])))
                                )
                            ),
                            Flexible(
                                child: FittedBox(
                                    fit: BoxFit.scaleDown,
                                    child: Text(subtitle, style: getSharedTextStyle(themeType, TextStyle(color: Colors.white70, fontSize: 11 * vScale, fontWeight: FontWeight.bold)))
                                )
                            ),
                          ],
                        ),
                      ),
                      Padding(
                          padding: EdgeInsets.symmetric(horizontal: 12 * vScale),
                          child: Icon(rightIcon, color: neonColor, size: 28 * vScale)
                      ),
                    ],
                  ),
                ),
              ),
              SizedBox(height: 10 * vScale),
              Container(
                height: 35 * vScale,
                width: 180 * vScale,
                decoration: BoxDecoration(
                    color: const Color(0xFF0D0D12),
                    borderRadius: BorderRadius.circular(20),
                    border: Border.all(color: Colors.white24, width: 1)
                ),
                child: Stack(
                  alignment: Alignment.center,
                  children: [
                    Container(height: 2, width: 120 * vScale, color: const Color(0xFF333333)),
                    Row(
                        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                        children: [ _buildSpool(vScale), _buildSpool(vScale) ]
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildSpool(double vScale) {
    return Container(
      width: 26 * vScale,
      height: 26 * vScale,
      decoration: BoxDecoration(
          shape: BoxShape.circle,
          color: Colors.white70,
          border: Border.all(color: Colors.black87, width: 5 * vScale)
      ),
      child: Center(
          child: Container(
              width: 6 * vScale,
              height: 6 * vScale,
              decoration: const BoxDecoration(shape: BoxShape.circle, color: Colors.black)
          )
      ),
    );
  }
}

class MusicKnobCard extends StatelessWidget {
  final String title;
  final IconData icon;
  final VoidCallback onTap;
  final AppThemeType themeType;
  final Color? iconColor;

  const MusicKnobCard({
    super.key,
    required this.title,
    required this.icon,
    required this.onTap,
    required this.themeType,
    this.iconColor
  });

  @override
  Widget build(BuildContext context) {
    // Adattiamo anche le manopole in base all'altezza dello schermo
    final double screenHeight = MediaQuery.of(context).size.height;
    final double vScale = (screenHeight / 850.0).clamp(0.65, 1.0);

    return GestureDetector(
      onTap: onTap,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Container(
            width: 65 * vScale,
            height: 65 * vScale,
            decoration: BoxDecoration(
              shape: BoxShape.circle,
              color: const Color(0xFF222222),
              border: Border.all(color: const Color(0xFF111111), width: 2),
              boxShadow: const [
                BoxShadow(color: Colors.black87, blurRadius: 10, offset: Offset(2, 6)),
                BoxShadow(color: Colors.white12, blurRadius: 2, offset: Offset(-1, -1))
              ],
            ),
            child: Padding(
              padding: EdgeInsets.all(6.0 * vScale),
              child: Container(
                decoration: BoxDecoration(
                  shape: BoxShape.circle,
                  border: Border.all(color: Colors.black54, width: 1),
                  gradient: const SweepGradient(colors: [Color(0xFF555555), Color(0xFFAAAAAA), Color(0xFF555555), Color(0xFF222222), Color(0xFF555555)]),
                ),
                child: Padding(
                  padding: EdgeInsets.all(4.0 * vScale),
                  child: Container(
                    decoration: const BoxDecoration(shape: BoxShape.circle, color: Color(0xFF1A1A1A)),
                    child: Center(child: Icon(icon, color: iconColor ?? Colors.white70, size: 20 * vScale)),
                  ),
                ),
              ),
            ),
          ),
          SizedBox(height: 10 * vScale),
          FittedBox(
              fit: BoxFit.scaleDown,
              child: Text(title, style: getSharedTextStyle(themeType, TextStyle(color: Colors.white70, fontSize: 11 * vScale, fontWeight: FontWeight.bold, letterSpacing: 1.0)))
          ),
        ],
      ),
    );
  }
}
// ===========================================================================
// FILE: lib/widgets/painters.dart
// ===========================================================================

import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'dart:math' as math;
import '../core/app_colors.dart'; // Import aggiornato

TextStyle getSharedTextStyle(AppThemeType themeType, TextStyle baseStyle) {
  if (themeType == AppThemeType.doodle) {
    return GoogleFonts.permanentMarker(textStyle: baseStyle);
  } else if (themeType == AppThemeType.arcade) {
    return GoogleFonts.pressStart2p(textStyle: baseStyle.copyWith(fontSize: baseStyle.fontSize != null ? baseStyle.fontSize! * 0.75 : null, letterSpacing: 0.5));
  } else if (themeType == AppThemeType.grimorio) {
    return GoogleFonts.cinzelDecorative(textStyle: baseStyle.copyWith(fontWeight: FontWeight.bold));
  } else if (themeType == AppThemeType.music) {
    return GoogleFonts.audiowide(textStyle: baseStyle.copyWith(letterSpacing: 1.5));
  }
  return baseStyle;
}

class DoodleBackgroundPainter extends CustomPainter {
  final Color fillColor; final Color strokeColor; final int seed; final bool isCircle;
  DoodleBackgroundPainter({required this.fillColor, required this.strokeColor, required this.seed, this.isCircle = false});

  @override
  void paint(Canvas canvas, Size size) {
    final math.Random random = math.Random(seed);
    double wobble() => random.nextDouble() * 6 - 3;
    final Paint fillPaint = Paint()..color = fillColor..style = PaintingStyle.fill;
    final Paint strokePaint = Paint()..color = strokeColor..strokeWidth = 2.5..style = PaintingStyle.stroke..strokeCap = StrokeCap.round..strokeJoin = StrokeJoin.round;

    if (isCircle) {
      final Rect rect = Rect.fromLTWH(wobble(), wobble(), size.width + wobble(), size.height + wobble());
      canvas.save(); canvas.translate(wobble(), wobble()); canvas.drawOval(rect, fillPaint); canvas.restore();
      canvas.drawOval(rect, strokePaint);
      canvas.save(); canvas.translate(random.nextDouble() * 4 - 2, random.nextDouble() * 4 - 2); canvas.drawOval(rect, strokePaint..strokeWidth = 1.0..color = strokeColor.withOpacity(0.6)); canvas.restore();
    } else {
      final Path path = Path()..moveTo(wobble(), wobble())..lineTo(size.width + wobble(), wobble())..lineTo(size.width + wobble(), size.height + wobble())..lineTo(wobble(), size.height + wobble())..close();
      final Path fillPath = Path()..moveTo(wobble() * 1.5, wobble() * 1.5)..lineTo(size.width + wobble() * 1.5, wobble() * 1.5)..lineTo(size.width + wobble() * 1.5, size.height + wobble() * 1.5)..lineTo(wobble() * 1.5, size.height + wobble() * 1.5)..close();
      canvas.drawPath(fillPath, fillPaint);
      canvas.drawPath(path, strokePaint);
      canvas.save(); canvas.translate(random.nextDouble() * 3 - 1.5, random.nextDouble() * 3 - 1.5); canvas.drawPath(path, strokePaint..strokeWidth = 1.0..color = strokeColor.withOpacity(0.6)); canvas.restore();
    }
  }
  @override bool shouldRepaint(covariant DoodleBackgroundPainter oldDelegate) => oldDelegate.fillColor != fillColor || oldDelegate.strokeColor != strokeColor;
}

class AudioCablesPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()..color = const Color(0xFF151515)..style = PaintingStyle.stroke..strokeWidth = 8.0..strokeCap = StrokeCap.round;
    final highlight = Paint()..color = const Color(0xFF3A3A3A)..style = PaintingStyle.stroke..strokeWidth = 2.0..strokeCap = StrokeCap.round;
    void drawCable(Path path) { canvas.drawPath(path, paint); canvas.drawPath(path, highlight); }

    Path c1 = Path()..moveTo(-20, size.height * 0.2)..quadraticBezierTo(100, size.height * 0.25, 50, size.height * 0.4)..quadraticBezierTo(0, size.height * 0.5, -20, size.height * 0.55); drawCable(c1);
    Path c2 = Path()..moveTo(size.width + 20, size.height * 0.4)..quadraticBezierTo(size.width - 100, size.height * 0.5, size.width - 50, size.height * 0.7)..quadraticBezierTo(size.width, size.height * 0.8, size.width + 20, size.height * 0.85); drawCable(c2);
    Path c3 = Path()..moveTo(size.width * 0.2, size.height + 20)..quadraticBezierTo(size.width * 0.3, size.height - 80, size.width * 0.5, size.height - 60)..quadraticBezierTo(size.width * 0.7, size.height - 40, size.width * 0.8, size.height + 20); drawCable(c3);

    _drawJack(canvas, Offset(80, size.height * 0.38), -0.5);
    _drawJack(canvas, Offset(size.width - 60, size.height * 0.68), 0.8);
  }

  void _drawJack(Canvas canvas, Offset pos, double angle) {
    canvas.save(); canvas.translate(pos.dx, pos.dy); canvas.rotate(angle);
    canvas.drawRect(const Rect.fromLTWH(-15, -4, 15, 8), Paint()..color = const Color(0xFF151515));
    canvas.drawRRect(RRect.fromRectAndRadius(const Rect.fromLTWH(0, -6, 25, 12), const Radius.circular(2)), Paint()..color = const Color(0xFF222222));
    canvas.drawRRect(RRect.fromRectAndRadius(const Rect.fromLTWH(2, -4, 21, 8), const Radius.circular(2)), Paint()..color = const Color(0xFF444444));
    canvas.drawRect(const Rect.fromLTWH(25, -2, 15, 4), Paint()..color = const Color(0xFFCCCCCC));
    canvas.drawRect(const Rect.fromLTWH(40, -1.5, 5, 3), Paint()..color = const Color(0xFFAAAAAA));
    canvas.drawLine(const Offset(30, -2), const Offset(30, 2), Paint()..color = Colors.black..strokeWidth = 1.5);
    canvas.drawLine(const Offset(35, -2), const Offset(35, 2), Paint()..color = Colors.black..strokeWidth = 1.5);
    canvas.restore();
  }
  @override bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}