import 'dart:math';

import 'package:daily_challenge/daily_challenge.dart';
import 'package:daily_challenge/ui/pages/award/trophy_decoration.dart';
import 'package:daily_challenge/ui/pages/award/trophy_exhibit_controller.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:get/get.dart' hide Rx;
import 'package:guru_widgets/guru_widgets.dart';
import 'package:design/design.dart';
import 'package:guru_widgets/theme/guru_theme.dart';
import 'package:guru_utils/datetime/datetime_utils.dart';

/// Created by Haoyi on 2023/10/11
///

part 'trophy_exhibit_widget.g.dart';

typedef DailyCalendarNavigator = void Function(
    DateTime focusMonth, int achieved);

@DesignSpec(width: 750, height: 1624, specMode: SpecMode.useGet)
abstract class TrophyAwardDesignSpec implements BasicDesignSpec {
  @SpecEdgeInsets.only(top: SpecVertical(40, consistent: true), bottom: SpecVertical(100, consistent: true))
  EdgeInsets get padding;

  @SpecEdgeInsets.only(
      start: SpecHorizontal(22.5),
      end: SpecHorizontal(22.5),
      bottom: SpecVertical(8, consistent: true))
  EdgeInsets get yearItemPadding;

  @SpecWidth(200)
  double get trophySize;

  @SpecEdgeInsets.only(top: SpecHeight(24, consistent: true), bottom: SpecHeight(72, consistent: true))
  EdgeInsets get monthNamePadding;

  @SpecAbsoluteFontSize(28)
  double get monthNameFontSize;

  @SpecHeight(200, consistent: true)
  double get yearlyHeaderHeight;

  @SpecEdgeInsets.only(top: SpecHeight(56, consistent: true), bottom: SpecHeight(64, consistent: true))
  EdgeInsets get yearHeaderPadding;

  @SpecAbsoluteFontSize(40)
  double get yearHeaderFontSize;

  @SpecSize(SpecWidth(140), SpecHeight(2, consistent: true))
  Size get gradientLineSize;

  @SpecHeight(26, consistent: true)
  double get gradientLineTopSpacing;

  @SpecHorizontal(16)
  double get gradientLineSpacing;

  static TrophyAwardDesignSpec get() {
    return _TrophyAwardDesignSpec.get();
  }
}

class TrophyExhibitTheme {
  final Color? yearColor;
  final Color? monthNameColor;
  final Gradient? headerGradient;

  static TrophyExhibitTheme defaultTheme = TrophyExhibitTheme();

  TrophyExhibitTheme(
      {this.yearColor, this.monthNameColor, this.headerGradient});
}

class _UIHolder {
  ThemeData? _theme;
  GuruThemeData? _guruTheme;
  TrophyExhibitTheme? _exhibitTheme;
  late TrophyAwardDesignSpec _designSpec;

  _UIHolder();

  void attach(BuildContext context) {
    _theme ??= Theme.of(context);
    _guruTheme ??= GuruTheme.of(context);
    _exhibitTheme ??= _guruTheme?.getCustomTheme<TrophyExhibitTheme>(
            TrophyExhibitTheme.defaultTheme.runtimeType) ??
        TrophyExhibitTheme.defaultTheme;
    _designSpec = TrophyAwardDesignSpec.get();
  }
}

mixin _UIData {
  final _UIHolder _uiHolder = _UIHolder();

  ThemeData get theme => _uiHolder._theme ?? ThemeData();

  GuruThemeData get guruTheme => _uiHolder._guruTheme ?? GuruThemeData();

  TrophyExhibitTheme? get exhibitTheme => _uiHolder._exhibitTheme;

  TrophyAwardDesignSpec get designSpec => _uiHolder._designSpec;
}

