import 'dart:math';

import 'package:filcnaplo/api/providers/user_provider.dart';
import 'package:filcnaplo/helpers/average_helper.dart';
import 'package:filcnaplo/models/settings.dart';
import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart';
import 'package:filcnaplo/utils/format.dart';
import 'package:filcnaplo_kreta_api/models/grade.dart';
import 'package:filcnaplo_kreta_api/models/subject.dart';
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
import 'package:filcnaplo_mobile_ui/screens/summary/summary_screen.i18n.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:auto_size_text/auto_size_text.dart';
import 'package:i18n_extension/i18n_widget.dart';

List<String> faces = [
  "(·.·)",
  "(≥o≤)",
  "(·_·)",
  "(˚Δ˚)b",
  "(^-^*)",
  "(='X'=)",
  "(>_<)",
  "(;-;)",
  "\\(^Д^)/",
  "\\(o_o)/",
];

class GradesBody extends StatefulWidget {
  const GradesBody({Key? key}) : super(key: key);

  @override
  _GradesBodyState createState() => _GradesBodyState();
}

class _GradesBodyState extends State<GradesBody> {
  late UserProvider user;
  late GradeProvider gradeProvider;
  late SettingsProvider settings;

  late double subjectAvg;
  late double endYearAvg;
  late String endYearAvgText;

  List<Widget> subjectTiles5 = [];
  List<Widget> subjectTiles3 = [];
  List<Widget> subjectTiles1 = [];

  int avgDropValue = 0;
  bool animation = false;

  List<Grade> getSubjectGrades(Subject subject, {int days = 0}) => gradeProvider
      .grades
      .where((e) =>
          e.subject == subject &&
          e.type == GradeType.midYear &&
          (days == 0 ||
              e.date.isBefore(DateTime.now().subtract(Duration(days: days)))))
      .toList();

