import 'package:flex_color_scheme/flex_color_scheme.dart';
import 'package:flutter/material.dart';

@immutable
class MapflowThemeTokens extends ThemeExtension<MapflowThemeTokens> {
  const MapflowThemeTokens({
    required this.mapPanel,
    required this.mapPanelBorder,
    required this.mapShadow,
    required this.danger,
    required this.onDark,
    required this.darkSurface,
    required this.darkSurfaceAlt,
    required this.voiceAccent,
    required this.voiceAccentSoft,
    required this.onVoiceControl,
    required this.snowflakeLine,
    required this.snowflakeNode,
    required this.snowflakeCenter,
    required this.snowflakeLabel,
    required this.imageScrim,
    required this.panelRadius,
  });

  final Color mapPanel;
  final Color mapPanelBorder;
  final Color mapShadow;
  final Color danger;
  final Color onDark;
  final Color darkSurface;
  final Color darkSurfaceAlt;
  final Color voiceAccent;
  final Color voiceAccentSoft;
  final Color onVoiceControl;
  final Color snowflakeLine;
  final Color snowflakeNode;
  final Color snowflakeCenter;
  final Color snowflakeLabel;
  final Color imageScrim;
  final double panelRadius;

  @override
  MapflowThemeTokens copyWith({
    Color? mapPanel,
    Color? mapPanelBorder,
    Color? mapShadow,
    Color? danger,
    Color? onDark,
    Color? darkSurface,
    Color? darkSurfaceAlt,
    Color? voiceAccent,
    Color? voiceAccentSoft,
    Color? onVoiceControl,
    Color? snowflakeLine,
    Color? snowflakeNode,
    Color? snowflakeCenter,
    Color? snowflakeLabel,
    Color? imageScrim,
    double? panelRadius,
  }) {
    return MapflowThemeTokens(
      mapPanel: mapPanel ?? this.mapPanel,
      mapPanelBorder: mapPanelBorder ?? this.mapPanelBorder,
      mapShadow: mapShadow ?? this.mapShadow,
      danger: danger ?? this.danger,
      onDark: onDark ?? this.onDark,
      darkSurface: darkSurface ?? this.darkSurface,
      darkSurfaceAlt: darkSurfaceAlt ?? this.darkSurfaceAlt,
      voiceAccent: voiceAccent ?? this.voiceAccent,
      voiceAccentSoft: voiceAccentSoft ?? this.voiceAccentSoft,
      onVoiceControl: onVoiceControl ?? this.onVoiceControl,
      snowflakeLine: snowflakeLine ?? this.snowflakeLine,
      snowflakeNode: snowflakeNode ?? this.snowflakeNode,
      snowflakeCenter: snowflakeCenter ?? this.snowflakeCenter,
      snowflakeLabel: snowflakeLabel ?? this.snowflakeLabel,
      imageScrim: imageScrim ?? this.imageScrim,
      panelRadius: panelRadius ?? this.panelRadius,
    );
  }

  @override
  MapflowThemeTokens lerp(
    covariant ThemeExtension<MapflowThemeTokens>? other,
    double t,
  ) {
    if (other is! MapflowThemeTokens) {
      return this;
    }
    return MapflowThemeTokens(
      mapPanel: Color.lerp(mapPanel, other.mapPanel, t)!,
      mapPanelBorder: Color.lerp(mapPanelBorder, other.mapPanelBorder, t)!,
      mapShadow: Color.lerp(mapShadow, other.mapShadow, t)!,
      danger: Color.lerp(danger, other.danger, t)!,
      onDark: Color.lerp(onDark, other.onDark, t)!,
      darkSurface: Color.lerp(darkSurface, other.darkSurface, t)!,
      darkSurfaceAlt: Color.lerp(darkSurfaceAlt, other.darkSurfaceAlt, t)!,
      voiceAccent: Color.lerp(voiceAccent, other.voiceAccent, t)!,
      voiceAccentSoft: Color.lerp(voiceAccentSoft, other.voiceAccentSoft, t)!,
      onVoiceControl: Color.lerp(onVoiceControl, other.onVoiceControl, t)!,
      snowflakeLine: Color.lerp(snowflakeLine, other.snowflakeLine, t)!,
      snowflakeNode: Color.lerp(snowflakeNode, other.snowflakeNode, t)!,
      snowflakeCenter: Color.lerp(snowflakeCenter, other.snowflakeCenter, t)!,
      snowflakeLabel: Color.lerp(snowflakeLabel, other.snowflakeLabel, t)!,
      imageScrim: Color.lerp(imageScrim, other.imageScrim, t)!,
      panelRadius: lerpDouble(panelRadius, other.panelRadius, t),
    );
  }
}

