// ignore_for_file: avoid_print, deprecated_member_use

import 'package:didvan/models/ai/ai_chat_args.dart';
import 'package:didvan/models/requests/news.dart';
import 'package:didvan/models/requests/radar.dart';
import 'package:didvan/models/story_model.dart';
import 'package:didvan/providers/user.dart';
import 'package:didvan/views/ai/ai_chat_page.dart';
import 'package:didvan/views/ai/ai_chat_state.dart';
import 'package:didvan/views/ai_section/ai_section_page.dart';
import 'package:didvan/views/ai/bot_assistants_page.dart';
import 'package:didvan/views/ai/create_bot_assistants_page.dart';
import 'package:didvan/views/ai/create_bot_assistants_state.dart';
import 'package:didvan/views/ai/history_ai_chat_page.dart';
import 'package:didvan/views/ai/info_page.dart';
import 'package:didvan/views/ai/info_state.dart';
import 'package:didvan/views/authentication/authentication.dart';
import 'package:didvan/views/authentication/authentication_state.dart';
import 'package:didvan/views/comments/comments.dart';
import 'package:didvan/views/comments/comments_state.dart';
import 'package:didvan/views/customize_category/customize_category_state.dart';
import 'package:didvan/views/customize_category/favorites_step.dart';
import 'package:didvan/views/direct/direct.dart';
import 'package:didvan/views/direct/direct_state.dart';
import 'package:didvan/views/hashtag/hashtag.dart';
import 'package:didvan/views/hashtag/hashtag_state.dart';
import 'package:didvan/views/home/home.dart';
import 'package:didvan/views/home/infography/infography_screen.dart';
import 'package:didvan/views/home/infography/infography_screen_state.dart';
import 'package:didvan/views/home/main/main_page_state.dart';
import 'package:didvan/views/home/home_state.dart';
import 'package:didvan/views/home/media/media_page.dart';
import 'package:didvan/views/home/media/video_details_page.dart';
import 'package:didvan/views/home/new_statistic/new_statistics_state.dart';
import 'package:didvan/views/home/new_statistic/statistics_details/stat_cats_general_screen.dart';
import 'package:didvan/views/home/new_statistic/statistics_details/stat_cats_general_state.dart';
import 'package:didvan/views/home/new_statistic/stock/new_stock_state.dart';
import 'package:didvan/views/home/new_statistic/stock/new_stock.dart';
import 'package:didvan/views/mentions/mentions.dart';
import 'package:didvan/views/mentions/mentions_state.dart';
import 'package:didvan/views/news/news.dart';
import 'package:didvan/views/news/news_details/news_details.dart';
import 'package:didvan/views/news/news_details/news_details_state.dart';
import 'package:didvan/views/news/news_state.dart';
import 'package:didvan/views/notification_time/notification_time_state.dart';
import 'package:didvan/views/podcasts/podcasts.dart';
import 'package:didvan/views/podcasts/podcasts_state.dart';
import 'package:didvan/views/podcasts/studio_details/studio_details_state.dart';
import 'package:didvan/views/profile/profile.dart';
import 'package:didvan/views/radar/radar.dart';
import 'package:didvan/views/radar/radar_details/radar_details.dart';
import 'package:didvan/views/radar/radar_details/radar_details_state.dart';
import 'package:didvan/views/radar/radar_state.dart';
import 'package:didvan/views/home/bookmarks/bookmarks.dart';
import 'package:didvan/views/home/bookmarks/bookmark_state.dart';
import 'package:didvan/views/home/bookmarks/filtered_bookmark/filtered_bookmark.dart';
import 'package:didvan/views/home/bookmarks/filtered_bookmark/filtered_bookmarks_state.dart';
import 'package:didvan/views/profile/direct_list/direct_list.dart';
import 'package:didvan/views/profile/direct_list/direct_list_state.dart';
import 'package:didvan/views/profile/general_settings/settings.dart';
import 'package:didvan/views/profile/general_settings/settings_state.dart';
import 'package:didvan/views/profile/edit_profile/edit_profile.dart';
import 'package:didvan/views/profile/change_password/change_password.dart';
import 'package:didvan/views/profile/change_password/change_password_state.dart';
import 'package:didvan/views/home/statistic/statistic_details/statistic_details.dart';
import 'package:didvan/views/home/statistic/statistic_details/statistic_details_state.dart';
import 'package:didvan/views/home/statistic/statistic_state.dart';
import 'package:didvan/views/podcasts/studio_details/studio_details.mobile.dart'
    if (dart.library.io) 'package:didvan/views/podcasts/studio_details/studio_details.mobile.dart'
    if (dart.library.html) 'package:didvan/views/podcasts/studio_details/studio_details.web.dart';
