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

import '../../about/external/data/Program.dart';
import '../../about/external/data/SessionLog.dart';
import '../../about/external/data/SessionTemplate.dart';
import '../../about/internal/application/NotificationType.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 '../../utils/IntegrityEngine.dart';
import 'ConnectTraining.dart';
import 'Training.dart';
import 'ViewTraining.dart';

class TrainingState extends State<Training> implements ConnectTraining {
  ViewTraining? _model;

  Program _program = Program();

  List<SessionTemplate> _sessions = <SessionTemplate>[];

  List<SessionLog> _history = <SessionLog>[];

  int _contacts = 0;

  bool _ceilingReached = false;

  int _recoveryHoursRemaining = 0;

  @override
  Widget build(BuildContext context) {
    return ViewModelBuilder<ViewTraining>.reactive(
      viewModelBuilder: () => ViewTraining(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?.loadProgram();
  }

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

  Widget _mobileView(BoxConstraints constraints) {
    return Sheet(
      eyebrow: _program.name.isEmpty ? "No program" : _program.name,
      title: "Training",
      onBack: _onBack,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        mainAxisSize: MainAxisSize.min,
        children: [
          if (_ceilingReached || _recoveryHoursRemaining > 0) ...[
            _stopCard(),
            const SizedBox(height: 24),
          ],
          if (_program.id == null)
            emptyState(
              CupertinoIcons.flame,
              "No active program",
              "Build a program with sessions, progression rules and scheduled deloads, and missed sessions start feeding your debt.",
            )
          else ...[
            _programCard(),
            const SizedBox(height: 28),
            sectionBreak("Sessions", caption: "${_sessions.length} per cycle"),
            if (_sessions.isEmpty)
              text("No sessions defined yet.", 13, TextType.Regular,
                  color: colorGrey2)
            else
              ..._sessions.map(_sessionRow),
            const SizedBox(height: 28),
            sectionBreak("Volume", caption: "this week"),
            _volumeCard(),
            const SizedBox(height: 28),
            sectionBreak("Recent", caption: "last sessions"),
            if (_history.isEmpty)
              text("Nothing logged yet.", 13, TextType.Regular,
                  color: colorGrey2)
            else
              ..._history.take(5).map(_historyRow),
          ],
        ],
      ),
    );
  }

  /// Plyo and recovery are the two places the app refuses rather than nags.
  Widget _stopCard() {
    final bool ceiling = _ceilingReached;

    return card(
      background: colorStandingLockdownBg,
      borderColor: colorStandingLockdown.withValues(alpha: 0.25),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisSize: MainAxisSize.min,
        children: [
          Row(
            children: [
              Icon(CupertinoIcons.hand_raised_fill,
                  size: 16, color: colorStandingLockdown),
              const SizedBox(width: 8),
              text(ceiling ? "CONTACT CEILING" : "RECOVERY", 9, TextType.Bold,
                  color: colorStandingLockdown, letterSpacing: 1.2),
            ],
          ),
          const SizedBox(height: 12),
          text(
            ceiling ? "Stop plyometrics this week." : "Not recovered yet.",
            22,
            TextType.Light,
            color: colorPrimaryDark,
          ),
          const SizedBox(height: 10),
          text(
            ceiling
                ? "You are at $_contacts of ${_program.weeklyContactCeiling} ground contacts. Connective tissue does not recover on a motivation schedule — this is the one place the app stops you."
                : "$_recoveryHoursRemaining hours left before the next hard lower-body session. Training through this is not discipline, it is a shortcut to an injury.",
            13,
            TextType.Regular,
            color: colorGrey2,
            height: 1.55,
          ),
        ],
      ),
    );
  }

