import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';

import '../providers/auth_provider.dart';
import '../providers/profile_provider.dart';
import '../providers/supabase_provider.dart';
import '../utils/lock_enforcer.dart';
import '../screens/auth/login_screen.dart';
import '../screens/auth/signup_screen.dart';
import '../screens/admin/offices_screen.dart';
import '../screens/admin/user_management_screen.dart';
import '../screens/admin/geofence_test_screen.dart';
import '../screens/dashboard/dashboard_screen.dart';
import '../screens/notifications/notifications_screen.dart';
import '../screens/profile/profile_screen.dart';
import '../screens/shared/under_development_screen.dart';
import '../screens/shared/permissions_screen.dart';
import '../screens/reports/reports_screen.dart';
import '../screens/tasks/task_detail_screen.dart';
import '../screens/tasks/tasks_list_screen.dart';
import '../screens/tickets/ticket_detail_screen.dart';
import '../screens/tickets/tickets_list_screen.dart';
import '../screens/workforce/workforce_screen.dart';
import '../widgets/app_shell.dart';
import '../screens/teams/teams_screen.dart';

final appRouterProvider = Provider<GoRouter>((ref) {
  final notifier = RouterNotifier(ref);
  ref.onDispose(notifier.dispose);

  return GoRouter(
    initialLocation: '/dashboard',
    refreshListenable: notifier,
    redirect: (context, state) {
      final authState = ref.read(authStateChangesProvider);
      dynamic session;
      if (authState is AsyncData) {
        final state = authState.value;
        session = state?.session;
      } else {
        session = ref.read(sessionProvider);
      }
      final isAuthRoute =
          state.fullPath == '/login' || state.fullPath == '/signup';
      final isSignedIn = session != null;
      final profileAsync = ref.read(currentProfileProvider);
      final isAdminRoute = state.matchedLocation.startsWith('/settings');
      final role = profileAsync is AsyncData
          ? (profileAsync.value)?.role
          : null;
      final isAdmin = role == 'admin';
      final isReportsRoute = state.matchedLocation == '/reports';
      final hasReportsAccess =
          role == 'admin' || role == 'dispatcher' || role == 'it_staff';

      if (!isSignedIn && !isAuthRoute) {
        return '/login';
      }
      if (isSignedIn && isAuthRoute) {
        return '/dashboard';
      }
      if (isAdminRoute && !isAdmin) {
        return '/tickets';
      }
      if (isReportsRoute && !hasReportsAccess) {
        return '/tickets';
      }
      return null;
    },
    routes: [
      GoRoute(path: '/login', builder: (context, state) => const LoginScreen()),
      GoRoute(
        path: '/signup',
        builder: (context, state) => const SignUpScreen(),
      ),
      ShellRoute(
        builder: (context, state, child) => AppScaffold(child: child),
        routes: [
          GoRoute(
            path: '/settings/teams',
            builder: (context, state) => const TeamsScreen(),
          ),
          GoRoute(
            path: '/dashboard',
            builder: (context, state) => const DashboardScreen(),
          ),
          GoRoute(
            path: '/tickets',
            builder: (context, state) => const TicketsListScreen(),
            routes: [
              GoRoute(
                path: ':id',
                builder: (context, state) => TicketDetailScreen(
                  ticketId: state.pathParameters['id'] ?? '',
                ),
              ),
            ],
          ),
          GoRoute(
            path: '/tasks',
            builder: (context, state) => const TasksListScreen(),
            routes: [
              GoRoute(
                path: ':id',
                builder: (context, state) =>
                    TaskDetailScreen(taskId: state.pathParameters['id'] ?? ''),
              ),
            ],
          ),
          GoRoute(
            path: '/events',
            builder: (context, state) => const UnderDevelopmentScreen(
              title: 'Events',
              subtitle: 'Event monitoring is under development.',
              icon: Icons.event,
            ),
          ),
          GoRoute(
            path: '/announcements',
            builder: (context, state) => const UnderDevelopmentScreen(
              title: 'Announcement',
              subtitle: 'Operational broadcasts are coming soon.',
              icon: Icons.campaign,
            ),
          ),
          GoRoute(
            path: '/workforce',
            builder: (context, state) => const WorkforceScreen(),
          ),
          GoRoute(
            path: '/reports',
            builder: (context, state) => const ReportsScreen(),
          ),
          GoRoute(
            path: '/settings/users',
            builder: (context, state) => const UserManagementScreen(),
          ),
          GoRoute(
            path: '/settings/offices',
            builder: (context, state) => const OfficesScreen(),
          ),
          GoRoute(
            path: '/settings/geofence-test',
            builder: (context, state) => const GeofenceTestScreen(),
          ),
          GoRoute(
            path: '/settings/permissions',
            builder: (context, state) => const PermissionsScreen(),
          ),
          GoRoute(
            path: '/notifications',
            builder: (context, state) => const NotificationsScreen(),
          ),
          GoRoute(
            path: '/profile',
            builder: (context, state) => const ProfileScreen(),
          ),
        ],
      ),
    ],
  );
});

class RouterNotifier extends ChangeNotifier {
  RouterNotifier(this.ref) {
    _authSub = ref.listen(authStateChangesProvider, (previous, next) {
      // Only enforce lock on successful sign-in events, not on every auth state change
      if (next is AsyncData) {
        final authState = next.value;
        final session = authState?.session;
        // Only check for bans when we have a session and the previous state didn't
        final previousSession = previous is AsyncData
            ? previous.value?.session
            : null;
        if (session != null && previousSession == null) {
          // User just signed in; enforce lock check
          _enforceLockAsync();
        }
      }
      notifyListeners();
    });
    _profileSub = ref.listen(currentProfileProvider, (previous, next) {
      notifyListeners();
    });
  }

  final Ref ref;
  late final ProviderSubscription _authSub;
  late final ProviderSubscription _profileSub;
  bool _lockEnforcementInProgress = false;

  /// Safely enforce lock in the background, preventing concurrent calls
  void _enforceLockAsync() {
    // Prevent concurrent enforcement calls
    if (_lockEnforcementInProgress) return;
    _lockEnforcementInProgress = true;

    // Use Future.microtask to defer execution and avoid blocking
    Future.microtask(() async {
      try {
        await enforceLockForCurrentUser(ref.read(supabaseClientProvider));
      } catch (e) {
        debugPrint('RouterNotifier: lock enforcement error: $e');
      } finally {
        _lockEnforcementInProgress = false;
      }
    });
  }

  @override
  void dispose() {
    _authSub.close();
    _profileSub.close();
    super.dispose();
  }
}
