import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flux/core/blocs/session/session_cubit.dart';
import 'package:flux/core/data/core_repository.dart';
import 'package:flux/core/layout/app_shell.dart';
import 'package:flux/core/routes/routes.dart';
import 'package:flux/core/widgets/image_upload/blocs/image_upload_cubit.dart';
import 'package:flux/core/widgets/image_upload/ui/image_upload_screen.dart';
import 'package:flux/core/widgets/image_upload/ui/upload_success_screen.dart';
import 'package:flux/features/auth/ui/auth_screen.dart';
import 'package:flux/features/auth/ui/set_password_screen.dart';
import 'package:flux/features/company/bloc/company_settings_cubit.dart';
import 'package:flux/features/company/ui/company_settings_screen.dart';
import 'package:flux/features/customers/blocs/customer_form_cubit.dart';
import 'package:flux/features/customers/blocs/customers_list_cubit.dart';
import 'package:flux/features/customers/models/customer_model.dart';
import 'package:flux/features/customers/ui/customer_detail_screen.dart';
import 'package:flux/features/customers/ui/customer_form_screen.dart';
import 'package:flux/features/customers/ui/customers_list_screen.dart';
import 'package:flux/features/home/dashboard_note_list/blocs/dashboard_note_list_cubit.dart';
import 'package:flux/features/home/dashboard_store_operation_list/bloc/dashboard_store_operation_list_cubit.dart';
import 'package:flux/features/home/dashboard_store_ticket_list/blocs/dashboard_store_ticket_list_cubit.dart';
import 'package:flux/features/home/dashboard_task_list/blocs/dashboard_task_list_cubit.dart';
import 'package:flux/features/home/ui/home_screen.dart';
import 'package:flux/features/master_data/master_data_hub_content.dart';
import 'package:flux/features/master_data/products/blocs/product_cubit.dart';
import 'package:flux/features/master_data/products/ui/products_screen.dart';
import 'package:flux/features/master_data/providers/blocs/provider_form_cubit.dart';
import 'package:flux/features/master_data/providers/blocs/provider_list_cubit.dart';
import 'package:flux/features/master_data/providers/models/provider_model.dart';
import 'package:flux/features/master_data/providers/ui/provider_form_screen.dart';
import 'package:flux/features/master_data/providers/ui/provider_list_screen.dart';
import 'package:flux/features/master_data/staff/blocs/staff_cubit.dart';
import 'package:flux/features/master_data/staff/models/staff_member_model.dart';
import 'package:flux/features/master_data/staff/ui/staff_screen.dart';
import 'package:flux/features/master_data/store/bloc/store_cubit.dart';
import 'package:flux/features/master_data/store/ui/stores_screen.dart';
import 'package:flux/features/notes/models/note_model.dart';
import 'package:flux/features/notes/ui/notes_form_screen.dart';
import 'package:flux/features/notes/ui/notes_list_screen.dart';
import 'package:flux/features/onboarding/blocs/onboarding_cubit.dart';
import 'package:flux/features/onboarding/ui/onboarding_screen.dart';
import 'package:flux/features/attachments/blocs/attachments_bloc.dart';
import 'package:flux/features/operations/blocs/operation_form_cubit.dart';
import 'package:flux/features/operations/models/operation_model.dart';
import 'package:flux/features/operations/ui/operation_form_screen.dart';
import 'package:flux/features/operations/ui/operation_list_screen.dart';
import 'package:flux/features/settings/blocs/reminder_defaults_cubit.dart';
import 'package:flux/features/settings/ui/reminder_settings_screen.dart';
import 'package:flux/features/settings/ui/settings_screen.dart';
import 'package:flux/features/settings/ui/theme_settings_view.dart';
import 'package:flux/features/tasks/blocs/task_form_cubit.dart';
import 'package:flux/features/tasks/blocs/task_list_cubit.dart';
import 'package:flux/features/tasks/models/task_model.dart';
import 'package:flux/features/tasks/ui/task_form_screen.dart';
import 'package:flux/features/tasks/ui/task_list_screen.dart';
import 'package:flux/features/tickets/blocs/ticket_form_cubit.dart';
import 'package:flux/features/tickets/models/ticket_model.dart';
import 'package:flux/features/tickets/ui/ticket_form_screen.dart';
import 'package:flux/features/tickets/ui/ticket_list_screen.dart';
import 'package:flux/features/tickets/ui/ticket_workspace/ticket_workspace_screen.dart';
import 'package:flux/features/tracking/blocs/tracking_cubit.dart';
import 'package:flux/features/tracking/models/tracking_model.dart';
import 'package:get_it/get_it.dart';
import 'package:go_router/go_router.dart';

