// Flutter
import 'dart:async';

import 'package:flutter/material.dart';
import '/models/item_type.dart';

// Local
import '/db.dart';
import '/widgets/cards.dart';
import '/models/tracked_item.dart';

/// TODO:
/// - Projected Assets:
///   - Allow customization?
///   - Fix bug where editing an item does not reflect immediately when returning to Reports page.
///     - Currently reflects after going back to Reports the 2nd time.

double _assetTotal = -1,
    _expenseMonthly = -1,
    _expenseYearly = -1,
    _incomeMonthly = -1,
    _incomeYearly = -1;

class ProjectionPage extends StatefulWidget {
  const ProjectionPage({
    super.key,
  });

  @override
  State<ProjectionPage> createState() => _ProjectionPageState();
}

class _ProjectionPageState extends State<ProjectionPage> {
  bool _showProjections = true;

  @override
  void dispose() {
    _assetTotal = -2;
    _expenseMonthly = -2;
    _expenseYearly = -2;
    _incomeMonthly = -2;
    _incomeYearly = -2;
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // Summaries for display as well as calculation of totals for projections.
    Widget expenseSummary = SummaryCardForTotals(
      list: DatabaseHelper.instance.getExpenses(),
      itemType: ItemType.expense,
    );
    Widget incomeSummary = SummaryCardForTotals(
      list: DatabaseHelper.instance.getIncomes(),
      itemType: ItemType.income,
    );
    Widget assetSummary = SummaryCardForTotals(
      list: DatabaseHelper.instance.getAssets(),
      itemType: ItemType.asset,
    );

    // Calculations for the projections.
    Widget projections;
    if (_assetTotal < 0 ||
        _incomeMonthly < 0 ||
        _incomeYearly < 0 ||
        _expenseMonthly < 0 ||
        _expenseYearly < 0) {
      _showProjections = false;

      projections = Center(
        child: SizedBox(
          child: CircularProgressIndicator(),
        ),
      );

      Future.delayed(Duration(seconds: 1), () {
        setState(() {
          _showProjections = true;
        });
      });
    } else {
      double oneMonth = _assetTotal + _incomeMonthly - _expenseMonthly,
          threeMonths = _assetTotal + (3 * (_incomeMonthly - _expenseMonthly)),
          sixMonths = _assetTotal + (6 * (_incomeMonthly - _expenseMonthly)),
          oneYear = _assetTotal + (_incomeYearly - _expenseYearly),
          twoYears = _assetTotal + (2 * (_incomeYearly - _expenseYearly)),
          fiveYears = _assetTotal + (5 * (_incomeYearly - _expenseYearly));

      // Widgets to show the projections.
      Widget proj1 = SummaryCard(
        name: "One month from now...",
        leftText: "",
        middleText: oneMonth.toStringAsFixed(2),
        rightText: "",
      );
      Widget proj2 = SummaryCard(
        name: "Three months from now...",
        leftText: "",
        middleText: threeMonths.toStringAsFixed(2),
        rightText: "",
      );
      Widget proj3 = SummaryCard(
        name: "Half a year from now...",
        leftText: "",
        middleText: sixMonths.toStringAsFixed(2),
        rightText: "",
      );
      Widget proj4 = SummaryCard(
        name: "One year from now...",
        leftText: "",
        middleText: oneYear.toStringAsFixed(2),
        rightText: "",
      );
      Widget proj5 = SummaryCard(
        name: "Two years from now...",
        leftText: "",
        middleText: twoYears.toStringAsFixed(2),
        rightText: "",
      );
      Widget proj6 = SummaryCard(
        name: "Five years from now...",
        leftText: "",
        middleText: fiveYears.toStringAsFixed(2),
        rightText: "",
      );

      projections = Column(
        children: [
          proj1,
          proj2,
          proj3,
          proj4,
          proj5,
          proj6,
        ],
      );
    }

    // Return all of the UI elements.
    return ListView(
      children: [
        TitleCard(title: "Summaries"),
        expenseSummary,
        incomeSummary,
        assetSummary,
        TitleCard(title: "Projections"),
        projections,
      ],
    );
  }
}

class SummaryCardForTotals extends StatelessWidget {
  const SummaryCardForTotals({
    super.key,
    required this.list,
    required this.itemType,
  });

  final Future<List<TrackedItem>> list;
  final ItemType itemType;

  @override
  Widget build(BuildContext context) {
    String summaryTypeLabel = itemType.title.toString();

    return FutureBuilder<List<TrackedItem>>(
        future: list,
        builder: (
          BuildContext context,
          AsyncSnapshot<List<TrackedItem>> snapshot,
        ) {
          if (!snapshot.hasData) {
            return Text('Loading $summaryTypeLabel Section...');
          }

          // Calculate the total fields based on item type.
          double dailyTotal = 0, monthlyTotal = 0, yearlyTotal = 0;
          for (TrackedItem e in snapshot.data!) {
            if (e.type != itemType) {
              throw "List in SummaryCardForTotals has incorrect item types, abort!";
            }

            if (e.type == ItemType.asset) {
              monthlyTotal += e.amount;
            } else {
              dailyTotal += e.calcComparableAmountDaily();
              monthlyTotal += e.calcComparableAmountYearly() / 12;
              yearlyTotal += e.calcComparableAmountYearly();
            }
          }

          /* Load page variables based on calculated totals. */
          switch (itemType) {
            case ItemType.asset:
              _assetTotal = monthlyTotal;
              break;

            case ItemType.expense:
              _expenseMonthly = monthlyTotal;
              _expenseYearly = yearlyTotal;
              break;

            case ItemType.income:
              _incomeMonthly = monthlyTotal;
              _incomeYearly = yearlyTotal;
              break;

            default:
              throw UnimplementedError(
                "Item type ${itemType.title} not handled in SummaryCardForTotals!",
              );
          }

          /* Determine what needs displayed for the item type. */
          // Header
          String plural = snapshot.data!.length == 1 ? "" : "s";
          String header = "$summaryTypeLabel Total";
          header += itemType == ItemType.asset ? "" : "s";
          header += " (${snapshot.data!.length} Item$plural)";

          // Total Fields
          String dailyEstimate =
                  dailyTotal.toStringAsFixed(3).endsWith("0") ? "" : "~",
              monthlyEstimate =
                  monthlyTotal.toStringAsFixed(3).endsWith("0") ? "" : "~",
              yearlyEstimate =
                  yearlyTotal.toStringAsFixed(3).endsWith("0") ? "" : "~";
          String leftText = "", middleText = "", rightText = "";
          if (itemType == ItemType.asset) {
            middleText = "$monthlyEstimate${monthlyTotal.toStringAsFixed(2)}";
          } else {
            leftText = "$dailyEstimate${dailyTotal.toStringAsFixed(2)} Daily";
            middleText =
                "$monthlyEstimate${monthlyTotal.toStringAsFixed(2)} Monthly";
            rightText =
                "$yearlyEstimate${yearlyTotal.toStringAsFixed(2)} Yearly";
          }

          // Return the UI element.
          return SummaryCard(
            name: header,
            leftText: leftText,
            middleText: middleText,
            rightText: rightText,
          );
        });
  }
}