import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:stacked/stacked.dart';

import '../../about/external/data/ExcuseCluster.dart';
import '../../about/internal/application/TextType.dart';
import '../../designs/Component.dart';
import '../../designs/Responsive.dart';
import '../../designs/Shell.dart';
import '../../designs/text/Text.dart';
import '../../utils/Colors.dart';
import '../../utils/CommonUtils.dart';
import 'ConnectExcuseReport.dart';
import 'ExcuseReport.dart';
import 'ViewExcuseReport.dart';

class ExcuseReportState extends State<ExcuseReport>
    implements ConnectExcuseReport {
  ViewExcuseReport? _model;

  List<ExcuseCluster> _clusters = <ExcuseCluster>[];

  @override
  Widget build(BuildContext context) {
    return ViewModelBuilder<ViewExcuseReport>.reactive(
      viewModelBuilder: () => ViewExcuseReport(context, this),
      onViewModelReady: (viewModel) {
        _model = viewModel;
        _initiate();
      },
      builder: (context, viewModel, child) => LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
          return Responsive(
            mobile: _mobileView(constraints),
            tablet: _mobileView(constraints),
            desktop: _mobileView(constraints),
          );
        },
      ),
    );
  }

  void _initiate() {
    _model?.loadClusters();
  }

  void _onBack() {
    Navigator.pop(context);
  }

  Widget _mobileView(BoxConstraints constraints) {
    final int total = _clusters.fold(0, (sum, item) => sum + item.occurrences);

    return Sheet(
      eyebrow: "Last 30 days",
      title: "Excuses",
      onBack: _onBack,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        mainAxisSize: MainAxisSize.min,
        children: [
          displayTitle("What you tell\nyourself."),
          const SizedBox(height: 14),
          text(
            "Every deferral you wrote, grouped. Read the concentrations rather than the totals — that is where the pattern is.",
            14,
            TextType.Regular,
            color: colorGrey2,
            height: 1.55,
          ),
          const SizedBox(height: 28),
          if (_clusters.isEmpty)
            emptyState(
              CupertinoIcons.text_quote,
              "Nothing to confront yet",
              "Excuses appear here once you have deferred a few things. There is no shame in an empty page.",
              accent: colorPositive,
            )
          else ...[
            card(
              background: colorPrimaryDark,
              borderColor: colorPrimaryDark,
              child: Row(
                children: [
                  Expanded(
                    child: labelled(
                      "Total excuses",
                      "$total",
                      valueSize: 30,
                      valueType: TextType.Light,
                      valueColor: colorWhite,
                      labelColor: colorWhite.withValues(alpha: 0.45),
                    ),
                  ),
                  Expanded(
                    child: labelled(
                      "Distinct kinds",
                      "${_clusters.length}",
                      valueSize: 30,
                      valueType: TextType.Light,
                      valueColor: colorWhite,
                      labelColor: colorWhite.withValues(alpha: 0.45),
                    ),
                  ),
                ],
              ),
            ),
            const SizedBox(height: 24),
            sectionBreak("The taxonomy", caption: "most frequent first"),
            ..._clusters.map(_clusterCard),
          ],
        ],
      ),
    );
  }

  Widget _clusterCard(ExcuseCluster cluster) {
    final MapEntry<int, int>? peakDay = _peak(cluster.byWeekday);
    final MapEntry<int, int>? peakHour = _peak(cluster.byHour);

    return Container(
      margin: const EdgeInsets.only(bottom: 12),
      child: card(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          mainAxisSize: MainAxisSize.min,
          children: [
            Row(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                Expanded(
                  child: text(cluster.label, 19, TextType.Light,
                      color: colorPrimaryDark),
                ),
                pill("${cluster.occurrences}×", colorPrimaryDark, colorMuted,
                    textSize: 10),
              ],
            ),
            if (cluster.insight.isNotEmpty) ...[
              const SizedBox(height: 14),
              Container(
                padding: const EdgeInsets.all(14),
                decoration: BoxDecoration(
                  color: colorInset,
                  borderRadius: BorderRadius.circular(12),
                  border: Border.all(color: colorBorder, width: 1),
                ),
                child: Row(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Icon(CupertinoIcons.quote_bubble_fill,
                        size: 14, color: colorGrey),
                    const SizedBox(width: 10),
                    Expanded(
                      child: text(cluster.insight, 13, TextType.Regular,
                          color: colorPrimaryDark, height: 1.55),
                    ),
                  ],
                ),
              ),
            ],
            hairline(margin: const EdgeInsets.symmetric(vertical: 16)),
            Row(
              children: [
                Expanded(
                  child: labelled(
                    "Worst day",
                    peakDay == null ? "—" : weekdayName(peakDay.key),
                    valueSize: 13,
                  ),
                ),
                Expanded(
                  child: labelled(
                    "Worst hour",
                    peakHour == null ? "—" : hourLabel(peakHour.key),
                    valueSize: 13,
                  ),
                ),
                Expanded(
                  child: labelled(
                    "Category",
                    cluster.dominantCategory.isEmpty
                        ? "—"
                        : cluster.dominantCategory,
                    valueSize: 13,
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }

  MapEntry<int, int>? _peak(Map<int, int> histogram) {
    if (histogram.isEmpty) {
      return null;
    }

    MapEntry<int, int>? peak;
    for (MapEntry<int, int> entry in histogram.entries) {
      if (peak == null || entry.value > peak.value) {
        peak = entry;
      }
    }
    return peak;
  }

  @override
  void onClustersLoaded(List<ExcuseCluster> clusters) {
    setState(() {
      _clusters = clusters;
    });
  }
}
