import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:qpay/auth_state.dart';
import 'package:qpay/navbar.dart';
import 'package:qpay/screens/confirm/confirm_screen.dart';
import 'package:qpay/screens/gateway/gateway_redirect.dart';
import 'package:qpay/screens/gateway/gateway_screen.dart';
import 'package:qpay/screens/gateway/gateway_web_screen.dart';
import 'package:qpay/screens/groups/screens/batch_create_screen.dart';
import 'package:qpay/screens/groups/screens/batch_detail_screen.dart';
import 'package:qpay/screens/groups/screens/batch_item_screen.dart';
import 'package:qpay/screens/groups/screens/create_group_from_file_screen.dart';
import 'package:qpay/screens/groups/screens/group_create_screen.dart';
import 'package:qpay/screens/groups/screens/group_detail_screen.dart';
import 'package:qpay/screens/groups/screens/groups_screen.dart';
import 'package:qpay/screens/groups/models/group_batch_model.dart';
import 'package:qpay/screens/groups/models/recipient_group_model.dart';
import 'package:qpay/screens/history/history_screen.dart';
import 'package:qpay/screens/home/home_screen.dart';
import 'package:qpay/screens/integration/integration_screen.dart';
import 'package:qpay/screens/onboarding/complete_screen.dart';
import 'package:qpay/screens/onboarding/landing/landing_screen.dart';
import 'package:qpay/screens/onboarding/login/login_screen.dart';
import 'package:qpay/screens/onboarding/phone/phone_screen.dart';
import 'package:qpay/screens/onboarding/verify/verify_screen.dart';
import 'package:qpay/screens/pay/pay_screen.dart';
import 'package:qpay/screens/poll/poll_screen.dart';
import 'package:qpay/screens/profile_screen.dart';
import 'package:qpay/screens/receipt/receipt_screen.dart';
import 'package:qpay/screens/recipient/recipients_screen.dart';
import 'package:qpay/screens/splash_screen.dart';
import 'package:qpay/screens/workspaces/workspace_screen.dart';
import 'package:qpay/screens/users/screens/user_list_screen.dart';
import 'package:qpay/screens/more/more_screen.dart';
import 'package:qpay/screens/uptime/uptime_status_screen.dart';
import 'package:qpay/screens/contact/contact_screen.dart';

/// Tracks whether the splash animation is complete so that
/// GoRouter's redirect can show the splash first, then release
/// navigation to the originally intended URL.
class SplashState extends ChangeNotifier {
  bool _complete = false;

  /// The route the user originally intended to visit before being
  /// redirected to /splash. Set by the redirect callback on first
  /// invocation.
  String? _intendedRoute;
  bool get complete => _complete;
  String? get intendedRoute => _intendedRoute;

  /// Called by the redirect to store the intended destination and
  /// return the splash route.
  String? guard(String attemptedRoute) {
    if (_complete) return null;
    // Avoid saving the splash route itself.
    if (attemptedRoute == '/splash') return null;
    _intendedRoute = attemptedRoute;
    return '/splash';
  }

  void finish() {
    _complete = true;
    notifyListeners();
  }
}

final SplashState splashState = SplashState();

/// Route prefixes that require the user to be signed in. Any URL
/// whose path starts with one of these strings will be redirected
/// to the sign-in screen when no auth token is present.
const List<String> _authProtectedRoutePrefixes = ['/groups', '/users'];

bool _isAuthProtected(String path) {
  for (final prefix in _authProtectedRoutePrefixes) {
    if (path == prefix || path.startsWith('$prefix/')) {
      return true;
    }
  }
  return false;
}

