import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:tdesign_flutter/tdesign_flutter.dart';
import 'package:easy_refresh/easy_refresh.dart';
import '../../core/theme/app_colors_extension.dart';
import '../../core/utils/date_utils.dart' as du;
import '../../core/utils/responsive.dart';
import '../../shared/widgets/date_range_picker.dart';
import '../../shared/widgets/list_card.dart';
import '../../shared/widgets/empty_state.dart';
import '../../shared/widgets/app_skeletons.dart';
import '../../shared/widgets/list_footer.dart';
import '../../core/i18n/app_localizations.dart';
import 'overtime_apply_list_controller.dart';
import 'overtime_apply_model.dart';

class OvertimeApplyListPage extends ConsumerStatefulWidget {
  const OvertimeApplyListPage({super.key});
  @override
  ConsumerState<OvertimeApplyListPage> createState() =>
      _OvertimeApplyListPageState();
}

class _OvertimeApplyListPageState extends ConsumerState<OvertimeApplyListPage> {
  String _keyword = '';
  final _startDateCtrl = TextEditingController();
  final _endDateCtrl = TextEditingController();
  late final EasyRefreshController _refreshCtrl;
  bool _firstBuild = true;
  bool _invalidateDone = false;
  bool _filterLoading = false;

  final _scrollCtrl = ScrollController();
  bool _showBackToTop = false;

  @override
  void initState() {
    super.initState();
    final now = DateTime.now();
    _startDateCtrl.text =
        '${now.year}-${now.month.toString().padLeft(2, '0')}-01';
    _endDateCtrl.text =
        '${now.year}-${now.month.toString().padLeft(2, '0')}-${DateTime(now.year, now.month + 1, 0).day.toString().padLeft(2, '0')}';
    _refreshCtrl = EasyRefreshController();
    _scrollCtrl.addListener(() {
      final show = _scrollCtrl.hasClients && _scrollCtrl.offset > 300;
      if (show != _showBackToTop && mounted) {
        setState(() => _showBackToTop = show);
      }
    });
    WidgetsBinding.instance.addPostFrameCallback((_) {
      ref.read(overtimeApplyDateStartProvider.notifier).state = DateTime(
        now.year,
        now.month,
        1,
      );
      ref.read(overtimeApplyDateEndProvider.notifier).state = DateTime(
        now.year,
        now.month,
        DateTime(now.year, now.month + 1, 0).day,
      );
      ref.invalidate(overtimeApplyListProvider(''));
      _invalidateDone = true;
      setState(() {});
    });
  }

  @override
  void dispose() {
    _startDateCtrl.dispose();
    _endDateCtrl.dispose();
    _refreshCtrl.dispose();
    _scrollCtrl.dispose();
    super.dispose();
  }

  void _applyFilter() {
    FocusManager.instance.primaryFocus?.unfocus();
    setState(() => _filterLoading = true);
    _doRefresh();
  }

  Future<void> _doRefresh() async {
    ref.read(overtimeApplyKeywordProvider.notifier).state = _keyword;
    ref
        .read(overtimeApplyDateStartProvider.notifier)
        .state = _startDateCtrl.text.isNotEmpty
        ? DateTime.tryParse(_startDateCtrl.text)
        : null;
    ref
        .read(overtimeApplyDateEndProvider.notifier)
        .state = _endDateCtrl.text.isNotEmpty
        ? DateTime.tryParse(_endDateCtrl.text)
        : null;
    ref.read(overtimeApplyRefreshProvider.notifier).state++;
  }

