// ignore_for_file: cascade_invocations

import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:habitrack_app/infrastructure/widget_wall/items_controller.dart';
import 'package:habitrack_app/infrastructure/widget_wall/items_state.dart';
import 'package:habitrack_app/main.dart';
import 'package:habitrack_app/sembast/timer.dart';
import 'package:intl/intl.dart';

class DataPoint {
  DataPoint({required this.date, required this.progress});
  DateTime date;
  double progress;
}

class TimerGraphWidget extends ConsumerStatefulWidget {
  TimerGraphWidget({super.key});

  @override
  ConsumerState<ConsumerStatefulWidget> createState() =>
      _TimerGraphWidgetState();

  final entries = <DataPoint>[
    DataPoint(date: DateTime(2024, 7, 7), progress: 0.75),
    DataPoint(date: DateTime(2024, 7, 7), progress: 0.75),
    DataPoint(date: DateTime(2024, 7, 7), progress: 0.75),
    DataPoint(date: DateTime(2024, 7, 7), progress: 0.75),
    DataPoint(date: DateTime(2024, 7, 7), progress: 0.75),
    DataPoint(date: DateTime(2024, 7, 7), progress: 0.75),
  ];
}

class _TimerGraphWidgetState extends ConsumerState<TimerGraphWidget> {
  final gradientColors = [
    Colors.cyan,
    Colors.blueAccent,
  ];
  final gradient2Colors = [
    Colors.amber,
    Colors.amberAccent,
  ];
  String _formatTime() {
    final minutesTotal =
        (_selectedValue == 'weekly') ? _timePlanned : _todayGoal;
    final hours = (minutesTotal / 60).floor();
    final minutes = (minutesTotal - (hours * 60)).toInt();
    return '$hours hours : $minutes minutes';
  }

  String _formatCurrent() {
    final secondsTotal =
        (_selectedValue == 'weekly') ? _timeCompleted : _todayCurrent;
    final hours = (secondsTotal / 3600).floor();
    final minutes = ((secondsTotal - (hours * 3600)) / 60).floor();
    return '$hours hours : $minutes minutes';
  }

  void _buildList(List<dynamic> value) {
    final items = value;
    _timeCompleted = 0;
    _timePlanned = 0;

    setState(() {
      _todayCurrent = 0;
      _todayGoal = 0;
      _weeklyPlannedEntries = [];
      _weeklyWorkedEntries = [];
      for (var i = 0; i <= 6; i++) {
        final itemToInsert = DataPoint(
          date: _latestDate.subtract(Duration(days: 6 - i)),
          progress: 0,
        );

        _weeklyPlannedEntries.add(itemToInsert);
      }

      for (var i = 0; i <= 6; i++) {
        final itemToInsert = DataPoint(
          date: _latestDate.subtract(Duration(days: 6 - i)),
          progress: 0,
        );
        _weeklyWorkedEntries.add(itemToInsert);
      }
    });
    for (final item in items) {
      if (_selectedValue == 'weekly' && item is TimerItem) {
        final parsedDate = DateTime.parse(item.createdOn);
        for (var i = 0; i <= 6; i++) {
          if (parsedDate.isBefore(_latestDate.subtract(Duration(days: i))) &&
              parsedDate.isAfter(_latestDate.subtract(Duration(days: i + 1)))) {
            logger.i('LOOPING');

            _timeCompleted += item.current;
            _timePlanned += item.goal;
            //  _maxTasks += 1;
            final hours = (item.goal / 60).ceil().toDouble();

            if (hours > _maxTime) {
              _maxTime = hours;
            }

            // Update maxAmount
            setState(() {
              _weeklyPlannedEntries.elementAt(6).progress = item.goal / 60;
              _weeklyWorkedEntries.elementAt(6).progress = item.current / 3600;

              //  _weeklyWorkedEntries.elementAt(6 - i).progress =
              //    _tasksCompleted.toDouble();
            });
          }
        }
      } else if (_selectedValue == 'daily' && item is TimerItem) {
        final parsedDate = DateTime.parse(item.createdOn);

        final oneDayAgo = _latestDate.subtract(const Duration(days: 1));

        if (parsedDate.isBefore(oneDayAgo)) {
          logger.i('More than a day old');
        } else if (parsedDate.isAfter(oneDayAgo) &&
            parsedDate.isBefore(_latestDate)) {
          logger.i('TOday');
          _todayCurrent += item.current;
          _todayGoal += item.goal;
        }
      }
    }
  }

  void _showPreviousWeek() {
    if (_selectedValue == 'weekly') {
      _latestDate = _latestDate.subtract(const Duration(days: 7));
    } else if (_selectedValue == 'daily') {
      logger.i('HMMM');
      _latestDate = _latestDate.subtract(const Duration(days: 1));
    }
    final items = ref.watch(itemsProvider);

    switch (items) {
      case AsyncError(:final error):
        logger.i('Error: $error');
      case AsyncData(:final value):
        final allItems = value;

        _buildList(allItems);
      default:
        logger.i('Hmmm, how can we help?');
    } // get current date
    // show past 7 days starting 14 days ago
  }

