import 'dart:math';

import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/models/category.dart';
import 'package:didvan/models/enums.dart';
import 'package:didvan/models/statistic_data/statistic_data.dart';
import 'package:didvan/views/home/statistic/statistic_state.dart';
import 'package:didvan/views/home/statistic/widgets/statistic_overview.dart';
import 'package:didvan/views/widgets/categories_gird.dart';
import 'package:didvan/views/widgets/categories_list.dart';
import 'package:didvan/views/widgets/animated_visibility.dart';
import 'package:didvan/views/widgets/didvan/divider.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/state_handlers/empty_list.dart';
import 'package:didvan/views/widgets/state_handlers/sliver_state_handler.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class Statistic extends StatefulWidget {
  const Statistic({Key? key}) : super(key: key);

  @override
  State<Statistic> createState() => _StatisticState();
}

class _StatisticState extends State<Statistic> {
  final ScrollController _scrollController = ScrollController();

  bool _isAnimating = false;

  @override
  void initState() {
    _scrollController.addListener(() {
      _handleAnimations();
    });
    final state = context.read<StatisticState>();
    state.addListener(() {
      if (state.shouldColapse && mounted) {
        _handleAnimations(true);
        state.shouldColapse = false;
      }
    });
    state.init();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Consumer<StatisticState>(
      builder: (context, state, child) => Stack(
        children: [
          CustomScrollView(
            physics: _isAnimating
                ? const NeverScrollableScrollPhysics()
                : const ClampingScrollPhysics(),
            controller: _scrollController,
            slivers: [
              if (state.appState != AppState.failed)
                const SliverToBoxAdapter(
                  child: SizedBox(height: 140),
                ),
              if (state.appState != AppState.failed &&
                  state.markedStatistics.isNotEmpty)
                SliverPadding(
                  padding: const EdgeInsets.only(right: 16, bottom: 20),
                  sliver: SliverToBoxAdapter(
                    child: Align(
                      alignment: Alignment.centerRight,
                      child: AnimatedVisibility(
                        isVisible: !state.isColapsed,
                        duration: DesignConfig.lowAnimationDuration,
                        child: DidvanText(
                          'شاخص‌های منتخب',
                          style: Theme.of(context).textTheme.titleMedium,
                          color: Theme.of(context).colorScheme.title,
                        ),
                      ),
                    ),
                  ),
                ),
              SliverStateHandler<StatisticState>(
                onRetry: state.getStatistic,
                state: state,
                itemPadding: const EdgeInsets.only(
                  bottom: 20,
                  left: 16,
                  right: 16,
                ),
                emptyState: const EmptyList(),
                enableEmptyState: _itemCount(state) == 0,
                placeholder: StatisticOverview.placeHolder,
                builder: (context, state, index) {
                  if (index == state.markedStatistics.length) {
                    return index == 0
                        ? const SizedBox()
                        : const DidvanDivider(verticalPadding: 8);
                  }
                  bool isMarked = false;
                  StatisticData statistic;
                  if (index < state.markedStatistics.length) {
                    isMarked = true;
                    statistic = state.markedStatistics[index];
                  } else {
                    index--;
                    statistic =
                        state.statistics[index - state.markedStatistics.length];
                  }
                  return StatisticOverview(
                    statistic: statistic,
                    isMarked: isMarked,
                    onMarkChanged: state.changeMark,
                  );
                },
                childCount: _itemCount(state) + 1,
              ),
              SliverToBoxAdapter(
                child: SizedBox(
                  height: state.appState == AppState.busy
                      ? 300
                      : _itemCount(state) == 0
                          ? 150
                          : max(
                              MediaQuery.of(context).size.height -
                                  _itemCount(state) * 120,
                              0),
                ),
              ),
            ],
          ),
          if (state.appState != AppState.failed)
            CategoriesRow1(
              onSelected: _onCategorySelected,
              categories: List.from(state.categories)..removeAt(0),
              isColapsed: state.isColapsed,
              topPadding: 20,
              rightPadding: 300,
            ),
          if (state.appState != AppState.failed)
            CategoriesList(
              top: 0,
              categories: state.categories,
              isColapsed: state.isColapsed,
              onSelected: (id) {
                state.selectedCategoryId = id;
                state.getStatistic();
              },
              selectedCats: state.selectedCategory == null
                  ? []
                  : [state.selectedCategory!],
            ),
        ],
      ),
    );
  }

  int _itemCount(state) =>
      state.markedStatistics.length +
      (state.selectedCategoryId == 1 ? 0 : state.statistics.length);

  void _onCategorySelected(CategoryData category) {
    final state = context.read<StatisticState>();
    state.selectedCategoryId = 0;
    if (category.id != 0) {
      state.selectedCategoryId = category.id;
    }
    state.getStatistic();
  }

  void _handleAnimations([bool forceAnimate = false]) async {
    final state = context.read<StatisticState>();
    if (_isAnimating) return;
    final double position = _scrollController.offset;
    if (position > 5 && !state.isColapsed || forceAnimate) {
      state.isScrolled = true;
      _isAnimating = true;
      setState(() {});
      await _scrollController.animateTo(
        60,
        duration: DesignConfig.lowAnimationDuration,
        curve: Curves.easeIn,
      );
      _isAnimating = false;
      setState(() {});
    } else if (position < min(_scrollController.position.maxScrollExtent, 40) &&
        state.isColapsed) {
      state.isScrolled = false;
      _isAnimating = true;
      setState(() {});
      await _scrollController.animateTo(
        0,
        duration: DesignConfig.lowAnimationDuration,
        curve: Curves.easeIn,
      );
      _isAnimating = false;
      setState(() {});
    }
  }

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