import 'package:flutter/material.dart';
import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/design_system/colors.dart';
import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/design_system/typography.dart';

const _smallTextScaleFactor = 0.80;
const _largeTextScaleFactor = 1.20;

/// Namespace for the [ThemeData].
class AppTheme {
  /// Light `ThemeData` for  UI.
  static ThemeData get light => ThemeData(
        colorScheme: ColorScheme.fromSwatch(
          primarySwatch: ColorName.seedColor,
          accentColor: ColorName.seedColorAccent,
          cardColor: ColorName.lightBackground,
          backgroundColor: ColorName.lightBackground,
          errorColor: ColorName.lightError,
        ),
        appBarTheme: _appBarLightTheme,
        elevatedButtonTheme: _elevatedButtonLightTheme,
        outlinedButtonTheme: _outlinedButtonLightTheme,
        textTheme: _textTheme(),
        dialogTheme: _dialogLightTheme,
        tooltipTheme: _tooltipLightTheme,
        bottomSheetTheme: _bottomSheetLightTheme,
        tabBarTheme: _tabBarLightTheme,
        dividerTheme: _dividerLightTheme,
        backgroundColor: ColorName.lightBackground,
      );

  /// dark `ThemeData` for  UI.
  static ThemeData get dark => ThemeData(
        colorScheme: ColorScheme.fromSwatch(
          primarySwatch: ColorName.seedColor,
          accentColor: ColorName.darkSecondary,
          cardColor: ColorName.darkBackground,
          backgroundColor: ColorName.darkBackground,
          errorColor: ColorName.darkError,
          brightness: Brightness.dark,
        ),
        appBarTheme: _appBarDarkTheme,
        elevatedButtonTheme: _elevatedButtonDarkTheme,
        outlinedButtonTheme: _outlinedButtonDarkTheme,
        textTheme: _textTheme(isDark: true),
        dialogTheme: _dialogDarkTheme,
        tooltipTheme: _tooltipDarkTheme,
        bottomSheetTheme: _bottomSheetDarkTheme,
        tabBarTheme: _tabBarDarkTheme,
        dividerTheme: _dividerDarkTheme,
        backgroundColor: ColorName.darkBackground,
        canvasColor: ColorName.darkBackground,
      );

  /// `ThemeData` for UI for small screens.
  static ThemeData get lightSmall =>
      light.copyWith(textTheme: _smallTextTheme());

  /// `ThemeData` for UI for medium screens.
  static ThemeData get lightMedium =>
      light.copyWith(textTheme: _smallTextTheme());

  /// `ThemeData` for UI for large screens.
  static ThemeData get lightLarge =>
      light.copyWith(textTheme: _largeTextTheme());

  /// `ThemeData` for UI for small screens.
  static ThemeData get darkSmall =>
      dark.copyWith(textTheme: _smallTextTheme(isDark: true));

  /// `ThemeData` for UI for medium screens.
  static ThemeData get darkMedium =>
      dark.copyWith(textTheme: _smallTextTheme(isDark: true));

  /// `ThemeData` for UI for large screens.
  static ThemeData get darkLarge =>
      dark.copyWith(textTheme: _largeTextTheme(isDark: true));

  static TextTheme _textTheme({bool isDark = false}) => TextTheme(
        headline1: AppTypography.headline1,
        headline2: AppTypography.headline2,
        headline3: AppTypography.headline3,
        headline4: AppTypography.headline4,
        headline5: AppTypography.headline5,
        headline6: AppTypography.headline6,
        subtitle1: AppTypography.subtitle1,
        subtitle2: AppTypography.subtitle2,
        bodyText1: AppTypography.bodyText1,
        bodyText2: AppTypography.bodyText2,
        caption: AppTypography.caption,
        overline: AppTypography.overline,
        button: AppTypography.button,
      ).apply(
        bodyColor:
            isDark ? ColorName.darkOnBackground : ColorName.lightOnBackground,
        displayColor:
            isDark ? ColorName.darkOnBackground : ColorName.lightOnBackground,
      );

  static TextTheme _smallTextTheme({bool isDark = false}) =>
      _textTheme(isDark: isDark).apply(fontSizeFactor: _smallTextScaleFactor);

  static TextTheme _largeTextTheme({bool isDark = false}) =>
      _textTheme(isDark: isDark).apply(fontSizeFactor: _largeTextScaleFactor);

  static AppBarTheme get _appBarLightTheme =>
      const AppBarTheme(color: ColorName.lightPrimary);