  void _showNextWeek() {
    logger.i('CURRENT: ${_todayCurrent / 60}');

    logger.i('MINUTES TOTAL: $_todayGoal');
    logger.i('PERCENTAGE: ${_todayCurrent / (_todayGoal * 60)}');
    if (_selectedValue == 'weekly') {
      _latestDate = _latestDate.add(const Duration(days: 7));
    } else if (_selectedValue == 'daily') {
      logger.i('HMMM');
      _latestDate = _latestDate.add(const Duration(days: 1));
    }
    if (!_latestDate.isAfter(DateTime.now())) {
      final items = ref.watch(itemsProvider);

      ref.watch(homeControllerProvider);
      switch (items) {
        case AsyncError(:final error):
          logger.i('Error: $error');
        case AsyncData(:final value):
          final allItems = value;

          _buildList(allItems);
        default:
          logger.i('Hmmm, how can we help?');
      } // get current date
    }

    // show past 7 days starting 14 days ago
  }

  String _getText() {
    final dateFormat = DateFormat('dd. MMM yyyy');

    if (_selectedValue == 'weekly' &&
        _latestDate.isAfter(DateTime.now().subtract(const Duration(days: 6)))) {
      return ' this past week';
    } else if (_selectedValue == 'weekly' &&
        !_latestDate
            .isAfter(DateTime.now().subtract(const Duration(days: 6)))) {
      return ' '
          'from'
          ' ${dateFormat.format(_latestDate.subtract(const Duration(days: 6)))}'
          ' to ${dateFormat.format(_latestDate)}';
    }
    final formattedDate = dateFormat.format(_latestDate);
    // return ' on ${_latestDate.toString().substring(6, 10)}';
    return ' on $formattedDate';
  }

  List<dynamic> thisWeekItems = [];
  List<dynamic> todayItems = [];
  String? _selectedValue = 'weekly';

  int _timeCompleted = 0;
  int _timePlanned = 0;
  double _maxTime = 0;
  DateTime _latestDate = DateTime.now();
  double _todayCurrent = 0;
  double _todayGoal = 0;

  List<DataPoint> _weeklyPlannedEntries = <DataPoint>[];
  List<DataPoint> _weeklyWorkedEntries = <DataPoint>[];