class MapflowTheme {
  const MapflowTheme._();

  static const tokens = MapflowThemeTokens(
    mapPanel: Color(0xFF15111D),
    mapPanelBorder: Color(0xFF2F263D),
    mapShadow: Color(0x99000000),
    danger: Color(0xFFFF2D75),
    onDark: Colors.white,
    darkSurface: Color(0xFF05030B),
    darkSurfaceAlt: Color(0xFF15111D),
    voiceAccent: Color(0xFFFF2D75),
    voiceAccentSoft: Color(0xFFFF8BB5),
    onVoiceControl: Color(0xFF090613),
    snowflakeLine: Color(0xFF3B304B),
    snowflakeNode: Color(0xFF67567E),
    snowflakeCenter: Color(0xFFFF2D75),
    snowflakeLabel: Color(0xFFCFC1DE),
    imageScrim: Color(0xCC000000),
    panelRadius: 8,
  );

  static ThemeData dark() {
    return FlexThemeData.dark(
      useMaterial3: true,
      colors: const FlexSchemeColor(
        primary: Color(0xFFFF2D75),
        primaryContainer: Color(0xFF5B1432),
        secondary: Color(0xFFB86BFF),
        secondaryContainer: Color(0xFF3E205A),
        tertiary: Color(0xFFFFB86B),
        tertiaryContainer: Color(0xFF4F2D13),
        appBarColor: Color(0xFF05030B),
        error: Color(0xFFFFB4AB),
      ),
      scaffoldBackground: tokens.darkSurface,
      surface: tokens.mapPanel,
      subThemesData: const FlexSubThemesData(
        defaultRadius: 8,
        inputDecoratorRadius: 8,
        cardRadius: 8,
        chipRadius: 8,
        filledButtonRadius: 8,
      ),
      fontFamily: 'SF Pro Display',
      extensions: const [tokens],
    ).copyWith(
      appBarTheme: const AppBarTheme(
        backgroundColor: Color(0xFF05030B),
        foregroundColor: Colors.white,
        surfaceTintColor: Colors.transparent,
      ),
      bottomSheetTheme: const BottomSheetThemeData(
        backgroundColor: Color(0xFF15111D),
        modalBackgroundColor: Color(0xFF15111D),
        surfaceTintColor: Colors.transparent,
        dragHandleColor: Color(0xFF8F7AA7),
      ),
      cardTheme: CardThemeData(
        elevation: 0,
        color: tokens.mapPanel,
        surfaceTintColor: Colors.transparent,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(tokens.panelRadius),
          side: BorderSide(color: tokens.mapPanelBorder),
        ),
      ),
      dialogTheme: const DialogThemeData(
        backgroundColor: Color(0xFF15111D),
        surfaceTintColor: Colors.transparent,
      ),
      popupMenuTheme: PopupMenuThemeData(
        color: tokens.mapPanel,
        surfaceTintColor: Colors.transparent,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(tokens.panelRadius),
          side: BorderSide(color: tokens.mapPanelBorder),
        ),
      ),
      chipTheme: ChipThemeData(
        backgroundColor: tokens.mapPanel,
        selectedColor: const Color(0xFF5B1432),
        disabledColor: const Color(0xFF211A2B),
        secondarySelectedColor: const Color(0xFF5B1432),
        labelStyle: const TextStyle(color: Color(0xFFF6ECFF)),
        secondaryLabelStyle: const TextStyle(color: Colors.white),
        shape: StadiumBorder(side: BorderSide(color: tokens.mapPanelBorder)),
      ),
    );
  }
}

double lerpDouble(double a, double b, double t) => a + (b - a) * t;

extension MapflowThemeContext on BuildContext {
  MapflowThemeTokens get mapflowTokens {
    return Theme.of(this).extension<MapflowThemeTokens>()!;
  }
}