/// Builds the application's [GoRouter] instance.
///
/// The router is responsible for:
/// - Showing the splash screen on cold start and replaying the
///   originally intended route when the animation finishes.
/// - Hosting the [ShellRoute] that adds the [ScaffoldWithNavBar]
///   to every authenticated screen (the onboarding flow renders
///   without the shell so the UI stays full-bleed).
/// - Enforcing the auth wall around protected routes (currently the
///   groups flow). Unauthenticated users are bounced to the sign-in
///   screen, then sent back to their original destination after a
///   successful sign-in.
GoRouter buildRouter() {
  return GoRouter(
    initialLocation: '/',
    // React to both the splash completion and auth state changes so
    // protected routes are re-evaluated as the user signs in or out.
    refreshListenable: Listenable.merge([splashState, authState]),
    errorBuilder: (context, state) => Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text('Page not found', style: TextStyle(fontSize: 20)),
            const SizedBox(height: 16),
            ElevatedButton(
              onPressed: () => context.go('/'),
              child: const Text('Go Home'),
            ),
          ],
        ),
      ),
    ),
    redirect: (context, state) {
      // Before splash is complete: redirect everything to /splash,
      // but save the original intended destination.
      final guardResult = splashState.guard(state.uri.path);
      if (guardResult != null) return guardResult;

      // Once splash is complete we can start evaluating auth rules.
      // We also wait for the initial auth state read to complete so
      // a persisted token isn't accidentally ignored on cold start.
      if (splashState.complete && isAuthInitialized) {
        final path = state.uri.path;

        // If the user has just signed in and we still have a pending
        // intended route, take them there instead of leaving them
        // stuck on the sign-in screen.
        if (path == '/onboarding/login' && authState.isLoggedIn) {
          final intended = authState.consumeIntendedRoute();
          if (intended != null && intended != '/onboarding/login') {
            return intended;
          }
        }

        // Auth wall: any protected route requires a valid token.
        if (_isAuthProtected(path) && !authState.isLoggedIn) {
          return authState.requireAuth(path);
        }

        // Splash → workspace selector (which may auto-redirect to home
        // if only one workspace exists).
        if (path == '/splash') {
          return '/workspace';
        }
      }

      return null;
    },
    routes: [
      // Splash route sits outside the ShellRoute so it renders
      // without the bottom nav bar or side rail.
      GoRoute(
        path: '/splash',
        builder: (context, state) => const SplashScreen(),
      ),
      ShellRoute(
        builder: (context, state, child) {
          final location = GoRouterState.of(context).uri.toString();
          if (location.startsWith('/onboarding/') || location == '/workspace') {
            return child;
          }
          return ScaffoldWithNavBar(child: child);
        },
        routes: [
          GoRoute(
            path: '/workspace',
            builder: (context, state) => const WorkspaceScreen(),
          ),
          GoRoute(path: '/', builder: (context, state) => const HomeScreen()),
          GoRoute(
            path: '/home',
            builder: (context, state) => const HomeScreen(),
          ),
          GoRoute(
            path: '/make-payment',
            builder: (context, state) => const PayScreen(),
          ),
          GoRoute(
            path: '/confirm',
            builder: (context, state) => const ConfirmScreen(),
          ),
          GoRoute(
            path: '/gateway',
            builder: (context, state) => const GatewayScreen(),
          ),
          GoRoute(
            path: '/gateway-web',
            builder: (context, state) => const GatewayWebScreen(),
          ),
          GoRoute(
            path: '/gateway-redirect',
            builder: (context, state) => const GatewayRedirectScreen(),
          ),
          GoRoute(
            path: '/poll/:id',
            builder: (context, state) =>
                PollScreen(transactionId: state.pathParameters['id']),
          ),
          GoRoute(
            path: '/poll',
            builder: (context, state) => const PollScreen(),
          ),
          GoRoute(
            path: '/receipt',
            builder: (context, state) => const ReceiptScreen(),
          ),
          GoRoute(
            path: '/receipt/:transactionId',
            builder: (context, state) => ReceiptScreen(
              transactionId: state.pathParameters['transactionId'],
            ),
          ),
          GoRoute(
            path: '/integration',
            builder: (context, state) => const IntegrationScreen(),
          ),
          GoRoute(
            path: '/recipients',
            builder: (context, state) => const RecipientsScreen(),
          ),
          GoRoute(
            path: '/history',
            builder: (context, state) => const HistoryScreen(),
          ),
          GoRoute(
            path: '/profile',
            builder: (context, state) => const ProfileScreen(),
          ),
          GoRoute(
            path: '/more',
            builder: (context, state) => const MoreScreen(),
          ),
          GoRoute(
            path: '/contact',
            builder: (context, state) => const ContactScreen(),
          ),
          GoRoute(
            path: '/uptime',
            builder: (context, state) => const UptimeStatusScreen(),
          ),
          GoRoute(
            path: '/users',
            builder: (context, state) => const UserListScreen(),
          ),
          GoRoute(
            path: '/groups',
            builder: (context, state) => const GroupsScreen(),
          ),
          GoRoute(
            path: '/groups/create',
            builder: (context, state) => const GroupCreateScreen(),
          ),
          GoRoute(
            path: '/groups/create-from-file',
            builder: (context, state) => const CreateGroupFromFileScreen(),
          ),
          GoRoute(
            path: '/groups/:groupId',
            builder: (context, state) {
              final group = state.extra as RecipientGroup;
              return GroupDetailScreen(group: group);
            },
          ),
          GoRoute(
            path: '/groups/:groupId/batches/create',
            builder: (context, state) {
              final group = state.extra as RecipientGroup;
              return BatchCreateScreen(group: group);
            },
          ),
          GoRoute(
            path: '/groups/batches/:batchId',
            builder: (context, state) {
              final batchId = state.pathParameters['batchId']!;
              return BatchDetailScreen(batchId: batchId);
            },
          ),
          GoRoute(
            path: '/groups/:groupId/batches/:batchId/items/:itemId',
            builder: (context, state) {
              final item = state.extra as GroupBatchItem;
              return BatchItemScreen(item: item);
            },
          ),
          GoRoute(
            path: '/onboarding/landing',
            builder: (context, state) => const LandingScreen(),
          ),
          GoRoute(
            path: '/onboarding/phone',
            builder: (context, state) => const PhoneScreen(),
          ),
          GoRoute(
            path: '/onboarding/verify',
            builder: (context, state) => const VerifyScreen(),
          ),
          GoRoute(
            path: '/onboarding/login',
            builder: (context, state) => const LoginScreen(),
          ),
          GoRoute(
            path: '/onboarding/complete',
            builder: (context, state) => const CompleteScreen(),
          ),
        ],
      ),
    ],
  );
}