  @override
  void initState() {
    super.initState();

    gradeProvider = Provider.of<GradeProvider>(context, listen: false);
    settings = Provider.of<SettingsProvider>(context, listen: false);

    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      setState(() {
        animation = true;
      });
    });
  }

  void generateTiles({required int filter}) {
    List<Subject> subjects = gradeProvider.grades
        .map((e) => e.subject)
        .toSet()
        .toList()
      ..sort((a, b) => a.name.compareTo(b.name));
    List<Widget> tiles = [];

    Map<Subject, double> subjectAvgs = {};

    var count = 1;

    for (Subject subject in subjects) {
      List<Grade> subjectGrades = getSubjectGrades(subject);

      double avg = AverageHelper.averageEvals(subjectGrades);
      if (avg != 0) subjectAvgs[subject] = avg;

      Widget widget = AnimatedContainer(
        curve: Curves.easeInOut,
        duration: Duration(milliseconds: 300 + (count * 120)),
        transform: Matrix4.translationValues(
            animation ? 0 : MediaQuery.of(context).size.width, 0, 0),
        child: Row(
          children: [
            GradeValueWidget(
              GradeValue(avg.round(), '', '', 100),
              fill: true,
              size: 28.0,
            ),
            const SizedBox(width: 8),
            Text(
              subject.renamedTo ?? subject.name.capital(),
              maxLines: 2,
              style: TextStyle(
                fontWeight: FontWeight.bold,
                fontSize: 20.0,
                color: Colors.white.withOpacity(0.98),
                fontStyle: settings.renamedSubjectsItalics && subject.isRenamed
                    ? FontStyle.italic
                    : null,
              ),
            )
          ],
        ),
      );

      if (avg.round() == filter) {
        tiles.add(widget);
        count++;
      }
    }

    if (tiles.isEmpty) {
      int index = Random(DateTime.now().minute).nextInt(faces.length);
      Widget faceWidget = Center(
        child: Text.rich(
          TextSpan(
            text: faces[index],
            style: const TextStyle(
              fontSize: 32.0,
              fontWeight: FontWeight.w500,
              color: Colors.white,
            ),
            children: [
              TextSpan(
                text: "\n${'no_grades'.i18n}",
                style: TextStyle(
                    fontSize: 18.0,
                    height: 2.0,
                    color: Colors.white.withOpacity(0.5)),
              ),
            ],
          ),
          textAlign: TextAlign.center,
        ),
      );
      tiles.insert(0, faceWidget);
    }

    subjectAvg = subjectAvgs.isNotEmpty
        ? subjectAvgs.values.fold(0.0, (double a, double b) => a + b) /
            subjectAvgs.length
        : 0.0;

    List<Grade> endYearGrades = gradeProvider.grades
        .where((grade) => grade.type == GradeType.endYear)
        .toList();
    endYearAvg = AverageHelper.averageEvals(endYearGrades, finalAvg: true);
    endYearAvgText = endYearAvg.toStringAsFixed(1);
    if (I18n.of(context).locale.languageCode != "en") {
      endYearAvgText = endYearAvgText.replaceAll(".", ",");
    }

    if (filter == 5) {
      subjectTiles5 = List.castFrom(tiles);
      if (subjectTiles5.length > 4) {
        subjectTiles5.length = 4;
      }
    } else if (filter == 3) {
      subjectTiles3 = List.castFrom(tiles);
      if (subjectTiles3.length > 3) {
        subjectTiles3.length = 3;
      }
    } else if (filter == 1) {
      subjectTiles1 = List.castFrom(tiles);
      if (subjectTiles1.length > 2) {
        subjectTiles1.length = 2;
      }
    }
  }

  void getGrades() {
    generateTiles(filter: 5);
    generateTiles(filter: 3);
    generateTiles(filter: 1);
  }

  @override
  Widget build(BuildContext context) {
    user = Provider.of<UserProvider>(context);
    settings = Provider.of<SettingsProvider>(context);

    getGrades();

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        SizedBox(
          height: ((100 * subjectTiles5.length) /
                  (subjectTiles5[0].runtimeType == AnimatedContainer
                      ? 1.95
                      : 1.2))
              .toDouble(),
          child: ListView.builder(
            padding: const EdgeInsets.only(left: 5),
            physics: const BouncingScrollPhysics(),
            itemCount: max(subjectTiles5.length, 1),
            itemBuilder: (context, index) {
              if (subjectTiles5.isNotEmpty) {
                EdgeInsetsGeometry panelPadding =
                    const EdgeInsets.symmetric(horizontal: 24.0);

                if (subjectTiles5[index].runtimeType == AnimatedContainer) {
                  return Padding(
                      padding: const EdgeInsets.only(top: 8),
                      child: subjectTiles5[index]);
                } else {
                  return Padding(
                      padding: panelPadding, child: subjectTiles5[index]);
                }
              } else {
                return Container();
              }
            },
          ),
        ),
        const SizedBox(height: 12.0),
        Text(
          'tryagain'.i18n,
          style: const TextStyle(
            fontWeight: FontWeight.bold,
            fontSize: 22.0,
            color: Colors.white,
          ),
        ),
        const SizedBox(height: 12.0),
        SizedBox(
          height: ((100 * subjectTiles3.length) /
                  (subjectTiles3[0].runtimeType == AnimatedContainer
                      ? 1.95
                      : 1.2))
              .toDouble(),
          child: ListView.builder(
            padding: const EdgeInsets.only(left: 5),
            physics: const BouncingScrollPhysics(),
            itemCount: max(subjectTiles3.length, 1),
            itemBuilder: (context, index) {
              if (subjectTiles3.isNotEmpty) {
                EdgeInsetsGeometry panelPadding =
                    const EdgeInsets.symmetric(horizontal: 24.0);

                if (subjectTiles3[index].runtimeType == AnimatedContainer) {
                  return Padding(
                      padding: const EdgeInsets.only(top: 8),
                      child: subjectTiles3[index]);
                } else {
                  return Padding(
                      padding: panelPadding, child: subjectTiles3[index]);
                }
              } else {
                return Container();
              }
            },
          ),
        ),
        const SizedBox(height: 12.0),
        Text(
          'oops'.i18n,
          style: const TextStyle(
            fontWeight: FontWeight.bold,
            fontSize: 22.0,
            color: Colors.white,
          ),
        ),
        const SizedBox(height: 12.0),
        SizedBox(
          height: ((100 * subjectTiles1.length) /
                  (subjectTiles1[0].runtimeType == AnimatedContainer
                      ? 1.95
                      : 1.2))
              .toDouble(),
          child: ListView.builder(
            padding: const EdgeInsets.only(left: 5),
            physics: const BouncingScrollPhysics(),
            itemCount: max(subjectTiles1.length, 1),
            itemBuilder: (context, index) {
              if (subjectTiles1.isNotEmpty) {
                EdgeInsetsGeometry panelPadding =
                    const EdgeInsets.symmetric(horizontal: 24.0);

                if (subjectTiles1[index].runtimeType == AnimatedContainer) {
                  return Padding(
                      padding: const EdgeInsets.only(top: 8),
                      child: subjectTiles1[index]);
                } else {
                  return Padding(
                      padding: panelPadding, child: subjectTiles1[index]);
                }
              } else {
                return Container();
              }
            },
          ),
        ),
        const SizedBox(height: 40.0),
        Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Text(
                'endyear_avg'.i18n,
                textAlign: TextAlign.center,
                style: const TextStyle(
                  fontWeight: FontWeight.bold,
                  fontSize: 22.0,
                  color: Colors.white,
                ),
              ),
              Container(
                margin: const EdgeInsets.only(top: 10.0),
                padding:
                    const EdgeInsets.symmetric(horizontal: 16.0, vertical: 4.0),
                decoration: BoxDecoration(
                  color: gradeColor(context: context, value: endYearAvg)
                      .withOpacity(.2),
                  border: Border.all(
                    color: (gradeColor(context: context, value: endYearAvg))
                        .withOpacity(0.0),
                    width: 2.0,
                  ),
                  borderRadius: BorderRadius.circular(45.0),
                ),
                child: AutoSizeText.rich(
                  TextSpan(
                    text: endYearAvgText,
                  ),
                  maxLines: 1,
                  minFontSize: 5,
                  textAlign: TextAlign.center,
                  style: TextStyle(
                    color: gradeColor(context: context, value: endYearAvg),
                    fontWeight: FontWeight.w800,
                    fontSize: 32.0,
                  ),
                ),
              ),
            ],
          ),
        ),
      ],
    );
  }
}