  @override
  Widget build(BuildContext context) {
    final items = ref.watch(itemsProvider);

    // ignore: unused_element
    double getProgress() {
      logger.i('CURRENT: $_todayCurrent');
      logger.i('GOAL: $_todayGoal');
      if (_todayGoal == 0) {
        return 0;
      }
      return _todayCurrent / _todayGoal;
    }

    ref.watch(homeControllerProvider);
    switch (items) {
      case AsyncError(:final error):
        logger.i('Error: $error');
      case AsyncData(:final value):
        final allItems = value;
        _buildList(allItems);
      default:
        logger.i('Hmmm, how can we help?');
    }

    final firstDate = _weeklyPlannedEntries[0].date;

    final flSpots = <FlSpot>[];
    for (final dataPoint in _weeklyPlannedEntries) {
      final xValue = _daysBetween(_weeklyPlannedEntries[0].date, dataPoint.date)
          .toDouble();
      final lcbd = FlSpot(
        xValue,
        dataPoint.progress,
      );

      flSpots.add(lcbd);
    }
    final weeklyWorkedSpots = <FlSpot>[];
    for (final dataPoint in _weeklyWorkedEntries) {
      final xValue =
          _daysBetween(_weeklyWorkedEntries[0].date, dataPoint.date).toDouble();
      final lcbd = FlSpot(xValue, dataPoint.progress);

      weeklyWorkedSpots.add(lcbd);
    }

    final df = DateFormat('dd. MMMM');

    return Column(
      children: [
        Container(
          height: 75,
          color: Theme.of(context).colorScheme.primaryContainer,
          margin: const EdgeInsets.only(bottom: 10),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              ElevatedButton(
                onPressed: _showPreviousWeek,
                style: ButtonStyle(
                  shape: WidgetStateProperty.all(
                    RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(10),
                    ),
                  ),
                ),
                child: const Text('Previous'),
              ),
              DropdownButton<String>(
                value: _selectedValue,
                borderRadius: BorderRadius.circular(10),
                onChanged: (value) {
                  setState(() {
                    _latestDate = DateTime.now();
                    _selectedValue = value;
                  });
                },
                items: const [
                  DropdownMenuItem(
                    value: 'daily',
                    child: Text('Daily'),
                  ),
                  DropdownMenuItem(
                    value: 'weekly',
                    child: Text('Weekly'),
                  ),
                ],
              ),
              ElevatedButton(
                onPressed: _showNextWeek,
                style: ButtonStyle(
                  shape: WidgetStateProperty.all(
                    RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(10),
                    ),
                  ),
                ),
                child: const Text('Next'),
              ),
            ],
          ),
        ),
        if (_selectedValue == 'weekly') ...[
          Container(
            padding:
                const EdgeInsets.only(bottom: 15, top: 15, right: 15, left: 5),
            child: SizedBox(
              width: MediaQuery.of(context).size.width * 0.90,
              height: MediaQuery.of(context).size.height * 0.5,
              child: LineChart(
                LineChartData(
                  minY: 0,
                  maxY: _maxTime,
                  lineBarsData: [
                    LineChartBarData(
                      isCurved: true,
                      preventCurveOverShooting: true,
                      spots: flSpots,
                      belowBarData: BarAreaData(
                        show: true,
                        gradient: LinearGradient(
                          colors: gradientColors
                              .map((color) => color.withOpacity(0.3))
                              .toList(),
                        ),
                      ),
                    ),
                    LineChartBarData(
                      color: Colors.amber,
                      isCurved: true,
                      isStrokeCapRound: true,
                      preventCurveOverShooting: true,
                      spots: weeklyWorkedSpots,
                      belowBarData: BarAreaData(
                        show: true,
                        gradient: LinearGradient(
                          colors: gradient2Colors
                              .map((color) => color.withOpacity(0.3))
                              .toList(),
                        ),
                      ),
                    ),
                  ],
                  titlesData: FlTitlesData(
                    rightTitles: const AxisTitles(
                      sideTitles: SideTitles(
                        reservedSize: 30,
                        interval: 20,
                      ),
                    ),
                    topTitles: const AxisTitles(
                      sideTitles: SideTitles(
                        interval: 20,
                      ),
                    ),
                    leftTitles: AxisTitles(
                      sideTitles: SideTitles(
                        showTitles: true,
                        reservedSize: 50,
                        getTitlesWidget: (value, meta) => Text(
                          '$value h',
                          style: const TextStyle(
                            fontSize: 10,
                            fontStyle: FontStyle.italic,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                        interval: 0.5,
                      ),
                    ),
                    bottomTitles: AxisTitles(
                      sideTitles: SideTitles(
                        reservedSize: 30,
                        getTitlesWidget: (value, meta) => Text(
                          style: const TextStyle(
                            fontSize: 10,
                            fontStyle: FontStyle.italic,
                            fontWeight: FontWeight.bold,
                          ),
                          df.format(
                            DateTime(
                              firstDate.year,
                              firstDate.month,
                              firstDate.day,
                            ).add(Duration(days: value.round())),
                          ),
                        ),
                        showTitles: true,
                        interval: 1,
                      ),
                    ),
                  ),
                ),
              ),
            ),
          ),
        ],
        if (_selectedValue == 'daily') ...[
          SizedBox(
            width: MediaQuery.of(context).size.width * 0.90,
            height: MediaQuery.of(context).size.height * 0.5,
            child: PieChart(
              PieChartData(
                sectionsSpace: 0,
                sections: [
                  PieChartSectionData(
                    value: _todayCurrent / 60, // Progress
                    color: Theme.of(context).colorScheme.primaryFixedDim,
                    radius: 60,
                    title: (_todayGoal > 0)
                        // ignore: lines_longer_than_80_chars
                        ? '${((_todayCurrent * 100 / 60) / _todayGoal).round()} %'
                        : '0 %',
                    titleStyle: TextStyle(
                      fontSize: 15,
                      fontWeight: FontWeight.bold,
                      color: Theme.of(context).colorScheme.secondary,
                    ),
                  ),
                  PieChartSectionData(
                    value: (_todayCurrent > 0)
                        ? (_todayGoal - (_todayCurrent / 60))
                        : 1, // Total - progress
                    color: Theme.of(context).colorScheme.secondary,
                    radius: 60,
                    showTitle: _todayCurrent <= 0,
                    titleStyle: TextStyle(
                      fontSize: 15,
                      fontWeight: FontWeight.bold,
                      color: Theme.of(context).colorScheme.primaryFixedDim,
                    ),
                    title: '0%',
                  ),
                ],
              ),
            ),
          ),
        ],
        SizedBox(
          width: MediaQuery.of(context).size.width * 0.90,
          child: Column(
            children: [
              Text(
                'You worked for ${_formatCurrent()}${_getText()}',
                style: Theme.of(context).textTheme.bodyMedium!.copyWith(
                      color: Theme.of(context).colorScheme.onPrimaryContainer,
                      fontSize: 15,
                      fontWeight: FontWeight.bold,
                    ),
              ),
              Text(
                'Out of a total goal of ${_formatTime()}${_getText()}',
                style: Theme.of(context).textTheme.bodyMedium!.copyWith(
                      color: Theme.of(context).colorScheme.onPrimaryContainer,
                      fontSize: 15,
                      fontWeight: FontWeight.bold,
                    ),
              ),
            ],
          ),
        ),
      ],
    );
  }

  int _daysBetween(DateTime from, DateTime to) {
    final d1 = DateTime(from.year, from.month, from.day);
    final d2 = DateTime(to.year, to.month, to.day);
    return (d2.difference(d1).inHours / 24).round();
  }
}
