import 'dart:async';

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

import '../../about/external/data/LiveSession.dart';
import '../../about/internal/application/CommitmentClass.dart';
import '../../about/internal/application/NotificationType.dart';
import '../../about/internal/application/ProofType.dart';
import '../../about/internal/application/TextType.dart';
import '../../designs/Component.dart';
import '../../designs/buttons/Buttons.dart';
import '../../designs/input/InputFields.dart';
import '../../designs/text/Text.dart';
import '../../utils/Colors.dart';
import '../../utils/CommonUtils.dart';
import '../../utils/Validators.dart';
import 'ConnectLiveTask.dart';
import 'LiveTask.dart';
import 'ViewLiveTask.dart';

/// The full-screen runner. Deliberately the only thing on screen: a task you
/// are running is not a row in a list, it is the thing you are doing.
class LiveTaskState extends State<LiveTask>
    with WidgetsBindingObserver
    implements ConnectLiveTask {
  ViewLiveTask? _model;

  late LiveSession _session;

  Timer? _ticker;

  /// Drives the display only. The elapsed value itself is derived from
  /// wall-clock, so a throttled ticker during screen-off cannot lose time.
  int _tick = 0;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);

    _session = LiveSession(
      commitmentId: widget.commitment.id ?? "",
      title: widget.commitment.title,
      goalTitle: widget.goalTitle,
      startedAt: DateTime.now(),
      requiredSeconds: widget.commitment.proofType == ProofType.Timer
          ? widget.commitment.proofTimerMinutes * 60
          : 0,
    );

    _session.resume();
  }

  @override
  Widget build(BuildContext context) {
    return ViewModelBuilder<ViewLiveTask>.reactive(
      viewModelBuilder: () => ViewLiveTask(context, this),
      onViewModelReady: (viewModel) {
        _model = viewModel;
        _initiate();
      },
      builder: (context, viewModel, child) => PopScope(
        // Leaving mid-run is a decision, not a back gesture.
        canPop: false,
        onPopInvokedWithResult: (didPop, result) {
          if (!didPop) {
            _onRequestExit();
          }
        },
        child: AnnotatedRegion<SystemUiOverlayStyle>(
          value: SystemUiOverlayStyle.light,
          child: Scaffold(
            backgroundColor: colorPrimaryDark,
            body: SafeArea(child: _runnerView()),
          ),
        ),
      ),
    );
  }

  void _initiate() {
    _startTicker();
    _model?.publishSession(_session);
  }

  void _startTicker() {
    _ticker?.cancel();
    _ticker = Timer.periodic(const Duration(seconds: 1), (timer) {
      if (!mounted) {
        return;
      }
      setState(() {
        _tick = _tick + 1;
      });

      // Refresh the lock-screen notification every 5s rather than every tick,
      // so the ongoing notification stays current without thrashing.
      if (_tick % 5 == 0 && _session.running) {
        _model?.publishSession(_session);
      }
    });
  }

  /// Backgrounding pauses the clock — that is what makes Timer proof mean
  /// something. The count is kept and shown rather than hidden.
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      if (!_session.running) {
        setState(() {
          _session.resume();
        });
        _model?.publishSession(_session);
      }
      return;
    }

    if (state == AppLifecycleState.paused ||
        state == AppLifecycleState.hidden) {
      if (_session.running) {
        setState(() {
          _session.pause();
          _session.backgroundedCount = _session.backgroundedCount + 1;
        });
        _model?.publishSession(_session);
      }
    }
  }

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

  void _onTogglePause() {
    setState(() {
      if (_session.running) {
        _session.pause();
      } else {
        _session.resume();
      }
    });
    _model?.publishSession(_session);
  }

  void _onFinish() {
    _model?.complete(widget.commitment, _session);
  }

  void _onRequestExit() {
    _model?.showApplicationNotification(
      NotificationType.warning,
      "Leave this running?",
      _session.satisfied()
          ? "You have met the requirement. You can finish it properly instead of walking away."
          : "You are ${formatClock(_session.remainingSeconds())} short. Leaving now logs nothing.",
      true,
      true,
      null,
      action: "Leave anyway",
      positiveAction: () {
        Navigator.pop(context);
        _model?.clearSession();
        Navigator.pop(context, false);
      },
    );
  }

  void _onAbandon() {
    final TextEditingController reason = TextEditingController();
    final GlobalKey<FormState> formKey = GlobalKey<FormState>();

    showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      backgroundColor: Colors.transparent,
      barrierColor: colorBlack.withValues(alpha: 0.7),
      builder: (BuildContext sheetContext) {
        return Padding(
          padding: EdgeInsets.only(
            bottom: MediaQuery.of(sheetContext).viewInsets.bottom,
          ),
          child: Container(
            decoration: BoxDecoration(
              color: colorSheetBackground,
              borderRadius: const BorderRadius.only(
                topLeft: Radius.circular(28),
                topRight: Radius.circular(28),
              ),
            ),
            child: SingleChildScrollView(
              padding: const EdgeInsets.fromLTRB(24, 24, 24, 32),
              child: Form(
                key: formKey,
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: [
                    text("ABANDONING MID-RUN", 9, TextType.Bold,
                        color: colorStandingLockdown, letterSpacing: 1.2),
                    const SizedBox(height: 10),
                    text(widget.commitment.title, 24, TextType.Light,
                        color: colorPrimaryDark, height: 1.2),
                    const SizedBox(height: 16),
                    inputField(
                      "Reason",
                      reason,
                      hint: "Why is this stopping here?",
                      validator: Validators.excuse,
                      maxLines: 3,
                    ),
                    const SizedBox(height: 20),
                    destructiveButton("Abandon", () {
                      if (formKey.currentState?.validate() != true) {
                        return;
                      }
                      Navigator.pop(sheetContext);
                      _model?.abandon(widget.commitment, reason.text.trim());
                    }),
                    const SizedBox(height: 8),
                    Center(
                      child: textButton("Keep going",
                          () => Navigator.pop(sheetContext), textSize: 13),
                    ),
                  ],
                ),
              ),
            ),
          ),
        );
      },
    );
  }

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

  Widget _runnerView() {
    final bool timed = _session.requiredSeconds > 0;

    final bool satisfied = _session.satisfied();

    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 20),
      child: Column(
        mainAxisSize: MainAxisSize.max,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          _runnerHeader(),
          _runnerClock(timed, satisfied),
          _runnerControls(timed, satisfied),
        ],
      ),
    );
  }

  Widget _runnerHeader() {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      mainAxisSize: MainAxisSize.min,
      children: [
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Row(
              children: [
                Container(
                  width: 7,
                  height: 7,
                  decoration: BoxDecoration(
                    color: _session.running ? colorPositive : colorWarning,
                    shape: BoxShape.circle,
                  ),
                ),
                const SizedBox(width: 8),
                text(
                  _session.running ? "IN PROGRESS" : "PAUSED",
                  9,
                  TextType.Bold,
                  color: colorWhite.withValues(alpha: 0.55),
                  letterSpacing: 1.4,
                ),
              ],
            ),
            iconButton(
              Icon(CupertinoIcons.xmark,
                  size: 15, color: colorWhite.withValues(alpha: 0.7)),
              _onRequestExit,
            ),
          ],
        ),
        const SizedBox(height: 28),
        if (widget.goalTitle.isNotEmpty) ...[
          text(widget.goalTitle.toUpperCase(), 10, TextType.Bold,
              color: colorWhite.withValues(alpha: 0.40), letterSpacing: 1.4),
          const SizedBox(height: 10),
        ],
        text(widget.commitment.title, 34, TextType.Light,
            color: colorWhite, height: 1.15),
        const SizedBox(height: 16),
        Row(
          children: [
            pill(
              classLabel(widget.commitment.commitmentClass),
              colorWhite,
              colorWhite.withValues(alpha: 0.12),
              textSize: 9,
            ),
            const SizedBox(width: 8),
            pill(
              proofLabel(widget.commitment.proofType),
              colorWhite.withValues(alpha: 0.75),
              colorWhite.withValues(alpha: 0.08),
              textSize: 9,
            ),
          ],
        ),
      ],
    );
  }

  Widget _runnerClock(bool timed, bool satisfied) {
    final int elapsed = _session.elapsedSeconds();

    return Column(
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        text(
          timed ? (satisfied ? "REQUIREMENT MET" : "REMAINING") : "ELAPSED",
          9,
          TextType.Bold,
          color: satisfied
              ? colorPositive
              : colorWhite.withValues(alpha: 0.40),
          letterSpacing: 1.6,
        ),
        const SizedBox(height: 18),
        text(
          timed && !satisfied
              ? formatClock(_session.remainingSeconds())
              : formatClock(elapsed),
          78,
          TextType.Light,
          color: colorWhite,
          height: 1.0,
        ),
        if (timed) ...[
          const SizedBox(height: 28),
          meter(
            _session.progress(),
            fill: satisfied ? colorPositive : colorWhite,
            track: colorWhite.withValues(alpha: 0.12),
            height: 5,
          ),
          const SizedBox(height: 14),
          text(
            satisfied
                ? "You can finish this now."
                : "Leaving the app pauses the clock.",
            12,
            TextType.Regular,
            color: colorWhite.withValues(alpha: 0.45),
            align: TextAlign.center,
          ),
        ],
        if (_session.backgroundedCount > 0) ...[
          const SizedBox(height: 18),
          pill(
            "Left ${_session.backgroundedCount}×",
            colorWarning,
            colorWarning.withValues(alpha: 0.12),
            textSize: 9,
          ),
        ],
      ],
    );
  }

  Widget _runnerControls(bool timed, bool satisfied) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        roundedCornerButton(
          satisfied || !timed ? "Finish" : "Finish early",
          _onFinish,
          background: satisfied || !timed ? colorWhite : colorWhite.withValues(alpha: 0.14),
          foreground: satisfied || !timed ? colorPrimaryDark : colorWhite,
          icon: CupertinoIcons.checkmark,
        ),
        const SizedBox(height: 10),
        outlinedActionButton(
          _session.running ? "Pause" : "Resume",
          _onTogglePause,
          foreground: colorWhite,
          icon: _session.running
              ? CupertinoIcons.pause_fill
              : CupertinoIcons.play_fill,
        ),
        const SizedBox(height: 6),
        Center(
          child: textButton(
            "Abandon this",
            _onAbandon,
            textSize: 12,
            color: colorWhite.withValues(alpha: 0.45),
          ),
        ),
      ],
    );
  }

  // ── ConnectLiveTask ───────────────────────────────────────────────────────

  @override
  void onCompleted() {
    _model?.showApplicationNotification(
      NotificationType.success,
      widget.commitment.wouldBeLate ? "Late complete" : "Done",
      widget.commitment.wouldBeLate
          ? "Recorded as a late complete — the window had already closed."
          : "${formatClock(_session.elapsedSeconds())} of focused work, recorded.",
      true,
      true,
      () {
        Navigator.pop(context, true);
      },
    );
  }

  @override
  void onTooEarly(int secondsRemaining) {
    _model?.showApplicationNotification(
      NotificationType.warning,
      "Not yet",
      "${formatClock(secondsRemaining)} still to go. The timer is the proof — finishing early would just be the checkbox again.",
      true,
      true,
      null,
    );
  }

  @override
  void onAbandoned() {
    Navigator.pop(context, true);
  }

  @override
  void dispose() {
    _ticker?.cancel();
    WidgetsBinding.instance.removeObserver(this);
    _model?.clearSession();
    super.dispose();
  }
}
