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 '../../core/utils/amount_utils.dart';
import 'expense_list_controller.dart';
import 'expense_model.dart';
import 'expense_api.dart';

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

class _ExpenseListPageState extends ConsumerState<ExpenseListPage> {
  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(expenseDateStartProvider.notifier).state = DateTime(
        now.year,
        now.month,
        1,
      );
      ref.read(expenseDateEndProvider.notifier).state = DateTime(
        now.year,
        now.month,
        DateTime(now.year, now.month + 1, 0).day,
      );
      ref.invalidate(expenseMyListProvider(''));
      _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(expenseKeywordProvider.notifier).state = _keyword;
    ref
        .read(expenseDateStartProvider.notifier)
        .state = _startDateCtrl.text.isNotEmpty
        ? DateTime.tryParse(_startDateCtrl.text)
        : null;
    ref
        .read(expenseDateEndProvider.notifier)
        .state = _endDateCtrl.text.isNotEmpty
        ? DateTime.tryParse(_endDateCtrl.text)
        : null;
    ref.read(expenseRefreshProvider.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(expenseMyListProvider(''), (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('searchExpense'),
                            style: TDSearchStyle.round,
                            onTextChanged: (String text) {
                              setState(() {
                                _keyword = text;
                              });
                              if (text.isEmpty) _applyFilter();
                            },
                            onSubmitted: (_) => _applyFilter(),
                          ),
                        ),
                        GestureDetector(
                          onTap: () {
                            final dir = ref.read(expenseSortDirProvider);
                            ref.read(expenseSortDirProvider.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(expenseSortDirProvider) == '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())
                        : _ExpenseListContent(
                            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/expense-detail'),
            backgroundColor: colors.primary,
            shape: const CircleBorder(),
            child: const Icon(Icons.bar_chart, color: Colors.white),
          ),
        ),
      ],
    );
  }
}

class _ExpenseListContent extends ConsumerWidget {
  final EasyRefreshController refreshCtrl;
  final Future<void> Function() onRefresh;
  final ScrollController scrollCtrl;
  const _ExpenseListContent({
    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(expenseMyListProvider(''));
    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<ExpenseModel>> itemsAsync,
    BuildContext context,
    WidgetRef ref,
  ) {
    final l10n = AppLocalizations.of(context);
    if (itemsAsync.isReloading) {
      final oldItems = itemsAsync.valueOrNull ?? [];
      if (oldItems.isEmpty) {
        return ListView(
          children: [
            const SizedBox(height: 120),
            EmptyState(message: l10n.get('noExpenses')),
          ],
        );
      }
      return ListView.builder(
        controller: scrollCtrl,
        padding: const EdgeInsets.fromLTRB(16, 16, 16, 24),
        itemCount: oldItems.length,
        itemBuilder: (_, i) {
          final item = oldItems[i];
          final applicant = item.deptName.isNotEmpty
              ? '${item.applicantName} · ${item.deptName}'
              : item.applicantName;
          final card = ListCard(
            cardNo: item.expenseNo,
            amount: formatAmount(item.totalAmount),
            subAmount: item.totalAmtnSh > 0
                ? formatAmount(item.totalAmtnSh)
                : null,
            applicant: applicant,
            description: item.purpose,
            date: du.DateUtils.formatDate(item.expenseDate ?? item.createTime),
            statusTag: _buildStatusTags(item, l10n, context),
            onTap: () {
              context.push('/expense/detail/${item.expenseNo}');
            },
          );
          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('noExpenses')),
        ],
      );
    }
    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 item = items[i];
        final applicant = item.deptName.isNotEmpty
            ? '${item.applicantName} · ${item.deptName}'
            : item.applicantName;
        final card = ListCard(
          cardNo: item.expenseNo,
          amount: formatAmount(item.totalAmount),
          subAmount: item.totalAmtnSh > 0
              ? formatAmount(item.totalAmtnSh)
              : null,
          applicant: applicant,
          description: item.purpose,
          date: du.DateUtils.formatDate(item.expenseDate ?? item.createTime),
          statusTag: _buildStatusTags(item, l10n, context),
          onTap: () {
            context.push('/expense/detail/${item.expenseNo}');
          },
        );
        return Padding(padding: const EdgeInsets.only(bottom: 16), child: card);
      },
    );
  }

  /// 构建状态 tag，放在卡片底部日期旁边
  Widget _buildStatusTags(
    ExpenseModel item,
    AppLocalizations l10n,
    BuildContext context,
  ) {
    final tags = <Widget>[];
    final colors = Theme.of(context).extension<AppColorsExtension>()!;
    if (item.isTransferred == 1) {
      tags.add(
        Container(
          padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
          decoration: BoxDecoration(
            color: colors.primary.withValues(alpha: 0.1),
            borderRadius: BorderRadius.circular(4),
          ),
          child: Text(
            l10n.get('statusTransferred'),
            style: TextStyle(
              fontSize: 11,
              fontWeight: FontWeight.w500,
              color: colors.primary,
            ),
          ),
        ),
      );
    }
    if (item.isClosed == 1) {
      tags.add(
        Container(
          padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
          decoration: BoxDecoration(
            color: colors.primary.withValues(alpha: 0.1),
            borderRadius: BorderRadius.circular(4),
          ),
          child: Text(
            l10n.get('statusClosed'),
            style: TextStyle(
              fontSize: 11,
              fontWeight: FontWeight.w500,
              color: colors.primary,
            ),
          ),
        ),
      );
    }
    if (item.isTransferred != 1 && item.isClosed != 1) {
      if (item.isAuditApproved) {
        tags.add(
          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,
              ),
            ),
          ),
        );
      } else {
        tags.add(
          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,
              ),
            ),
          ),
        );
      }
    }
    if (tags.isEmpty) return const SizedBox.shrink();
    return Row(mainAxisSize: MainAxisSize.min, children: tags);
  }
}