class TrophyExhibitWidget extends GetWidget<TrophyExhibitController>
    with _UIData {
  final DailyCalendarNavigator? dailyCalendarNavigator;

  TrophyExhibitWidget({super.key, this.dailyCalendarNavigator});

  Widget buildTrophy(int yearMonth, Color monthNameColor) {
    return GestureDetector(
      onTap: () {
        final yearMonthDateTime =
            DateTimeUtils.createDateTimeFromYearMonth(yearMonth);
        DailyChallengeManager.instance
            .setFocusDateAfterPageResume(yearMonthDateTime);
        dailyCalendarNavigator?.call(
            yearMonthDateTime, controller.getAchievedAward(yearMonth));
      },
      child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.start,
          children: [
            AdaptiveImage(controller.getTrophyImage(yearMonth),
                width: designSpec.trophySize, height: designSpec.trophySize),
            Padding(
                padding: designSpec.monthNamePadding,
                child: SizedBox(
                    width: designSpec.trophySize,
                    child: Text(
                        controller
                            .monthName[(yearMonth % 100).clamp(1, 12) - 1],
                            textAlign: TextAlign.center,
                            overflow: TextOverflow.ellipsis,
                        style: TextStyle(
                            fontSize: designSpec.monthNameFontSize,
                            fontWeight: GuruTheme.fwMedium,
                            height: 1.25,
                            color: monthNameColor))))
          ]),
    );
  }

  Widget buildYearTrophy(int year) {
    final now = DateTime.now();
    final startLimit = DateTimeUtils.generateYearMonthNum(
        DailyChallengeManager.instance.config.start);
    final endLimit = DateTimeUtils.generateYearMonthNum(now);
    final start =
        max(DateTimeUtils.generateYearMonthNum(DateTime(year, 1)), startLimit);
    final end =
        min(DateTimeUtils.generateYearMonthNum(DateTime(year, 12)), endLimit);
    final monthNameColor = exhibitTheme?.monthNameColor ??
        guruTheme.colorScheme.primaryContentColor ??
        Colors.black;
    final trophyGrid = GridView.count(
        crossAxisCount: 3,
        shrinkWrap: true,
        childAspectRatio: 0.7078,
        physics: const NeverScrollableScrollPhysics(),
        padding: EdgeInsets.zero,
        children: [
          for (int yearMonth = end; yearMonth >= start; --yearMonth)
            buildTrophy(yearMonth, monthNameColor)
        ]);

    final yearColor = exhibitTheme?.yearColor ??
        guruTheme.colorScheme.primaryContentColor ??
        Colors.black;

    return DecoratedBox(
        decoration: YearlyTrophiesDecoration(
            enabled: year != now.year,
            gradient: exhibitTheme?.headerGradient,
            height: designSpec.yearlyHeaderHeight),
        child: Padding(
          padding: designSpec.yearItemPadding,
          child: year != now.year
              ? Column(
                  children: [
                    Padding(
                        padding: designSpec.yearHeaderPadding,
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Container(
                              margin: EdgeInsets.only(top: designSpec.gradientLineTopSpacing),
                              child: DecoratedBox(
                                decoration: BoxDecoration(
                                    gradient: LinearGradient(
                                        begin: Alignment.centerLeft,
                                        end: Alignment.centerRight,
                                        colors: [
                                      Colors.transparent,
                                      yearColor
                                    ])),
                                child: SizedBox.fromSize(
                                    size: designSpec.gradientLineSize))),
                            SizedSpacer(width: designSpec.gradientLineSpacing),
                            Text(year.toString(),
                                style: TextStyle(
                                  height: 1.25,
                                    fontSize: designSpec.yearHeaderFontSize,
                                    fontWeight: GuruTheme.fwSemiBold,
                                    color: yearColor)),
                            SizedSpacer(width: designSpec.gradientLineSpacing),
                            Container(
                              margin: EdgeInsets.only(top: designSpec.gradientLineTopSpacing),
                              child: DecoratedBox(
                                decoration: BoxDecoration(
                                    gradient: LinearGradient(
                                        end: Alignment.centerLeft,
                                        begin: Alignment.centerRight,
                                        colors: [
                                      Colors.transparent,
                                      yearColor
                                    ])),
                                child: SizedBox.fromSize(
                                    size: designSpec.gradientLineSize))),
                            
                          ],
                        )),
                    trophyGrid
                  ],
                )
              : trophyGrid,
        ));
  }

  @override
  Widget build(BuildContext context) {
    _uiHolder.attach(context);
    final now = DateTime.now();
    final limitStartYear = DailyChallengeManager.instance.config.start.year;
    final years = [
      for (var year = now.year; year >= limitStartYear; --year) year
    ];
    return ListView.builder(
        padding: designSpec.padding,
        itemBuilder: (context, index) {
          return buildYearTrophy(years[index]);
        },
        itemCount: years.length);
  }
}