  Widget _programCard() {
    return card(
      background: colorPrimaryDark,
      borderColor: colorPrimaryDark,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisSize: MainAxisSize.min,
        children: [
          text("ACTIVE PROGRAM", 9, TextType.Bold,
              color: colorWhite.withValues(alpha: 0.45), letterSpacing: 1.2),
          const SizedBox(height: 10),
          text(_program.name, 24, TextType.Light, color: colorWhite),
          const SizedBox(height: 20),
          Row(
            children: [
              Expanded(
                child: labelled(
                  "Weeks",
                  "${_program.weeks}",
                  valueSize: 18,
                  valueColor: colorWhite,
                  labelColor: colorWhite.withValues(alpha: 0.45),
                ),
              ),
              Expanded(
                child: labelled(
                  "Per week",
                  "${_program.sessionsPerWeek}",
                  valueSize: 18,
                  valueColor: colorWhite,
                  labelColor: colorWhite.withValues(alpha: 0.45),
                ),
              ),
              Expanded(
                child: labelled(
                  "Deloads",
                  "${_program.deloadWeeks.length}",
                  valueSize: 18,
                  valueColor: colorWhite,
                  labelColor: colorWhite.withValues(alpha: 0.45),
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }

  Widget _sessionRow(SessionTemplate session) {
    return Container(
      margin: const EdgeInsets.only(bottom: 10),
      child: card(
        padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 14),
        child: Row(
          children: [
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: [
                  text(session.name, 15, TextType.Medium,
                      color: colorPrimaryDark),
                  const SizedBox(height: 6),
                  text("${session.prescriptions.length} exercises", 11,
                      TextType.Regular, color: colorGrey2),
                ],
              ),
            ),
            if (session.highIntensityLowerBody)
              pill("HIGH LOAD", colorStandingWarned, colorStandingWarnedBg,
                  textSize: 9),
          ],
        ),
      ),
    );
  }

  /// Volume per muscle group, not "you went to the gym".
  Widget _volumeCard() {
    final Map<String, int> volume =
        IntegrityEngine.weeklySetsByMuscleGroup(_history);

    if (volume.isEmpty) {
      return card(
        child: text("No sets logged this week.", 13, TextType.Regular,
            color: colorGrey2),
      );
    }

    return card(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisSize: MainAxisSize.min,
        children: volume.entries.map((entry) {
          return Padding(
            padding: const EdgeInsets.only(bottom: 12),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisSize: MainAxisSize.min,
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    text(entry.key, 13, TextType.Regular,
                        color: colorPrimaryDark),
                    text("${entry.value} sets", 12, TextType.Bold,
                        color: colorGrey2),
                  ],
                ),
                const SizedBox(height: 6),
                meter(entry.value / 20),
              ],
            ),
          );
        }).toList(),
      ),
    );
  }

  Widget _historyRow(SessionLog session) {
    final bool watered = session.integrityScore > 0 &&
        session.integrityScore < 0.7;

    return Container(
      margin: const EdgeInsets.only(bottom: 10),
      child: card(
        padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 14),
        child: Row(
          children: [
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: [
                  text(session.templateName, 14, TextType.Medium,
                      color: colorPrimaryDark),
                  const SizedBox(height: 6),
                  text(
                    "${formatDate(session.startedAt)} · ${session.sets.length} sets · RPE ${session.sessionRpe.toStringAsFixed(1)}",
                    11,
                    TextType.Regular,
                    color: colorGrey2,
                  ),
                ],
              ),
            ),
            if (session.integrityScore > 0)
              pill(
                "${(session.integrityScore * 100).round()}%",
                watered ? colorStandingGrounded : colorPositive,
                watered ? colorStandingGroundedBg : colorStandingGoodBg,
                textSize: 9,
              ),
          ],
        ),
      ),
    );
  }

  // ── ConnectTraining ───────────────────────────────────────────────────────

  @override
  void onProgramLoaded(Program program, List<SessionTemplate> sessions) {
    setState(() {
      _program = program;
      _sessions = sessions;
    });
  }

  @override
  void onHistoryLoaded(List<SessionLog> sessions) {
    setState(() {
      _history = sessions;
    });
  }

  @override
  void onContactCeilingReached(int contacts, int ceiling) {
    setState(() {
      _contacts = contacts;
      _ceilingReached = true;
    });

    _model?.showApplicationNotification(
      NotificationType.warning,
      "Contact ceiling reached",
      "$contacts of $ceiling ground contacts this week. No more plyometrics until it resets.",
      true,
      true,
      null,
    );
  }

  @override
  void onRecoveryBlocked(int hoursRemaining) {
    setState(() {
      _recoveryHoursRemaining = hoursRemaining;
    });
  }
}
