import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:island/models/poll.dart';
import 'package:island/pods/network.dart';
import 'package:island/widgets/alert.dart';
import 'package:island/widgets/poll/poll_stats_widget.dart';

class PollSubmit extends ConsumerStatefulWidget {
  const PollSubmit({
    super.key,
    required this.poll,
    required this.onSubmit,
    required this.stats,
    this.initialAnswers,
    this.onCancel,
    this.showProgress = true,
    this.isReadonly = false,
  });

  final SnPollWithStats poll;

  /// Callback when user submits all answers. Map questionId -> answer.
  final void Function(Map<String, dynamic> answers) onSubmit;

  /// Optional initial answers, keyed by questionId.
  final Map<String, dynamic>? initialAnswers;
  final Map<String, dynamic>? stats;

  /// Optional cancel callback.
  final VoidCallback? onCancel;

  /// Whether to show a progress indicator (e.g., "2 / N").
  final bool showProgress;

  final bool isReadonly;

  @override
  ConsumerState<PollSubmit> createState() => _PollSubmitState();
}

class _PollSubmitState extends ConsumerState<PollSubmit> {
  late final List<SnPollQuestion> _questions;
  int _index = 0;
  bool _submitting = false;
  bool _isModifying = false; // New state to track if user is modifying answers

  /// Collected answers, keyed by questionId
  late Map<String, dynamic> _answers;

  /// Local controller for free text input
  final TextEditingController _textController = TextEditingController();

  /// Local state holders for inputs to avoid rebuilding whole list
  String? _singleChoiceSelected; // optionId
  final Set<String> _multiChoiceSelected = {};
  bool? _yesNoSelected;
  int? _ratingSelected; // 1..5

  @override
  void initState() {
    super.initState();
    // Ensure questions are ordered by `order`
    _questions = [...widget.poll.questions]
      ..sort((a, b) => a.order.compareTo(b.order));
    _answers = Map<String, dynamic>.from(widget.initialAnswers ?? {});
    if (!widget.isReadonly) {
      _loadCurrentIntoLocalState();
      // If initial answers are provided, set _isModifying to false initially
      // so the "Modify" button is shown.
      if (widget.initialAnswers != null && widget.initialAnswers!.isNotEmpty) {
        _isModifying = false;
      }
    }
  }