  static AppBarTheme get _appBarDarkTheme =>
      const AppBarTheme(color: ColorName.darkSurfaceVariant);

  static ElevatedButtonThemeData get _elevatedButtonLightTheme =>
      ElevatedButtonThemeData(
        style: ElevatedButton.styleFrom(
          elevation: 0,
          shape: const RoundedRectangleBorder(
            borderRadius: BorderRadius.all(Radius.circular(30)),
          ),
          primary: ColorName.lightPrimary,
          fixedSize: const Size(208, 54),
        ),
      );

  static ElevatedButtonThemeData get _elevatedButtonDarkTheme =>
      ElevatedButtonThemeData(
        style: ElevatedButton.styleFrom(
          elevation: 0,
          shape: const RoundedRectangleBorder(
            borderRadius: BorderRadius.all(Radius.circular(30)),
          ),
          primary: ColorName.darkPrimary,
          fixedSize: const Size(208, 54),
        ),
      );

  static OutlinedButtonThemeData get _outlinedButtonLightTheme =>
      OutlinedButtonThemeData(
        style: OutlinedButton.styleFrom(
          shape: const RoundedRectangleBorder(
            borderRadius: BorderRadius.all(Radius.circular(30)),
          ),
          side: const BorderSide(color: ColorName.lightOutline, width: 2),
          primary: ColorName.lightPrimary,
          fixedSize: const Size(208, 54),
        ),
      );

  static OutlinedButtonThemeData get _outlinedButtonDarkTheme =>
      OutlinedButtonThemeData(
        style: OutlinedButton.styleFrom(
          shape: const RoundedRectangleBorder(
            borderRadius: BorderRadius.all(Radius.circular(30)),
          ),
          side: const BorderSide(color: ColorName.darkOutline, width: 2),
          primary: ColorName.darkPrimary,
          fixedSize: const Size(208, 54),
        ),
      );

  static TooltipThemeData get _tooltipLightTheme => const TooltipThemeData(
        decoration: BoxDecoration(
          color: ColorName.lightInverseSurface,
          borderRadius: BorderRadius.all(Radius.circular(5)),
        ),
        padding: EdgeInsets.all(10),
        textStyle: TextStyle(color: ColorName.lightOnInverseSurface),
      );

  static TooltipThemeData get _tooltipDarkTheme => const TooltipThemeData(
        decoration: BoxDecoration(
          color: ColorName.darkInverseSurface,
          borderRadius: BorderRadius.all(Radius.circular(5)),
        ),
        padding: EdgeInsets.all(10),
        textStyle: TextStyle(color: ColorName.darkOnInverseSurface),
      );

  static DialogTheme get _dialogLightTheme => DialogTheme(
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(12),
        ),
      );

  static DialogTheme get _dialogDarkTheme => DialogTheme(
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(12),
        ),
      );

  static BottomSheetThemeData get _bottomSheetLightTheme =>
      const BottomSheetThemeData(
        backgroundColor: ColorName.lightBackground,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.vertical(top: Radius.circular(12)),
        ),
      );

  static BottomSheetThemeData get _bottomSheetDarkTheme =>
      const BottomSheetThemeData(
        backgroundColor: ColorName.darkBackground,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.vertical(top: Radius.circular(12)),
        ),
      );

  static TabBarTheme get _tabBarLightTheme => const TabBarTheme(
        indicator: UnderlineTabIndicator(
          borderSide: BorderSide(
            width: 2,
            color: ColorName.lightPrimary,
          ),
        ),
        labelColor: ColorName.lightPrimary,
        unselectedLabelColor: ColorName.lightOutline,
        indicatorSize: TabBarIndicatorSize.tab,
      );

  static TabBarTheme get _tabBarDarkTheme => const TabBarTheme(
        indicator: UnderlineTabIndicator(
          borderSide: BorderSide(
            width: 2,
            color: ColorName.darkPrimary,
          ),
        ),
        labelColor: ColorName.darkPrimary,
        unselectedLabelColor: ColorName.darkOutline,
        indicatorSize: TabBarIndicatorSize.tab,
      );

  static DividerThemeData get _dividerLightTheme => const DividerThemeData(
        space: 0,
        thickness: 1,
        color: ColorName.lightOutline,
      );

  static DividerThemeData get _dividerDarkTheme => const DividerThemeData(
        space: 0,
        thickness: 1,
        color: ColorName.darkOutline,
      );
}
