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

import '../../about/external/data/Commitment.dart';
import '../../about/external/data/Goal.dart';
import '../../about/internal/application/CommitmentStatus.dart';
import '../../about/internal/application/NotificationType.dart';
import '../../about/internal/application/ProofType.dart';
import '../../about/internal/application/TextType.dart';
import '../../configs/Navigator.dart';
import '../../designs/Checkbox.dart';
import '../../designs/Component.dart';
import '../../designs/Responsive.dart';
import '../../designs/Shell.dart';
import '../../designs/buttons/Buttons.dart';
import '../../designs/text/Text.dart';
import '../../utils/Colors.dart';
import '../../utils/CommonUtils.dart';
import '../../utils/DebtEngine.dart';
import '../commitment/NewCommitment.dart';
import '../live/LiveTask.dart';
import 'ConnectGoalDetail.dart';
import 'GoalDetail.dart';
import 'ViewGoalDetail.dart';

class GoalDetailState extends State<GoalDetail>
    implements ConnectGoalDetail {
  ViewGoalDetail? _model;

  Goal _goal = Goal();

  List<Commitment> _tasks = <Commitment>[];

  bool _changed = false;

  /// Ticked locally, awaiting the server.
  final Set<String> _ticked = <String>{};

  @override
  Widget build(BuildContext context) {
    return ViewModelBuilder<ViewGoalDetail>.reactive(
      viewModelBuilder: () => ViewGoalDetail(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() {
    setState(() {
      _goal = widget.goal;
    });
    _model?.loadTasks(widget.goal);
  }

  // ── Handlers ──────────────────────────────────────────────────────────────

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

  void _onStartTask(Commitment task) {
    _model?.startTask(task);
  }

  /// Ticking completes the task without opening the runner — the runner is for
  /// work you actually want timed.
  void _onTick(Commitment task) {
    if (task.id == null || _ticked.contains(task.id)) {
      return;
    }

    setState(() {
      _ticked.add(task.id!);
    });

    _model?.tick(task);
  }

  void _onAddTask() async {
    final result = await GroundedNavigation()
        .navigateToPageWithData(const NewCommitment(), context);

    if (result == true) {
      _changed = true;
      _model?.loadTasks(_goal);
    }
  }

  // ── Views ─────────────────────────────────────────────────────────────────

  Widget _mobileView(BoxConstraints constraints) {
    final List<Commitment> open = _tasks
        .where((task) =>
            task.status != CommitmentStatus.Completed &&
            task.status != CommitmentStatus.LateCompleted &&
            task.status != CommitmentStatus.Abandoned)
        .toList();

    final List<Commitment> done = _tasks
        .where((task) =>
            task.status == CommitmentStatus.Completed ||
            task.status == CommitmentStatus.LateCompleted)
        .toList();

    return Sheet(
      eyebrow: "Goal",
      title: _goal.title,
      onBack: _onBack,
      action: chromeAction(CupertinoIcons.add, _onAddTask),
      banner: _progressBanner(),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        mainAxisSize: MainAxisSize.min,
        children: [
          if (_goal.description.isNotEmpty) ...[
            text(_goal.description, 15, TextType.Regular,
                color: colorGrey2, height: 1.6),
            const SizedBox(height: 28),
          ],
          sectionBreak("To do", caption: "${open.length} open"),
          if (open.isEmpty)
            emptyState(
              CupertinoIcons.square_list,
              "Nothing scheduled",
              "Add the actual sessions — Monday shoulders, Wednesday legs — and they start counting.",
            )
          else
            ...open.map(_taskRow),
          if (done.isNotEmpty) ...[
            const SizedBox(height: 28),
            sectionBreak("Done", caption: "${done.length}"),
            ...done.map(_doneRow),
          ],
          const SizedBox(height: 24),
          roundedCornerButton("Add a task", _onAddTask,
              icon: CupertinoIcons.add),
        ],
      ),
    );
  }

  Widget _progressBanner() {
    return Container(
      padding: const EdgeInsets.fromLTRB(16, 14, 16, 14),
      decoration: BoxDecoration(
        color: colorWhite.withValues(alpha: 0.08),
        borderRadius: BorderRadius.circular(16),
      ),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              text("PROGRESS", 9, TextType.Bold,
                  color: colorWhite.withValues(alpha: 0.45),
                  letterSpacing: 1.2),
              text("${(_goal.progress * 100).round()}%", 13, TextType.Bold,
                  color: colorWhite),
            ],
          ),
          const SizedBox(height: 12),
          meter(
            _goal.progress,
            fill: colorWhite,
            track: colorWhite.withValues(alpha: 0.14),
            height: 5,
          ),
        ],
      ),
    );
  }

  /// A task row leads with the action: the point of opening a goal is to start
  /// something, not to admire the list.
  Widget _taskRow(Commitment task) {
    final Color accent = classColor(task.commitmentClass);

    final bool late = task.windowClosed;

    return Container(
      margin: const EdgeInsets.only(bottom: 10),
      child: card(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          mainAxisSize: MainAxisSize.min,
          children: [
            TickRow(
              checked: _ticked.contains(task.id),
              title: task.title,
              accent: accent,
              onTick: () => _onTick(task),
              detail: Row(
                children: [
                  text(formatWindow(task), 11, TextType.Regular,
                      color: colorGrey2),
                  const SizedBox(width: 9),
                  Container(
                    width: 3,
                    height: 3,
                    decoration: BoxDecoration(
                        color: colorGrey, shape: BoxShape.circle),
                  ),
                  const SizedBox(width: 9),
                  text(formatMinutes(task.estMinutes), 11, TextType.Regular,
                      color: colorGrey2),
                ],
              ),
              trailing: pill(proofLabel(task.proofType), colorGrey2, colorMuted,
                  textSize: 9),
            ),
            if (late) ...[
              const SizedBox(height: 12),
              Row(
                children: [
                  pill(overdueLabel(task), colorStandingGrounded,
                      colorStandingGroundedBg, textSize: 9),
                  const SizedBox(width: 6),
                  pill("−${formatDebt(DebtEngine.commitmentDebt(task))}",
                      colorGrey2, colorMuted, textSize: 9),
                ],
              ),
            ],
            const SizedBox(height: 14),
            roundedCornerButton(
              "Start",
              () => _onStartTask(task),
              icon: CupertinoIcons.play_fill,
              verticalPadding: 13,
            ),
          ],
        ),
      ),
    );
  }

  Widget _doneRow(Commitment task) {
    final bool late = task.status == CommitmentStatus.LateCompleted;

    return Container(
      margin: const EdgeInsets.only(bottom: 8),
      child: card(
        padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 13),
        child: TickRow(
          checked: true,
          locked: true,
          title: task.title,
          accent: late ? colorStandingWarned : colorPositive,
          trailing: late
              ? pill("Late", colorStandingWarned, colorStandingWarnedBg,
                  textSize: 9)
              : null,
        ),
      ),
    );
  }

  // ── ConnectGoalDetail ─────────────────────────────────────────────────────

  @override
  void onGoalLoaded(Goal goal, List<Commitment> tasks) {
    setState(() {
      _ticked.removeWhere((id) => tasks.every((task) => task.id != id));
      _goal = goal;
      _tasks = tasks;
    });
  }

  @override
  void onTaskTicked(Commitment task, bool late) {
    _changed = true;
    _model?.loadTasks(_goal);

    if (!late) {
      return;
    }

    _model?.showApplicationNotification(
      NotificationType.warning,
      "Late complete",
      "The window had already closed. This is recorded as a late complete — it reduces the debt but does not clear it.",
      true,
      true,
      null,
    );
  }

  @override
  void onTickFailed(Commitment task) {
    setState(() {
      _ticked.remove(task.id);
    });
  }

  @override
  void onTaskReady(Commitment task) async {
    // The runner takes over the whole screen — a task you are running is the
    // thing you are doing, not a row in a list.
    final result = await GroundedNavigation().navigateToPageWithData(
      LiveTask(commitment: task, goalTitle: _goal.title),
      context,
    );

    if (result == true) {
      _changed = true;
      _model?.loadTasks(_goal);
    }
  }
}