  @override
  Widget build(BuildContext context) {
    final l10n = AppLocalizations.of(context);
    final colors = Theme.of(context).extension<AppColorsExtension>()!;
    final tdTheme = TDTheme.of(context);

    if (_invalidateDone) {
      ref.listen(overtimeApplyListProvider(''), (prev, next) {
        if (_firstBuild && !next.isLoading && !next.isReloading) {
          setState(() => _firstBuild = false);
          WidgetsBinding.instance.addPostFrameCallback((_) {
            if (mounted) setState(() {});
          });
        }
        if (_filterLoading && !next.isReloading && !next.isLoading) {
          setState(() => _filterLoading = false);
        }
      });
    }

    return Stack(
      children: [
        Column(
          children: [
            Container(
              decoration: BoxDecoration(
                color: colors.bgCard,
                border: Border(
                  bottom: BorderSide(color: tdTheme.componentStrokeColor),
                ),
              ),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Padding(
                    padding: const EdgeInsets.fromLTRB(16, 8, 16, 0),
                    child: DateRangePicker(
                      startCtrl: _startDateCtrl,
                      endCtrl: _endDateCtrl,
                      onChanged: () {
                        setState(() {});
                        _applyFilter();
                      },
                    ),
                  ),
                  const SizedBox(height: 8),
                  Padding(
                    padding: const EdgeInsets.fromLTRB(0, 0, 12, 8),
                    child: Row(
                      children: [
                        Expanded(
                          child: TDSearchBar(
                            placeHolder: l10n.get('searchOvertimeApply'),
                            style: TDSearchStyle.round,
                            onTextChanged: (String text) {
                              setState(() {
                                _keyword = text;
                              });
                              if (text.isEmpty) _applyFilter();
                            },
                            onSubmitted: (_) => _applyFilter(),
                          ),
                        ),
                        GestureDetector(
                          onTap: () {
                            final dir = ref.read(overtimeApplySortDirProvider);
                            ref
                                .read(overtimeApplySortDirProvider.notifier)
                                .state = dir == 'ASC'
                                ? 'DESC'
                                : 'ASC';
                            _applyFilter();
                          },
                          child: Container(
                            width: 40,
                            height: 40,
                            decoration: BoxDecoration(
                              color: colors.primary,
                              borderRadius: BorderRadius.circular(20),
                            ),
                            child: Center(
                              child: Icon(
                                ref.watch(overtimeApplySortDirProvider) == 'ASC'
                                    ? Icons.arrow_upward
                                    : Icons.arrow_downward,
                                color: Colors.white,
                                size: 20,
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
            Expanded(
              child: Container(
                color: colors.bgPage,
                child: Stack(
                  children: [
                    _firstBuild
                        ? const Center(child: SkeletonLoadingList())
                        : _OvertimeApplyListContent(
                            refreshCtrl: _refreshCtrl,
                            onRefresh: _doRefresh,
                            scrollCtrl: _scrollCtrl,
                          ),
                    if (_filterLoading) ...[
                      Container(color: colors.bgPage.withValues(alpha: 0.6)),
                      const Center(
                        child: TDLoading(
                          size: TDLoadingSize.medium,
                          icon: TDLoadingIcon.activity,
                        ),
                      ),
                    ],
                  ],
                ),
              ),
            ),
          ],
        ),
        AnimatedPositioned(
          duration: const Duration(milliseconds: 200),
          bottom: _showBackToTop ? 80 : -60,
          left: 0,
          right: 0,
          child: Center(
            child: GestureDetector(
              onTap: () {
                if (_scrollCtrl.hasClients) {
                  _scrollCtrl.jumpTo(0);
                }
              },
              child: AnimatedOpacity(
                duration: const Duration(milliseconds: 200),
                opacity: _showBackToTop ? 1.0 : 0.0,
                child: Container(
                  width: 36,
                  height: 36,
                  decoration: BoxDecoration(
                    color: colors.primary400,
                    shape: BoxShape.circle,
                    boxShadow: [
                      BoxShadow(
                        color: Colors.black.withValues(alpha: 0.15),
                        blurRadius: 6,
                        offset: const Offset(0, 2),
                      ),
                    ],
                  ),
                  child: const Icon(
                    Icons.keyboard_arrow_up,
                    color: Colors.white,
                    size: 22,
                  ),
                ),
              ),
            ),
          ),
        ),
        Positioned(
          right: 16,
          bottom: 16,
          child: FloatingActionButton(
            onPressed: () => context.push('/report/overtime-apply-detail'),
            backgroundColor: colors.primary,
            shape: const CircleBorder(),
            child: const Icon(Icons.bar_chart, color: Colors.white),
          ),
        ),
      ],
    );
  }
}

class _OvertimeApplyListContent extends ConsumerWidget {
  final EasyRefreshController refreshCtrl;
  final Future<void> Function() onRefresh;
  final ScrollController scrollCtrl;
  const _OvertimeApplyListContent({
    required this.refreshCtrl,
    required this.onRefresh,
    required this.scrollCtrl,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final r = ResponsiveHelper.of(context);
    final itemsAsync = ref.watch(overtimeApplyListProvider(''));
    if (itemsAsync.isLoading && !itemsAsync.hasValue) {
      return Center(
        child: ConstrainedBox(
          constraints: BoxConstraints(maxWidth: r.listMaxWidth),
          child: const SkeletonLoadingList(),
        ),
      );
    }
    return Center(
      child: ConstrainedBox(
        constraints: BoxConstraints(maxWidth: r.listMaxWidth),
        child: EasyRefresh(
          controller: refreshCtrl,
          header: TDRefreshHeader(),
          onRefresh: onRefresh,
          child: _buildContent(itemsAsync, context, ref),
        ),
      ),
    );
  }

  Widget _buildContent(
    AsyncValue<List<OvertimeApplyModel>> itemsAsync,
    BuildContext context,
    WidgetRef ref,
  ) {
    final l10n = AppLocalizations.of(context);
    final colors = Theme.of(context).extension<AppColorsExtension>()!;
    if (itemsAsync.isReloading) {
      final oldItems = itemsAsync.valueOrNull ?? [];
      if (oldItems.isEmpty) {
        return ListView(
          children: [
            const SizedBox(height: 120),
            EmptyState(message: l10n.get('noOvertimeApplications')),
          ],
        );
      }
      return ListView.builder(
        controller: scrollCtrl,
        padding: const EdgeInsets.fromLTRB(16, 16, 16, 24),
        itemCount: oldItems.length,
        itemBuilder: (_, i) {
          final m = oldItems[i];
          final card = _buildListCard(m, l10n, colors, context);
          return Padding(
            padding: const EdgeInsets.only(bottom: 16),
            child: card,
          );
        },
      );
    }
    if (itemsAsync.hasError) {
      return ListView(
        children: [
          const SizedBox(height: 120),
          EmptyState(message: l10n.get('loadFailed')),
        ],
      );
    }
    final items = itemsAsync.requireValue;
    if (items.isEmpty) {
      return ListView(
        children: [
          const SizedBox(height: 120),
          EmptyState(message: l10n.get('noOvertimeApplications')),
        ],
      );
    }
    return ListView.builder(
      controller: scrollCtrl,
      padding: const EdgeInsets.fromLTRB(16, 16, 16, 24),
      itemCount: items.length + 1,
      itemBuilder: (_, i) {
        if (i == items.length) return ListFooter(itemCount: items.length);
        final m = items[i];
        final card = _buildListCard(m, l10n, colors, context);
        return Padding(padding: const EdgeInsets.only(bottom: 16), child: card);
      },
    );
  }

  Widget _buildListCard(
    OvertimeApplyModel m,
    AppLocalizations l10n,
    AppColorsExtension colors,
    BuildContext context,
  ) {
    final deptLabel = m.depName.isNotEmpty
        ? '${m.salName} · ${m.depName}'
        : m.salName;
    final desc = m.rem.isNotEmpty
        ? '${m.reason}\n${l10n.get('remark')}: ${m.rem}'
        : m.reason;
    return ListCard(
      cardNo: m.jbNo,
      amount: m.totalJbHours > 0 ? '${m.totalJbHours.toStringAsFixed(1)}${l10n.get('hours')}' : '',
      amountColor: colors.timePrimary,
      applicant: deptLabel,
      description: desc,
      date: m.jbDd != null ? du.DateUtils.formatDate(m.jbDd!) : '',
      statusTag: _buildStatusTag(m, l10n, colors),
      onTap: () {
        context.push('/overtime-apply/detail/${m.jbNo}');
      },
    );
  }

  Widget _buildStatusTag(
    OvertimeApplyModel item,
    AppLocalizations l10n,
    AppColorsExtension colors,
  ) {
    if (item.isAuditApproved) {
      return Container(
        padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
        decoration: BoxDecoration(
          color: colors.success.withValues(alpha: 0.1),
          borderRadius: BorderRadius.circular(4),
        ),
        child: Text(
          l10n.get('statusApproved'),
          style: TextStyle(
            fontSize: 11,
            fontWeight: FontWeight.w500,
            color: colors.success,
          ),
        ),
      );
    }
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
      decoration: BoxDecoration(
        color: colors.statusGray.withValues(alpha: 0.1),
        borderRadius: BorderRadius.circular(4),
      ),
      child: Text(
        l10n.get('statusPending'),
        style: TextStyle(
          fontSize: 11,
          fontWeight: FontWeight.w500,
          color: colors.statusGray,
        ),
      ),
    );
  }
}