  @override
  void didUpdateWidget(covariant PollSubmit oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.poll.id != widget.poll.id) {
      _index = 0;
      _answers = Map<String, dynamic>.from(widget.initialAnswers ?? {});
      _questions
        ..clear()
        ..addAll(
          [...widget.poll.questions]
            ..sort((a, b) => a.order.compareTo(b.order)),
        );
      if (!widget.isReadonly) {
        _loadCurrentIntoLocalState();
        // If poll ID changes, reset modification state
        _isModifying = false;
      }
    }
  }

  @override
  void dispose() {
    _textController.dispose();
    super.dispose();
  }

  SnPollQuestion get _current => _questions[_index];

  void _loadCurrentIntoLocalState() {
    final q = _current;
    final saved = _answers[q.id];

    _singleChoiceSelected = null;
    _multiChoiceSelected.clear();
    _yesNoSelected = null;
    _ratingSelected = null;
    _textController.text = '';

    switch (q.type) {
      case SnPollQuestionType.singleChoice:
        if (saved is String) _singleChoiceSelected = saved;
        break;
      case SnPollQuestionType.multipleChoice:
        if (saved is List) {
          _multiChoiceSelected.addAll(saved.whereType<String>());
        }
        break;
      case SnPollQuestionType.yesNo:
        if (saved is bool) _yesNoSelected = saved;
        break;
      case SnPollQuestionType.rating:
        if (saved is int) _ratingSelected = saved;
        break;
      case SnPollQuestionType.freeText:
        if (saved is String) _textController.text = saved;
        break;
    }
  }

  bool _isCurrentAnswered() {
    final q = _current;
    if (!q.isRequired) return true;

    switch (q.type) {
      case SnPollQuestionType.singleChoice:
        return _singleChoiceSelected != null;
      case SnPollQuestionType.multipleChoice:
        return _multiChoiceSelected.isNotEmpty;
      case SnPollQuestionType.yesNo:
        return _yesNoSelected != null;
      case SnPollQuestionType.rating:
        return (_ratingSelected ?? 0) > 0;
      case SnPollQuestionType.freeText:
        return _textController.text.trim().isNotEmpty;
    }
  }

  void _persistCurrentAnswer() {
    final q = _current;
    switch (q.type) {
      case SnPollQuestionType.singleChoice:
        if (_singleChoiceSelected == null) {
          _answers.remove(q.id);
        } else {
          _answers[q.id] = _singleChoiceSelected!;
        }
        break;
      case SnPollQuestionType.multipleChoice:
        if (_multiChoiceSelected.isEmpty) {
          _answers.remove(q.id);
        } else {
          _answers[q.id] = _multiChoiceSelected.toList(growable: false);
        }
        break;
      case SnPollQuestionType.yesNo:
        if (_yesNoSelected == null) {
          _answers.remove(q.id);
        } else {
          _answers[q.id] = _yesNoSelected!;
        }
        break;
      case SnPollQuestionType.rating:
        if (_ratingSelected == null) {
          _answers.remove(q.id);
        } else {
          _answers[q.id] = _ratingSelected!;
        }
        break;
      case SnPollQuestionType.freeText:
        final text = _textController.text.trim();
        if (text.isEmpty) {
          _answers.remove(q.id);
        } else {
          _answers[q.id] = text;
        }
        break;
    }
  }

  Future<void> _submitToServer() async {
    // Persist current question before final submit
    _persistCurrentAnswer();

    setState(() {
      _submitting = true;
    });

    try {
      final dio = ref.read(apiClientProvider);

      await dio.post(
        '/sphere/polls/${widget.poll.id}/answer',
        data: {'answer': _answers},
      );

      // Only call onSubmit after server accepts
      widget.onSubmit(Map<String, dynamic>.unmodifiable(_answers));

      showSnackBar('pollAnswerSubmitted'.tr());
      HapticFeedback.heavyImpact();
    } catch (e) {
      showErrorAlert(e);
    } finally {
      if (mounted) {
        setState(() {
          _submitting = false;
        });
      }
    }
  }

  void _next() {
    if (_submitting) return;
    _persistCurrentAnswer();
    if (_index < _questions.length - 1) {
      setState(() {
        _index++;
        _loadCurrentIntoLocalState();
      });
    } else {
      // Final submit to API
      _submitToServer();
    }
  }

  void _back() {
    if (_submitting) return;
    _persistCurrentAnswer();
    if (_index > 0) {
      setState(() {
        _index--;
        _loadCurrentIntoLocalState();
      });
    } else {
      // at the first question; allow cancel if provided
      widget.onCancel?.call();
    }
  }

  Widget _buildHeader(BuildContext context) {
    final q = _current;
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        if (widget.poll.title != null || widget.poll.description != null)
          Padding(
            padding: const EdgeInsets.only(bottom: 12),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                if (widget.poll.title != null)
                  Text(
                    widget.poll.title!,
                    style: Theme.of(context).textTheme.titleLarge,
                  ),
                if (widget.poll.description != null)
                  Padding(
                    padding: const EdgeInsets.only(top: 4),
                    child: Text(
                      widget.poll.description!,
                      style: Theme.of(context).textTheme.bodyMedium?.copyWith(
                        color: Theme.of(
                          context,
                        ).textTheme.bodyMedium?.color?.withOpacity(0.7),
                      ),
                    ),
                  ),
              ],
            ),
          ),
        if (widget.showProgress &&
            _isModifying) // Only show progress when modifying
          Text(
            '${_index + 1} / ${_questions.length}',
            style: Theme.of(context).textTheme.labelMedium,
          ),
        Row(
          children: [
            Expanded(
              child: Text(
                q.title,
                style: Theme.of(context).textTheme.titleMedium,
              ),
            ),
            if (q.isRequired)
              Padding(
                padding: const EdgeInsets.only(left: 8),
                child: Text(
                  '*',
                  style: Theme.of(context).textTheme.titleMedium?.copyWith(
                    color: Theme.of(context).colorScheme.error,
                  ),
                ),
              ),
          ],
        ),
        if (q.description != null)
          Padding(
            padding: const EdgeInsets.only(top: 4),
            child: Text(
              q.description!,
              style: Theme.of(context).textTheme.bodySmall?.copyWith(
                color: Theme.of(
                  context,
                ).textTheme.bodySmall?.color?.withOpacity(0.7),
              ),
            ),
          ),
      ],
    );
  }

  Widget _buildStats(BuildContext context, SnPollQuestion q) {
    return PollStatsWidget(question: q, stats: widget.stats);
  }

  Widget _buildBody(BuildContext context) {
    if (widget.initialAnswers != null && !widget.isReadonly && !_isModifying) {
      return const SizedBox.shrink(); // Collapse input fields if already submitted and not modifying
    }
    final q = _current;
    switch (q.type) {
      case SnPollQuestionType.singleChoice:
        return _buildSingleChoice(context, q);
      case SnPollQuestionType.multipleChoice:
        return _buildMultipleChoice(context, q);
      case SnPollQuestionType.yesNo:
        return _buildYesNo(context, q);
      case SnPollQuestionType.rating:
        return _buildRating(context, q);
      case SnPollQuestionType.freeText:
        return _buildFreeText(context, q);
    }
  }

  Widget _buildSingleChoice(BuildContext context, SnPollQuestion q) {
    final options = [...?q.options]..sort((a, b) => a.order.compareTo(b.order));
    return Column(
      children: [
        for (final opt in options)
          RadioListTile<String>(
            value: opt.id,
            groupValue: _singleChoiceSelected,
            onChanged: (val) => setState(() => _singleChoiceSelected = val),
            title: Text(opt.label),
            subtitle: opt.description != null ? Text(opt.description!) : null,
          ),
      ],
    );
  }

  Widget _buildMultipleChoice(BuildContext context, SnPollQuestion q) {
    final options = [...?q.options]..sort((a, b) => a.order.compareTo(b.order));
    return Column(
      children: [
        for (final opt in options)
          CheckboxListTile(
            value: _multiChoiceSelected.contains(opt.id),
            onChanged: (val) {
              setState(() {
                if (val == true) {
                  _multiChoiceSelected.add(opt.id);
                } else {
                  _multiChoiceSelected.remove(opt.id);
                }
              });
            },
            title: Text(opt.label),
            subtitle: opt.description != null ? Text(opt.description!) : null,
          ),
      ],
    );
  }

  Widget _buildYesNo(BuildContext context, SnPollQuestion q) {
    return Row(
      children: [
        Expanded(
          child: SegmentedButton<bool>(
            segments: [
              ButtonSegment(value: true, label: Text('yes'.tr())),
              ButtonSegment(value: false, label: Text('no'.tr())),
            ],
            selected: _yesNoSelected == null ? {} : {_yesNoSelected!},
            onSelectionChanged: (sel) {
              setState(() {
                _yesNoSelected = sel.isEmpty ? null : sel.first;
              });
            },
            multiSelectionEnabled: false,
          ),
        ),
      ],
    );
  }

  Widget _buildRating(BuildContext context, SnPollQuestion q) {
    const max = 5;
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: List.generate(max, (i) {
        final value = i + 1;
        final selected = (_ratingSelected ?? 0) >= value;
        return IconButton(
          icon: Icon(
            selected ? Icons.star : Icons.star_border,
            color: selected ? Colors.amber : null,
          ),
          onPressed: () {
            setState(() {
              _ratingSelected = value;
            });
          },
        );
      }),
    );
  }

  Widget _buildFreeText(BuildContext context, SnPollQuestion q) {
    return TextField(
      controller: _textController,
      maxLines: 6,
      decoration: const InputDecoration(border: OutlineInputBorder()),
    );
  }

  Widget _buildNavBar(BuildContext context) {
    final isLast = _index == _questions.length - 1;
    final canProceed = _isCurrentAnswered() && !_submitting;

    if (widget.initialAnswers != null && !_isModifying && !widget.isReadonly) {
      // If poll is submitted and not in modification mode, show "Modify" button
      return FilledButton.icon(
        icon: const Icon(Icons.edit),
        label: Text('modifyAnswers'.tr()),
        onPressed: () {
          setState(() {
            _isModifying = true;
            _index = 0; // Reset to first question for modification
            _loadCurrentIntoLocalState();
          });
        },
      );
    }

    return Row(
      children: [
        OutlinedButton.icon(
          icon: const Icon(Icons.arrow_back),
          label: Text(_index == 0 ? 'cancel'.tr() : 'back'.tr()),
          onPressed:
              _submitting
                  ? null
                  : () {
                    if (_index == 0 && _isModifying) {
                      // If at first question and in modification mode, go back to submitted view
                      setState(() {
                        _isModifying = false;
                      });
                    } else {
                      _back();
                    }
                  },
        ),
        const Spacer(),
        FilledButton.icon(
          icon:
              _submitting
                  ? const SizedBox(
                    width: 16,
                    height: 16,
                    child: CircularProgressIndicator(strokeWidth: 2),
                  )
                  : Icon(isLast ? Icons.check : Icons.arrow_forward),
          label: Text(isLast ? 'submit'.tr() : 'next'.tr()),
          onPressed: canProceed ? _next : null,
        ),
      ],
    );
  }

  Widget _buildSubmittedView(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        if (widget.poll.title != null || widget.poll.description != null)
          Padding(
            padding: const EdgeInsets.only(bottom: 12),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                if (widget.poll.title?.isNotEmpty ?? false)
                  Text(
                    widget.poll.title!,
                    style: Theme.of(context).textTheme.titleLarge,
                  ),
                if (widget.poll.description?.isNotEmpty ?? false)
                  Padding(
                    padding: const EdgeInsets.only(top: 4),
                    child: Text(
                      widget.poll.description!,
                      style: Theme.of(context).textTheme.bodyMedium?.copyWith(
                        color: Theme.of(
                          context,
                        ).textTheme.bodyMedium?.color?.withOpacity(0.7),
                      ),
                    ),
                  ),
              ],
            ),
          ),
        for (final q in _questions)
          Padding(
            padding: const EdgeInsets.only(bottom: 16.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Row(
                  children: [
                    Expanded(
                      child: Text(
                        q.title,
                        style: Theme.of(context).textTheme.titleMedium,
                      ),
                    ),
                    if (q.isRequired)
                      Padding(
                        padding: const EdgeInsets.only(left: 8),
                        child: Text(
                          '*',
                          style: Theme.of(
                            context,
                          ).textTheme.titleMedium?.copyWith(
                            color: Theme.of(context).colorScheme.error,
                          ),
                        ),
                      ),
                  ],
                ),
                if (q.description != null)
                  Padding(
                    padding: const EdgeInsets.only(top: 4),
                    child: Text(
                      q.description!,
                      style: Theme.of(context).textTheme.bodySmall?.copyWith(
                        color: Theme.of(
                          context,
                        ).textTheme.bodySmall?.color?.withOpacity(0.7),
                      ),
                    ),
                  ),
                _buildStats(context, q),
              ],
            ),
          ),
      ],
    );
  }

  Widget _buildReadonlyView(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        if (widget.poll.title != null || widget.poll.description != null)
          Padding(
            padding: const EdgeInsets.only(bottom: 12),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                if (widget.poll.title != null)
                  Text(
                    widget.poll.title!,
                    style: Theme.of(context).textTheme.titleLarge,
                  ),
                if (widget.poll.description != null)
                  Padding(
                    padding: const EdgeInsets.only(top: 4),
                    child: Text(
                      widget.poll.description!,
                      style: Theme.of(context).textTheme.bodyMedium?.copyWith(
                        color: Theme.of(
                          context,
                        ).textTheme.bodyMedium?.color?.withOpacity(0.7),
                      ),
                    ),
                  ),
              ],
            ),
          ),
        for (final q in _questions)
          Padding(
            padding: const EdgeInsets.only(bottom: 16.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Row(
                  children: [
                    Expanded(
                      child: Text(
                        q.title,
                        style: Theme.of(context).textTheme.titleMedium,
                      ),
                    ),
                    if (q.isRequired)
                      Padding(
                        padding: const EdgeInsets.only(left: 8),
                        child: Text(
                          '*',
                          style: Theme.of(
                            context,
                          ).textTheme.titleMedium?.copyWith(
                            color: Theme.of(context).colorScheme.error,
                          ),
                        ),
                      ),
                  ],
                ),
                if (q.description != null)
                  Padding(
                    padding: const EdgeInsets.only(top: 4),
                    child: Text(
                      q.description!,
                      style: Theme.of(context).textTheme.bodySmall?.copyWith(
                        color: Theme.of(
                          context,
                        ).textTheme.bodySmall?.color?.withOpacity(0.7),
                      ),
                    ),
                  ),
                _buildStats(context, q),
              ],
            ),
          ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    if (_questions.isEmpty) {
      return const SizedBox.shrink();
    }

    // If poll is already submitted and not in readonly mode, and not in modification mode, show submitted view
    if (widget.initialAnswers != null && !widget.isReadonly && !_isModifying) {
      return Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [_buildSubmittedView(context), _buildNavBar(context)],
      );
    }

    // If poll is in readonly mode, show readonly view
    if (widget.isReadonly) {
      return _buildReadonlyView(context);
    }

    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        _buildHeader(context),
        const SizedBox(height: 12),
        _AnimatedStep(
          key: ValueKey(_current.id),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [_buildBody(context), _buildStats(context, _current)],
          ),
        ),
        const SizedBox(height: 16),
        _buildNavBar(context),
      ],
    );
  }
}

/// Simple fade/slide transition between questions.
class _AnimatedStep extends StatelessWidget {
  const _AnimatedStep({super.key, required this.child});
  final Widget child;

  @override
  Widget build(BuildContext context) {
    return AnimatedSwitcher(
      duration: const Duration(milliseconds: 250),
      transitionBuilder: (child, anim) {
        final offset = Tween<Offset>(
          begin: const Offset(0.1, 0),
          end: Offset.zero,
        ).animate(anim);
        final fade = CurvedAnimation(parent: anim, curve: Curves.easeInOut);
        return FadeTransition(
          opacity: fade,
          child: SlideTransition(position: offset, child: child),
        );
      },
      child: child,
    );
  }
}