class AppRouter {
  // 1. CREIAMO LA CHIAVE GLOBALE DEL NAVIGATORE
  static final GlobalKey<NavigatorState> rootNavigatorKey =
      GlobalKey<NavigatorState>();
  static String? pendingRoute;
  static GoRouter createRouter(SessionCubit sessionCubit) {
    return GoRouter(
      navigatorKey: rootNavigatorKey,
      initialLocation: '/',
      refreshListenable: GoRouterRefreshStream(sessionCubit.stream),

      redirect: (context, state) {
        final sessionState = sessionCubit.state;
        final isGoingToLogin = state.matchedLocation == '/login';
        final isGoingToOnboarding = state.matchedLocation == '/onboarding';
        final isGoingToSetPassword = state.matchedLocation == '/set-password';

        // 1. LA PASSATOIA VIP (DEVE ESSERE IN CIMA)
        // Usiamo state.uri.path perché state.matchedLocation a volte fa i capricci coi deep link iniziali
        final isPublicRoute = state.uri.path.startsWith('/upload');

        if (isPublicRoute) {
          // Ritorna null esplicitamente per dire al router "Rimani qui e non fare altri controlli"
          return null;
        }

        // 2. CONTROLLO INIZIALE
        // Se la sessione sta ancora caricando la primissima volta (es. splash screen logico)
        if (sessionState.status == SessionStatus.initial) return null;

        // 3. UTENTE NON LOGGATO (Ma ci arriva solo se non è su /upload)
        if (sessionState.status == SessionStatus.unauthenticated) {
          // Se sta già andando alle uniche altre pagine pubbliche, lascialo andare
          if (isGoingToLogin || isGoingToSetPassword) return null;
          // Altrimenti bloccalo e mandalo al login
          return '/login';
        }

        // 4. UTENTE LOGGATO MA DEVE COMPLETARE L'ONBOARDING
        if (sessionState.status == SessionStatus.onboardingRequired) {
          return isGoingToOnboarding ? null : '/onboarding';
        }

        // 5. UTENTE PERFETTAMENTE LOGGATO E OPERATIVO
        if (sessionState.status == SessionStatus.authenticated) {
          // Se per sbaglio cerca di tornare al login o all'onboarding, ributtalo in dashboard
          if (isGoingToLogin || isGoingToOnboarding) return '/';
          return null;
        }

        return null;
      },
      routes: [
        // --- ROTTE DI SERVIZIO (FUORI DALLA SHELL) ---
        GoRoute(
          path: '/login',
          name: Routes.login,
          builder: (context, state) => const AuthScreen(),
        ),
        GoRoute(
          path: '/set-password',
          name: Routes.setPassword,
          builder: (context, state) => const SetPasswordScreen(),
        ),
        GoRoute(
          path: '/onboarding',
          name: Routes.onboarding,
          builder: (context, state) => BlocProvider(
            create: (context) => OnboardingCubit(
              GetIt.I.get<SessionCubit>(),
              GetIt.I.get<CoreRepository>(),
            ),
            child: const OnboardingScreen(),
          ),
        ),

        // --- CORE APP (DENTRO LA SHELL CON NAVIGATION BAR/RAIL) ---
        ShellRoute(
          builder: (context, state, child) => AppShell(child: child),
          routes: [
            // ==========================================
            // 1. DASHBOARD
            // ==========================================
            GoRoute(
              path: '/',
              name: Routes.home,
              builder: (context, state) {
                return MultiBlocProvider(
                  providers: [
                    BlocProvider<DashboardStoreOperationListCubit>(
                      create: (context) => DashboardStoreOperationListCubit(
                        companyId: sessionCubit.state.company?.id,
                        storeId: sessionCubit.state.currentStore?.id,
                      ),
                    ),
                    BlocProvider<DashboardTaskListCubit>(
                      create: (context) => DashboardTaskListCubit(
                        companyId: sessionCubit.state.company?.id,
                        staffId: sessionCubit.state.currentStaffMember?.id,
                      ),
                    ),
                    BlocProvider<DashboardStoreTicketListCubit>(
                      create: (context) => DashboardStoreTicketListCubit(
                        companyId: sessionCubit.state.company?.id,
                        storeId: sessionCubit.state.currentStore?.id,
                      ),
                    ),
                    BlocProvider<DashboardNoteListCubit>(
                      create: (context) => DashboardNoteListCubit(
                        companyId: sessionCubit.state.company?.id,
                        staffId: sessionCubit.state.currentStaffMember?.id,
                      ),
                    ),
                  ],
                  child: const HomeScreen(),
                );
              },
            ),

            // ==========================================
            // 2. HUB ANAGRAFICHE E SOTTO-ROTTE
            // ==========================================
            GoRoute(
              path: '/master-data',
              name: Routes.masterData,
              builder: (context, state) => const MasterDataHubScreen(),
              routes: [
                GoRoute(
                  path:
                      'customers', // Niente slash iniziale per le sottorotte! -> /master-data/customers
                  name: Routes.customers,
                  builder: (context, state) => const CustomersListScreen(),
                ),
                GoRoute(
                  path: 'providers', // -> /master-data/providers
                  name: Routes.providers,
                  builder: (context, state) => const ProviderListScreen(),
                ),
                GoRoute(
                  path: 'products', // -> /master-data/products
                  name: Routes.products,
                  builder: (context, state) {
                    context.read<ProductsCubit>().refreshCubit();
                    return const ProductsScreen();
                  },
                ),
                GoRoute(
                  path: 'staff', // -> /master-data/staff
                  name: Routes.staff,
                  builder: (context, state) => const StaffScreen(),
                ),
                GoRoute(
                  path:
                      'stores', // Sistemata l'inversione path/name -> /master-data/stores
                  name: Routes.stores,
                  builder: (context, state) {
                    context.read<ProviderListCubit>().loadAllProviders();
                    context.read<StoreCubit>().loadStores();
                    return const StoresScreen();
                  },
                ),
                GoRoute(
                  path: 'company-settings', // -> /master-data/company-settings
                  name: Routes.companySettings,
                  builder: (context, state) => BlocProvider(
                    create: (context) => CompanySettingsCubit(),
                    child: const CompanySettingsScreen(),
                  ),
                ),
              ],
            ),

            // ==========================================
            // 3. IMPOSTAZIONI
            // ==========================================
            GoRoute(
              path: '/settings',
              name: Routes.settings,
              builder: (context, state) => const SettingsScreen(),
              routes: [
                GoRoute(
                  path: 'themeSettings', // -> /settings/themeSettings
                  name: Routes.themeSettings,
                  builder: (context, state) => const ThemeSettingsView(),
                ),
                GoRoute(
                  path: 'reminderSettings',
                  name: Routes.reminderSettings,
                  builder: (context, state) =>
                      BlocProvider<ReminderDefaultsCubit>(
                        create: (context) => ReminderDefaultsCubit(),

                        child: const ReminderSettingsScreen(),
                      ),
                ),
              ],
            ),

            // ==========================================
            // 4. SCHERMATE PRINCIPALI EXTRA NELLA SHELL
            // (Accessibili ad es. dalla dashboard, mantengono la sidebar)
            // ==========================================
            GoRoute(
              path: '/operations',
              name: Routes.operations,
              builder: (context, state) => const OperationListScreen(),
            ),
            GoRoute(
              path: '/tickets',
              name: Routes.tickets,
              builder: (context, state) => const TicketListScreen(),
            ),
            GoRoute(
              path: '/notes',
              name: Routes.notes,
              builder: (context, state) => const NotesListScreen(),
            ),
            GoRoute(
              path: '/tasks',
              name: Routes.tasks,
              builder: (context, state) {
                // 1. Recuperiamo lo stato della sessione per le dipendenze
                final sessionState = context.read<SessionCubit>().state;

                // Sicurezza: Se per qualche motivo non abbiamo l'azienda,
                // qui potresti reindirizzare o gestire l'errore
                final companyId = sessionState.company?.id;
                if (companyId == null) {
                  return const Scaffold(
                    body: Center(child: Text("Errore: Azienda non trovata")),
                  );
                }

                // 2. Iniettiamo il Cubit con tutto ciò che gli serve
                return BlocProvider(
                  create: (context) => TaskListCubit(
                    currentCompanyId: companyId,
                    currentStoreId: sessionState
                        .currentStore
                        ?.id, // Opzionale: filtra per negozio se l'utente è "dentro" uno store
                  ),
                  child: const TaskListScreen(),
                );
              },
            ),
          ],
        ),

        // --- DETTAGLI E OPERATIVITÀ (FUORI DALLA SHELL - TUTTO SCHERMO) ---
        GoRoute(
          path: '/providers/form',
          name: Routes.providerForm,
          builder: (context, state) {
            // Estraiamo il fornitore (se stiamo modificando e non creando)
            final existingProvider = state.extra as ProviderModel?;

            return BlocProvider<ProviderFormCubit>(
              // Inizializziamo un Cubit NUOVO ogni volta che apriamo il form
              create: (context) => ProviderFormCubit(),
              child: ProviderFormScreen(existingProvider: existingProvider),
            );
          },
        ),
        GoRoute(
          // Il path sarà es. /tickets/form/123 oppure /tickets/form/new
          path: '/tickets/form/:id',
          name: Routes.ticketForm,
          builder: (context, state) {
            // 1. Leggiamo l'ID dall'URL
            final String pathId = state.pathParameters['id'] ?? 'new';

            // 2. CAST DA NINJA (Aggiungi i punti interrogativi!)
            final record =
                state.extra
                    as ({StaffMemberModel? createdBy, TicketModel? ticket})?;

            // 3. LOGICA SOBRIA
            final String? realTicketId;

            if (pathId == 'new') {
              realTicketId = null;
            } else if (record?.ticket?.id != null) {
              // <-- Parentesi TONDE per la condizione, GRAFFE per il blocco!
              realTicketId = record!.ticket!.id;
            } else {
              realTicketId = pathId;
            }
            if (realTicketId != null) {
              context.read<TrackingCubit>().loadTrackings(
                realTicketId,
                TrackingParentType.ticket,
              );
            }
            context.read<CustomersListCubit>().loadCustomers();
            context.read<ProductsCubit>().loadModels();
            context.read<ProductsCubit>().loadBrands();

            return MultiBlocProvider(
              providers: [
                BlocProvider(
                  create: (context) => AttachmentsBloc(
                    parentType: AttachmentParentType.ticket,
                    parentId: realTicketId,
                  ),
                ),
                BlocProvider(
                  create: (context) => TicketFormCubit(
                    // Passiamo il creatore e l'eventuale ticket esistente presi dal Record!
                    createdBy: record?.createdBy,
                    existingTicket: record?.ticket,
                  ),
                ),
              ],

              child: TicketFormScreen(
                ticketId: realTicketId,
                existingTicket: record?.ticket,
              ),
            );
          },
        ),
        GoRoute(
          path: '/tickets/workspace/:id',
          name: Routes.ticketWorkspace,
          builder: (context, state) {
            // 1. Recuperiamo il Cubit vivo dall'extra
            final formCubit = state.extra as TicketFormCubit?;

            // 2. Controllo di sicurezza (fondamentale per Flutter Web)
            if (formCubit != null) {
              return BlocProvider.value(
                value: formCubit,
                child: const TicketWorkspaceScreen(),
              );
            } else {
              // SCENARIO REFRESH WEB:
              // Se l'utente preme F5 del browser mentre è nel banco da lavoro,
              // l'extra viene distrutto e diventa null.
              // In questo caso, gli diciamo elegantemente che la sessione è persa
              // e lo invitiamo a tornare indietro, oppure restituisci direttamente
              // un blocco di redirect!
              return const Scaffold(
                body: Center(
                  child: Text(
                    'Sessione di lavoro scaduta. Torna alla lista e riapri il ticket.',
                  ),
                ),
              );
            }
          },
        ),
        GoRoute(
          path: '/upload-success',
          name: Routes.uploadSuccess,
          builder: (context, state) => const UploadSuccessScreen(),
        ),
        GoRoute(
          path: '/customer/details/:id',
          name: Routes.customerDetails,
          builder: (context, state) {
            final customer = state.extra as CustomerModel;
            return BlocProvider(
              create: (context) => AttachmentsBloc(
                parentType: AttachmentParentType.customer,
                parentId: customer.id,
              ),
              child: CustomerDetailScreen(customer: customer),
            );
          },
        ),
        GoRoute(
          path: '/customer/form/:id',
          name: Routes.customerForm,
          builder: (context, state) {
            final String pathId = state.pathParameters['id'] ?? 'new';
            final String? realCustomerId;
            if (pathId == 'new') {
              realCustomerId = null;
            } else {
              realCustomerId = pathId;
            }
            final customer = state.extra as CustomerModel?;

            return BlocProvider(
              create: (context) => CustomerFormCubit(
                existingCustomer: customer,
                customerId: realCustomerId,
              ),
              child: CustomerFormScreen(
                customer: customer,
                customerId: realCustomerId,
              ),
            );
          },
        ),

        GoRoute(
          path: '/operations/form/:id',
          name: Routes.operationForm,
          builder: (context, state) {
            final String pathId = state.pathParameters['id'] ?? 'new';

            final record =
                state.extra
                    as ({
                      StaffMemberModel? createdBy,
                      OperationModel? operation,
                    })?;

            final String? realOperationId;
            if (pathId == 'new') {
              realOperationId = null;
            } else if (record?.operation?.id != null) {
              realOperationId = record!.operation!.id;
            } else {
              realOperationId = pathId;
            }
            final currentStoreId = GetIt.I
                .get<SessionCubit>()
                .state
                .currentStore!
                .id!;
            context.read<CustomersListCubit>().loadCustomers();
            context.read<ProviderListCubit>().loadProviders(currentStoreId);
            context.read<ProductsCubit>().loadModels();
            context.read<ProductsCubit>().loadBrands();
            return MultiBlocProvider(
              providers: [
                BlocProvider(
                  create: (context) => AttachmentsBloc(
                    parentId: realOperationId,
                    parentType: AttachmentParentType.operation,
                  ),
                ),
                BlocProvider(
                  create: (context) => OperationFormCubit(
                    createdBy: record?.createdBy,
                    existingOperation: record?.operation,
                  ),
                ),
              ],
              child: OperationFormScreen(
                operationId: realOperationId,
                existingOperation: record?.operation,
              ),
            );
          },
        ),

        GoRoute(
          path: '/upload/:type/:id',
          name: Routes.upload,
          builder: (context, state) {
            final typeString = state.pathParameters['type']!;
            final id = state.pathParameters['id']!;
            final companyId = state.uri.queryParameters['companyId']!;

            // Trasformiamo la stringa dell'URL nel nostro amato Enum!
            final parentType = AttachmentParentType.values.firstWhere(
              (e) => e.name == typeString,
              orElse: () =>
                  AttachmentParentType.ticket, // Fallback di sicurezza
            );

            // Creiamo il BLoC "al volo" solo per questa schermata
            return MultiBlocProvider(
              providers: [
                BlocProvider<AttachmentsBloc>(
                  create: (context) =>
                      AttachmentsBloc(parentId: id, parentType: parentType),
                ),
                BlocProvider(create: (context) => ImageUploadCubit()),
              ],

              child: ImageUploadScreen(
                title: 'Caricamento Rapido',
                companyId: companyId,
              ),
            );
          },
        ),
        GoRoute(
          path: '/notes/edit/:id',
          name: Routes.noteForm,
          builder: (context, state) {
            final id = state.pathParameters['id']!;
            final NoteModel note = state.extra as NoteModel;

            // Creiamo il BLoC "al volo" solo per questa schermata
            return MultiBlocProvider(
              providers: [
                BlocProvider<AttachmentsBloc>(
                  create: (context) => AttachmentsBloc(
                    parentId: id,
                    parentType: AttachmentParentType.note,
                  ),
                ),
              ],

              child: NoteFormScreen(note: note),
            );
          },
        ),
        GoRoute(
          path: '/tasks/form/:id',
          name: Routes.taskForm,
          builder: (context, state) {
            final String pathId = state.pathParameters['id'] ?? 'new';
            final TaskModel? task = state.extra as TaskModel?;
            final String? realTaskId;
            if (pathId == 'new') {
              realTaskId = null;
            } else if (task?.id != null) {
              realTaskId = task!.id;
            } else {
              realTaskId = pathId;
            }

            List<StaffMemberModel>? preloadedStaff;
            try {
              preloadedStaff = context.read<StaffCubit>().state.allStaff;
            } catch (_) {
              preloadedStaff = null; // Fallback se la rotta è isolata
            }

            // Creiamo il BLoC "al volo" solo per questa schermata
            return MultiBlocProvider(
              providers: [
                BlocProvider<TaskFormCubit>(
                  create: (context) => TaskFormCubit(
                    existingTask: task,
                    initialTaskId: realTaskId,
                    allStaff: preloadedStaff,
                  ),
                ),
              ],

              child: TaskFormScreen(),
            );
          },
        ),
      ],
    );
  }
}

class GoRouterRefreshStream extends ChangeNotifier {
  GoRouterRefreshStream(Stream<dynamic> stream) {
    notifyListeners();
    _subscription = stream.asBroadcastStream().listen(
      (dynamic _) => notifyListeners(),
    );
  }
  late final StreamSubscription<dynamic> _subscription;
  @override
  void dispose() {
    _subscription.cancel();
    super.dispose();
  }
}