import 'package:didvan/views/pdf_viewer/pdf_viewer_page.dart';
import 'package:didvan/views/monthly/monthly_list_page.dart';
import 'package:didvan/views/monthly/monthly_list_state.dart';
import 'package:didvan/views/splash/splash.dart';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/views/story_viewer/story_viewer_page.dart';

import 'package:didvan/views/webview/web_view.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:home_widget/home_widget.dart';
import 'package:provider/provider.dart';

import '../views/customize_category/notification_status_step.dart';
import '../views/notification_time/notification_time.dart';
import '../views/notification_settings/notification_settings.dart';

class RouteGenerator {
  static Route<dynamic> generateRoute(RouteSettings settings) {
    final uri = Uri.parse(settings.name ?? '');
    if (uri.pathSegments.isNotEmpty) {
      if (uri.pathSegments.first == 'news' && uri.pathSegments.length > 1) {
        final id = int.tryParse(uri.pathSegments[1]);
        if (id != null) {
          return _createRoute(
            ChangeNotifierProvider<NewsDetailsState>(
              create: (context) => NewsDetailsState(),
              child: NewsDetails(
                pageData: {'id': id, 'args': const NewsRequestArgs(page: 0)},
              ),
            ),
          );
        }
      }
      if (uri.pathSegments.first == 'radar' && uri.pathSegments.length > 1) {
        final id = int.tryParse(uri.pathSegments[1]);
        if (id != null) {
          return _createRoute(
            ChangeNotifierProvider<RadarDetailsState>(
              create: (context) => RadarDetailsState(),
              child: RadarDetails(
                pageData: {'id': id, 'args': const RadarRequestArgs(page: 0)},
              ),
            ),
          );
        }
      }
    }
    if (!kIsWeb) {
      HomeWidget.saveWidgetData("cRoute", settings.name!);
    }
    switch (settings.name) {
      case Routes.splash:
        return _createRoute(
          const Splash(),
        );
      case Routes.aiSection:
        return _createRoute(
          const AiSectionPage(),
        );
      case Routes.notificationTime:
        if (settings.arguments is Map<String, dynamic>) {
          return _createRoute(
            ChangeNotifierProvider<NotificationTimeState>(
                create: (context) => NotificationTimeState(),
                child: NotificationTime(
                  pageData: settings.arguments as Map<String, dynamic>,
                )),
          );
        }
        return _errorRoute(
            'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');

      case Routes.favouritesStep:
        if (settings.arguments is Map<String, dynamic>) {
          return _createRoute(
            ChangeNotifierProvider<CustomizeCategoryState>(
                create: (context) => CustomizeCategoryState(),
                child: FavoritesStep(
                  pageData: settings.arguments as Map<String, dynamic>,
                )),
          );
        }
        return _errorRoute(
            'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');

      case Routes.notificationStatusStep:
        if (settings.arguments is Map<String, dynamic>) {
          return _createRoute(
            ChangeNotifierProvider<CustomizeCategoryState>(
                create: (context) => CustomizeCategoryState(),
                child: NotificationStatusStep(
                  pageData: settings.arguments as Map<String, dynamic>,
                )),
          );
        }
        return _errorRoute(
            'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');

      case Routes.notificationSettings:
        final args = settings.arguments;
        final pageData = args is Map<String, dynamic>
            ? args
            : (args is Map
                ? Map<String, dynamic>.from(args)
                : <String, dynamic>{});

        return _createRoute(
          MultiProvider(
            providers: [
              ChangeNotifierProvider<NotificationTimeState>(
                create: (context) => NotificationTimeState(),
              ),
              ChangeNotifierProvider<CustomizeCategoryState>(
                create: (context) => CustomizeCategoryState(),
              ),
            ],
            child: NotificationSettings(
              pageData: pageData,
            ),
          ),
        );

      case Routes.authenticaion:
        bool isResetPassword = false;
        if (settings.arguments is bool) {
          isResetPassword = settings.arguments as bool;
        } else if (settings.arguments != null) {
          print(
              'Warning: Invalid argument type for isResetPassword. Expected bool, got ${settings.arguments.runtimeType}. Using default false.');
        }
        return _createRoute(
            ChangeNotifierProvider<AuthenticationState>(
              create: (context) => AuthenticationState(),
              child: Authentication(isResetPassword: isResetPassword),
            ),
            animationType: 'fade');
      case Routes.home:
        bool? showDialogsArg;
        if (settings.arguments is bool?) {
          showDialogsArg = settings.arguments as bool?;
        } else if (settings.arguments != null) {
          print(
              'Warning: Invalid argument type for showDialogs. Expected bool?, got ${settings.arguments.runtimeType}. Using default null.');
        }
        return _createRoute(
            MultiProvider(
              providers: [
                ChangeNotifierProvider<HomeState>(
                  create: (context) => HomeState(),
                ),
                ChangeNotifierProvider<MainPageState>(
                  create: (context) => MainPageState(),
                ),
                ChangeNotifierProvider<StatisticState>(
                  create: (context) => StatisticState(),
                ),
                ChangeNotifierProvider<BookmarksState>(
                  create: (context) => BookmarksState(),
                ),
                ChangeNotifierProvider<NewStatisticState>(
                    create: (context) => NewStatisticState())
              ],
              child: Home(
                showDialogs: showDialogsArg,
              ),
            ),
            animationType: 'scale');
      case Routes.editProfile:
        return _createRoute(
          const EditProfile(),
        );
      case Routes.changePassword:
        return _createRoute(
          ChangeNotifierProvider<ChangePasswordState>(
            create: (context) {
              final userProvider = context.read<UserProvider>();
              final state = ChangePasswordState();
              state.username =
                  userProvider.user.username ?? userProvider.user.phoneNumber;
              return state;
            },
            child: const ChangePasswordPage(),
          ),
        );
      case Routes.profile:
        return _createRoute(
          ChangeNotifierProvider<GeneralSettingsState>(
              create: (context) => GeneralSettingsState(),
              child: const ProfilePage()),
        );
      case Routes.generalSettings:
        return _createRoute(
          ChangeNotifierProvider<GeneralSettingsState>(
            create: (context) => GeneralSettingsState(),
            child: const GeneralSettings(),
          ),
        );
      case Routes.podcasts:
        return _createRoute(
          Podcasts(
            viewPodcasts: true,
            pageData: settings.arguments as Map<String, dynamic>?,
          ),
        );
      case Routes.videocasts:
        return _createRoute(
          Podcasts(
            pageData: settings.arguments as Map<String, dynamic>?,
          ),
        );
      case Routes.radars:
        return _createRoute(
          ChangeNotifierProvider<RadarState>(
            create: (context) => RadarState(),
            child: const Radar(),
          ),
        );
      case Routes.news:
        return _createRoute(
          ChangeNotifierProvider<NewsState>(
            create: (context) => NewsState(),
            child: const News(),
          ),
        );
      case Routes.infography:
        return _createRoute(ChangeNotifierProvider<InfographyScreenState>(
          create: (context) => InfographyScreenState(),
          child: InfographyScreen(
            pageData: settings.arguments as Map<String, dynamic>?,
          ),
        ));

      case Routes.radarDetails:
        if (settings.arguments is Map<String, dynamic>) {
          return _createRoute(
            ChangeNotifierProvider<RadarDetailsState>(
              create: (context) => RadarDetailsState(),
              child: RadarDetails(
                pageData: settings.arguments as Map<String, dynamic>,
              ),
            ),
          );
        }
        return _errorRoute(
            'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');

      case Routes.statGeneral:
        if (settings.arguments is Map<String, dynamic>) {
          return _createRoute(MultiProvider(
            providers: [
              ChangeNotifierProvider<StatGeneralScreenState>(
                  create: (context) => StatGeneralScreenState()),
              ChangeNotifierProvider<NewStatisticState>(
                  create: (context) => NewStatisticState()),
            ],
            child: StatGeneralScreen(
                pageData: settings.arguments as Map<String, dynamic>),
          ));
        }
        return _errorRoute(
            'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');

      case Routes.newsDetails:
        if (settings.arguments is Map<String, dynamic>) {
          return _createRoute(
            ChangeNotifierProvider<NewsDetailsState>(
              create: (context) => NewsDetailsState(),
              child: NewsDetails(
                pageData: settings.arguments as Map<String, dynamic>,
              ),
            ),
          );
        }
        return _errorRoute(
            'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');

      case Routes.studioDetails:
        if (settings.arguments is Map<String, dynamic>) {
          return _createRoute(
            ChangeNotifierProvider<StudioDetailsState>(
              create: (context) => StudioDetailsState(),
              child: StudioDetails(
                pageData: settings.arguments as Map<String, dynamic>,
              ),
            ),
          );
        }
        return _errorRoute(
            'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');

      case Routes.videoDetails:
        if (settings.arguments is Map<String, dynamic>) {
          return _createRoute(
            ChangeNotifierProvider<StudioDetailsState>(
              create: (context) => StudioDetailsState(),
              child: VideoDetailsPage(
                pageData: settings.arguments as Map<String, dynamic>,
              ),
            ),
          );
        }
        return _errorRoute(
            'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');

      case Routes.statisticDetails:
        if (settings.arguments is Map<String, dynamic>) {
          return _createRoute(
            ChangeNotifierProvider<StatisticDetailsState>(
              create: (context) => StatisticDetailsState(),
              child: StatisticDetails(
                pageData: settings.arguments as Map<String, dynamic>,
              ),
            ),
          );
        }
        return _errorRoute(
            'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');

      case Routes.pdfViewer:
        if (settings.arguments is Map<String, dynamic>) {
          final args = settings.arguments as Map<String, dynamic>;
          return _createRoute(
            PdfViewerPage(
              pdfUrl: args['pdfUrl'] as String,
              title: args['title'] as String,
            ),
          );
        }
        return _errorRoute(
            'Invalid arguments for ${settings.name}: Expected Map<String, dynamic> with pdfUrl and title.');

      case Routes.monthlyList:
        return _createRoute(
          ChangeNotifierProvider<MonthlyListState>(
            create: (context) => MonthlyListState(),
            child: const MonthlyListPage(),
          ),
        );

      case Routes.stock:
        return _createRoute(MultiProvider(
          providers: [
            ChangeNotifierProvider<NewStockState>(
              create: (context) => NewStockState(),
            ),
          ],
          child: const NewStock(),
        ));

      case Routes.directList:
        return _createRoute(
          ChangeNotifierProvider<DirectListState>(
            create: (context) => DirectListState(),
            child: const DirectList(),
          ),
        );
      case Routes.direct:
        if (settings.arguments is Map<String, dynamic>) {
          return _createRoute(
            ChangeNotifierProvider<DirectState>(
              create: (context) => DirectState(),
              child:
                  Direct(pageData: settings.arguments as Map<String, dynamic>),
            ),
          );
        }
        return _errorRoute(
            'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');

      case Routes.comments:
        if (settings.arguments is Map<String, dynamic>) {
          return _createRoute(
            ChangeNotifierProvider<CommentsState>(
              create: (context) => CommentsState(),
              child: Comments(
                pageData: settings.arguments as Map<String, dynamic>,
              ),
            ),
          );
        }
        return _errorRoute(
            'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');

      case Routes.mentions:
        if (settings.arguments is Map<String, dynamic>) {
          return _createRoute(
            ChangeNotifierProvider<MentionsState>(
              create: (context) => MentionsState(),
              child: Mentions(
                pageData: settings.arguments as Map<String, dynamic>,
              ),
            ),
          );
        }
        return _errorRoute(
            'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');

      case Routes.bookmarks:
        return _createRoute(
          ChangeNotifierProvider<BookmarksState>(
            create: (context) => BookmarksState(),
            child: const Bookmarks(),
          ),
        );
      case Routes.hashtag:
        if (settings.arguments is Map<String, dynamic>) {
          return _createRoute(
            ChangeNotifierProvider<HashtagState>(
              create: (context) => HashtagState(),
              child:
                  Hashtag(pageData: settings.arguments as Map<String, dynamic>),
            ),
          );
        }
        return _errorRoute(
            'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');

      case Routes.filteredBookmarks:
        if (settings.arguments is Map<String, dynamic>) {
          final args = settings.arguments as Map<String, dynamic>;
          if (args['type'] is int) {
            final type = args['type'] as int;
            final onDeleted = args['onDeleted'] as void Function(int id)?;
            return _createRoute(
              ChangeNotifierProvider<FilteredBookmarksState>(
                create: (context) => FilteredBookmarksState(type),
                child: FilteredBookmarks(
                  onDeleted: onDeleted,
                  type: type,
                ),
              ),
            );
          } else {
            return _errorRoute(
                'Invalid arguments for ${settings.name}: "type" key is missing or not an int.');
          }
        } else {
          return _errorRoute(
              'Invalid arguments for ${settings.name}: Expected a Map.');
        }

      case Routes.aiChat:
        if (settings.arguments is AiChatArgs) {
          return _createRoute(ChangeNotifierProvider<AiChatState>(
              create: (context) => AiChatState(),
              child: AiChatPage(
                args: settings.arguments as AiChatArgs,
              )));
        }
        return _errorRoute(
            'Invalid arguments for ${settings.name}: Expected AiChatArgs.');

      case Routes.aiHistory:
        return _createRoute(HistoryAiChatPage(
          archived: settings.arguments as bool?,
        ));

      case Routes.botAssistants:
        return _createRoute(const BotAssistantsPage());
      case Routes.createBotAssistants:
        return _createRoute(ChangeNotifierProvider<CreateBotAssistantsState>(
          create: (context) {
            final CreateBotAssistantsState pr = CreateBotAssistantsState();
            final id = settings.arguments as int?;
            if (id != null) {
              pr.getAnAssistant(id: id);
            } else {
              pr.getImageToolsBots();
            }
            return pr;
          },
          child: CreateBotAssistantsPage(
            id: settings.arguments as int?,
          ),
        ));
      case Routes.info:
        return _createRoute(ChangeNotifierProvider<InfoState>(
            create: (context) {
              InfoState infoState = InfoState();
              infoState.getTools();
              return infoState;
            },
            child: const InfoPage()));

      case Routes.web:
        if (settings.arguments is String) {
          return _createRoute(WebView(
            src: settings.arguments as String,
          ));
        }
        return _errorRoute(
            'Invalid arguments for ${settings.name}: Expected String.');

      case Routes.storyViewer:
        if (settings.arguments is Map<String, dynamic>) {
          final args = settings.arguments as Map<String, dynamic>;
          final stories = args['stories'] as List<UserStories>;
          final tappedIndex = args['tappedIndex'] as int;
          return _createRoute(
            StoryViewerPage(
              stories: stories,
              tappedIndex: tappedIndex,
            ),
          );
        }
        return _errorRoute(
            'Invalid arguments for ${settings.name}: Expected Map with stories and tappedIndex.');

      case Routes.media:
        return MaterialPageRoute(
          builder: (_) => ChangeNotifierProvider(
            create: (context) => PodcastsState(),
            child: const MediaPage(),
          ),
        );

      case Routes.aiArchivedHistory:
        return MaterialPageRoute(
          builder: (_) => const HistoryAiChatPage(archived: true),
        );
      default:
        return _errorRoute(settings.name ?? 'Unknown route');
    }
  }

