import 'dart:collection';
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:okane/database/database.dart';
import 'package:okane/ui/state/core.dart';
import 'package:okane/ui/utils.dart';

double getBalanceGraphScaling(double maxBalance) {
  final absMaxBalance = maxBalance.abs();
  if (absMaxBalance < 100) {
    return 10;
  } else if (absMaxBalance < 1000) {
    return 200;
  } else if (absMaxBalance < 10000) {
    return 1000;
  }

  return 10000;
}

class AccountBalanceGraphCard extends StatelessWidget {
  const AccountBalanceGraphCard({super.key});

  Future<List<FlSpot>> getAccountBalance() async {
    final coreCubit = GetIt.I.get<CoreCubit>();
    final today = toMidnight(DateTime.now());
    final transactions = await getLastTransactions(
      coreCubit.activeAccount!,
      today,
      30,
    );
    final totalBalance = await getTotalBalance(coreCubit.activeAccount!);

    // Compute the differences per day
    Map<int, double> differences = Map.fromEntries(
      List.generate(30, (i) => i).map((i) => MapEntry(i, 0)),
    );
    for (final item in transactions) {
      final diff = today.difference(toMidnight(item.date)).inDays;
      final balance = differences[diff]!;
      differences[diff] = balance + item.amount;
    }

    // Compute the balance
    final balances = HashMap<int, double>();
    balances[0] = totalBalance;
    for (final idx in List.generate(29, (i) => i + 1)) {
      balances[idx] = balances[idx - 1]! + differences[idx]!;
    }

    List<FlSpot> result = List.empty(growable: true);
    result.add(FlSpot(0, totalBalance));
    result.addAll(
      List.generate(
        28,
        (i) => i + 1,
      ).map((i) => FlSpot(i.toDouble(), balances[i]!)),
    );
    return result;
  }

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: [
            Text("Account balance"),
            SizedBox(
              height: 150,
              child: FutureBuilder(
                future: getAccountBalance(),
                builder: (context, snapshot) {
                  if (!snapshot.hasData) {
                    return CircularProgressIndicator();
                  }

                  final today = DateTime.now();
                  final maxBalance = snapshot.data!
                      .map((spot) => spot.y)
                      .reduce((acc, y) => y > acc ? y : acc);
                  return LineChart(
                    LineChartData(
                      minY:
                          snapshot.data!
                              .map((spot) => spot.y)
                              .reduce((acc, y) => y < acc ? y : acc) -
                          20,
                      maxY: maxBalance + 20,
                      titlesData: FlTitlesData(
                        bottomTitles: AxisTitles(
                          sideTitles: SideTitles(
                            interval: 4,
                            showTitles: true,
                            reservedSize: 40,
                            getTitlesWidget: (val, meta) {
                              final day = today.subtract(
                                Duration(days: val.toInt()),
                              );
                              return SideTitleWidget(
                                meta: meta,
                                child: Text(
                                  formatDateTime(day, formatYear: false),
                                ),
                              );
                            },
                          ),
                        ),
                        leftTitles: AxisTitles(
                          sideTitles: SideTitles(
                            showTitles: true,
                            reservedSize: 50,
                            interval: getBalanceGraphScaling(maxBalance),
                            getTitlesWidget:
                                (value, meta) => SideTitleWidget(
                                  meta: meta,
                                  child: Text(
                                    formatCurrency(value, precise: false),
                                  ),
                                ),
                          ),
                        ),
                        rightTitles: const AxisTitles(
                          sideTitles: SideTitles(showTitles: false),
                        ),
                        topTitles: const AxisTitles(
                          sideTitles: SideTitles(showTitles: false),
                        ),
                      ),
                      gridData: const FlGridData(show: false),
                      lineBarsData: [
                        LineChartBarData(
                          isCurved: false,
                          barWidth: 3,
                          dotData: const FlDotData(show: false),
                          spots: snapshot.data!,
                        ),
                      ],
                    ),
                  );
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}