  static Route<dynamic> _errorRoute(String message) {
    return MaterialPageRoute(builder: (_) {
      return Scaffold(
        appBar: AppBar(
          title: const Text('خطا در مسیریابی'),
        ),
        body: Center(
          child: Text(
              'مسیر "$message" معتبر نیست یا آرگومان‌های نادرستی ارسال شده است.'),
        ),
      );
    });
  }

  static Route _createRoute(Widget page, {String animationType = 'slide'}) {
    Widget pageWrapper(BuildContext context) {
      final shortestSide = MediaQuery.of(context).size.shortestSide;
      final bool useMobileLayout = shortestSide < 600;

      if (kIsWeb && !useMobileLayout) {
        final deviceSize = MediaQuery.of(context).size;
        return MediaQuery(
          data: MediaQuery.of(context).copyWith(
            size: Size(
              deviceSize.height * 9 / 16,
              deviceSize.height,
            ),
            textScaler: const TextScaler.linear(1.0),
          ),
          child: Container(
            color: Theme.of(context).colorScheme.background,
            alignment: Alignment.center,
            child: AspectRatio(aspectRatio: 9 / 16, child: page),
          ),
        );
      }

      return MediaQuery(
        data: MediaQuery.of(context)
            .copyWith(textScaler: const TextScaler.linear(1.0)),
        child: Container(
          color: Theme.of(context).colorScheme.surface,
          child: SafeArea(
            top: false,
            child: page,
          ),
        ),
      );
    }

    return PageRouteBuilder(
      pageBuilder: (context, animation, secondaryAnimation) =>
          pageWrapper(context),
      transitionDuration: const Duration(milliseconds: 400),
      transitionsBuilder: (context, animation, secondaryAnimation, child) {
        switch (animationType) {
          case 'slide':
            const begin = Offset(1.0, 0.0);
            const end = Offset.zero;
            final tween = Tween(begin: begin, end: end)
                .chain(CurveTween(curve: Curves.easeInOut));
            final offsetAnimation = animation.drive(tween);
            return SlideTransition(
              position: offsetAnimation,
              child: child,
            );

          case 'fade':
            return FadeTransition(
              opacity: CurvedAnimation(parent: animation, curve: Curves.easeIn),
              child: child,
            );

          case 'scale':
            return ScaleTransition(
              scale: CurvedAnimation(
                  parent: animation, curve: Curves.fastOutSlowIn),
              child: child,
            );

          case 'rotation':
            return RotationTransition(
              turns: Tween<double>(begin: 0.8, end: 1.0).animate(
                  CurvedAnimation(parent: animation, curve: Curves.easeInOut)),
              child: FadeTransition(opacity: animation, child: child),
            );

          default:
            const begin = Offset(1.0, 0.0);
            const end = Offset.zero;
            final tween = Tween(begin: begin, end: end)
                .chain(CurveTween(curve: Curves.easeInOut));
            final offsetAnimation = animation.drive(tween);
            return SlideTransition(
              position: offsetAnimation,
              child: child,
            );
        }
      },
    );
  }
}
