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 '../../shared/widgets/nav_bar_config.dart';
import '../../core/theme/app_colors_extension.dart';
import '../../core/utils/date_utils.dart' as du;
import '../../core/auth/role_provider.dart';
import '../../shared/widgets/list_card.dart';
import '../../shared/widgets/status_tag.dart';
import '../../shared/widgets/empty_state.dart';
import '../../shared/widgets/skeleton_list_card.dart';
import '../../shared/widgets/list_filter_panel.dart';
import '../../shared/widgets/list_footer.dart';
import '../../core/i18n/app_localizations.dart';
import 'overtime_list_controller.dart';
import 'overtime_model.dart';

final _scopeProvider = StateProvider<String>((ref) => 'my');

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

class _OvertimeListPageState extends ConsumerState<OvertimeListPage>
    with TickerProviderStateMixin {
  List<String> _getTabLabels(AppLocalizations l10n) => [
    l10n.get('all'),
    l10n.get('draft'),
    l10n.get('pending'),
    l10n.get('approved'),
    l10n.get('rejected'),
    l10n.get('withdrawn'),
  ];
  static const _tabKeys = [
    '',
    'draft',
    'pending',
    'approved',
    'rejected',
    'withdrawn',
  ];

  late final TabController _tabCtrl;

  @override
  void initState() {
    super.initState();
    _tabCtrl = TabController(length: _tabKeys.length, vsync: this);
    _tabCtrl.addListener(() {
      if (!_tabCtrl.indexIsChanging) {
        ref.read(overtimeStatusFilterProvider.notifier).state =
            _tabKeys[_tabCtrl.index];
      }
    });
  }

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

  @override
  Widget build(BuildContext context) {
    final status = ref.watch(overtimeStatusFilterProvider);
    final dateStart = ref.watch(overtimeDateStartProvider);
    final dateEnd = ref.watch(overtimeDateEndProvider);
    final otTypeFilter = ref.watch(overtimeTypeFilterProvider);
    final l10n = AppLocalizations.of(context);
    final colors = Theme.of(context).extension<AppColorsExtension>()!;
    final isManager = ref.watch(isManagerProvider);

    // Sync TabController with external filter changes
    final targetIdx = _tabKeys.indexOf(status);
    if (targetIdx >= 0 &&
        _tabCtrl.index != targetIdx &&
        !_tabCtrl.indexIsChanging) {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        if (mounted) _tabCtrl.animateTo(targetIdx);
      });
    }

    final filterGroups = [
      FilterGroup(
        title: l10n.get('filterDateRange'),
        type: FilterGroupType.dateRange,
        sections: [
          FilterSection(
            label: l10n.get('filterDateRange'),
            type: FilterSectionType.dateRange,
            startDate: dateStart,
            endDate: dateEnd,
            onStartChanged: (v) =>
                ref.read(overtimeDateStartProvider.notifier).state = v,
            onEndChanged: (v) =>
                ref.read(overtimeDateEndProvider.notifier).state = v,
          ),
        ],
      ),
      FilterGroup(
        title: l10n.get('other'),
        type: FilterGroupType.other,
        sections: [
          FilterSection(
            label: l10n.get('overtimeType'),
            type: FilterSectionType.singleSelect,
            options: [
              FilterOption(
                value: 'workday',
                label: l10n.get('workdayOvertime'),
              ),
              FilterOption(
                value: 'weekend',
                label: l10n.get('weekendOvertime'),
              ),
              FilterOption(
                value: 'holiday',
                label: l10n.get('holidayOvertime'),
              ),
            ],
            selectedValue: otTypeFilter,
            onChanged: (v) =>
                ref.read(overtimeTypeFilterProvider.notifier).state = v,
          ),
        ],
      ),
    ];
    final hasFilter = ListFilterPanel.hasActiveFilter(filterGroups);
    final filterVersion = Object.hash(dateStart, dateEnd, otTypeFilter);
    final now = DateTime.now();
    void onFilterReset() {
      ref.read(overtimeDateStartProvider.notifier).state = null;
      ref.read(overtimeDateEndProvider.notifier).state = null;
      ref.read(overtimeTypeFilterProvider.notifier).state = null;
    }

    setNavBarTitle(context, ref, NavBarConfig(
      title: l10n.get('overtimeList'),
      showBack: true,
      showRight: true,
      rightWidget: GestureDetector(
        onTap: () => ListFilterPanel.show(
          context,
          groups: filterGroups,
          onReset: onFilterReset,
          onConfirm: () {},
          defaultStartDate: DateTime(now.year, now.month, 1),
          defaultEndDate: DateTime(now.year, now.month, now.day),
        ),
        child: Stack(
          clipBehavior: Clip.none,
          children: [
            Icon(
              TDIcons.filter,
              size: 22,
              color: hasFilter ? colors.primary : colors.textPrimary,
            ),
            if (hasFilter)
              Positioned(
                right: -2,
                top: -2,
                child: Container(
                  width: 6,
                  height: 6,
                  decoration: BoxDecoration(
                    color: colors.danger,
                    shape: BoxShape.circle,
                  ),
                ),
              ),
          ],
        ),
      ),
      hasFilter: hasFilter,
      filterVersion: filterVersion,
      onBack: () => context.pop(),
    ));
    return Column(
      children: [
        if (isManager)
          Container(
            color: colors.bgCard,
            padding: const EdgeInsets.fromLTRB(16, 0, 16, 8),
            child: _buildScopeChip(colors),
          ),
        Container(
          color: colors.bgCard,
          padding: EdgeInsets.zero,
          child: TDSearchBar(
            placeHolder: l10n.get('searchOvertime'),
            needCancel: true,
            style: TDSearchStyle.round,
          ),
        ),
        Container(
          color: colors.bgCard,
          padding: const EdgeInsets.symmetric(horizontal: 8),
          child: TDTabBar(
            tabs: _getTabLabels(l10n).map((l) => TDTab(text: l)).toList(),
            controller: _tabCtrl,
            isScrollable: true,
            labelColor: colors.primary,
            unselectedLabelColor: colors.textSecondary,
            outlineType: TDTabBarOutlineType.filled,
            showIndicator: true,
            indicatorColor: colors.primary,
            indicatorHeight: 3,
            dividerHeight: 0,
            labelPadding: const EdgeInsets.symmetric(horizontal: 12),
            onTap: (index) {
              ref.read(overtimeStatusFilterProvider.notifier).state =
                  _tabKeys[index];
            },
          ),
        ),

        Expanded(
          child: Container(
            color: colors.bgPage,
            child: TabBarView(
              controller: _tabCtrl,
              children: List.generate(_tabKeys.length, (tabIdx) {
                return _buildTabContent(tabIdx);
              }),
            ),
          ),
        ),
      ],
    );
  }

  Widget _buildScopeChip(AppColorsExtension colors) {
    final scope = ref.watch(_scopeProvider);
    final l10n = AppLocalizations.of(context);
    return Row(
      children: [
        GestureDetector(
          onTap: () => ref.read(_scopeProvider.notifier).state = 'my',
          child: Container(
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
            decoration: BoxDecoration(
              color: scope == 'my' ? colors.primary : colors.bgPage,
              borderRadius: BorderRadius.circular(16),
              border: scope == 'my' ? null : Border.all(color: colors.border),
            ),
            child: Text(
              l10n.get('scopeMyApplications'),
              style: TextStyle(
                fontSize: 13,
                color: scope == 'my' ? colors.bgCard : colors.textSecondary,
              ),
            ),
          ),
        ),
        const SizedBox(width: 8),
        GestureDetector(
          onTap: () => ref.read(_scopeProvider.notifier).state = 'sub',
          child: Container(
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
            decoration: BoxDecoration(
              color: scope == 'sub' ? colors.primary : colors.bgPage,
              borderRadius: BorderRadius.circular(16),
              border: scope == 'sub' ? null : Border.all(color: colors.border),
            ),
            child: Text(
              l10n.get('scopeSubordinates'),
              style: TextStyle(
                fontSize: 13,
                color: scope == 'sub' ? colors.bgCard : colors.textSecondary,
              ),
            ),
          ),
        ),
      ],
    );
  }

  Widget _buildTabContent(int tabIdx) {
    return _OvertimeTabContent(statusKey: _tabKeys[tabIdx]);
  }
}

class _OvertimeTabContent extends ConsumerWidget {
  final String statusKey;

  const _OvertimeTabContent({required this.statusKey});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final itemsAsync = ref.watch(overtimeListProvider(statusKey));
    final scope = ref.watch(_scopeProvider);

    if (itemsAsync.isLoading && !itemsAsync.hasValue) {
      return const SkeletonLoadingList();
    }

    return EasyRefresh(
      header: TDRefreshHeader(),
      onRefresh: () async {
        ref.read(overtimeRefreshProvider.notifier).state++;
      },
      child: _buildContent(itemsAsync, context, ref, scope),
    );
  }

  Widget _buildContent(
    AsyncValue<List<OvertimeModel>> itemsAsync,

    BuildContext context,
    WidgetRef ref,
    String scope,
  ) {
    final l10n = AppLocalizations.of(context);
    final colors = Theme.of(context).extension<AppColorsExtension>()!;
    final isSub = scope == 'sub';
    if (itemsAsync.isReloading) {
      final oldItems = itemsAsync.valueOrNull ?? [];
      if (oldItems.isEmpty) {
        return ListView(
          children: [
            const SizedBox(height: 120),
            EmptyState(message: l10n.get('noOvertimes')),
          ],
        );
      }
      return ListView.builder(
        padding: const EdgeInsets.fromLTRB(16, 16, 16, 24),
        itemCount: oldItems.length,
        itemBuilder: (_, i) {
          final desc = isSub
              ? '${oldItems[i].otType} · ${oldItems[i].compensationType}\n申请人: ${oldItems[i].applicantName} · ${oldItems[i].deptName}'
              : '${oldItems[i].otType} · ${oldItems[i].compensationType}';
          final card = ListCard(
            cardNo: oldItems[i].applicationNo,
            description: desc,
            amount:
                '${oldItems[i].otHours.toStringAsFixed(1)}${l10n.get('hours')}',
            amountColor: colors.textPrimary,
            date: du.DateUtils.formatDate(oldItems[i].otDate),
            statusTag: StatusTag.fromStatus(oldItems[i].status, l10n),
            onTap: () => context.push('/overtime/detail/${oldItems[i].id}'),
          );
          if (isSub && oldItems[i].status == 'pending') {
            return Padding(
              padding: const EdgeInsets.only(bottom: 16),
              child: _buildSwipeApprove(card, oldItems[i].id),
            );
          }
          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('noOvertimes')),
        ],
      );
    }

    return ListView.builder(
      padding: const EdgeInsets.fromLTRB(16, 16, 16, 24),
      itemCount: items.length + 1,
      itemBuilder: (_, i) {
        if (i == items.length) return ListFooter(itemCount: items.length);
        final desc = isSub
            ? '${items[i].otType} · ${items[i].compensationType}\n申请人: ${items[i].applicantName} · ${items[i].deptName}'
            : '${items[i].otType} · ${items[i].compensationType}';
        final card = ListCard(
          cardNo: items[i].applicationNo,
          description: desc,
          amount: '${items[i].otHours.toStringAsFixed(1)}${l10n.get('hours')}',
          amountColor: colors.textPrimary,
          date: du.DateUtils.formatDate(items[i].otDate),
          statusTag: StatusTag.fromStatus(items[i].status, l10n),
          onTap: () => context.push('/overtime/detail/${items[i].id}'),
        );
        if (isSub && items[i].status == 'pending') {
          return Padding(
            padding: const EdgeInsets.only(bottom: 16),
            child: _buildSwipeApprove(card, items[i].id),
          );
        }
        return Padding(padding: const EdgeInsets.only(bottom: 16), child: card);
      },
    );
  }

  Widget _buildSwipeApprove(Widget card, String itemId) {
    return Builder(
      builder: (ctx) {
        final screenWidth = MediaQuery.of(ctx).size.width;
        return TDSwipeCell(
          groupTag: 'overtime_approve',
          right: TDSwipeCellPanel(
            extentRatio: 100 / screenWidth,
            children: [
              TDSwipeCellAction(
                label: '',
                backgroundColor: Colors.transparent,
                builder: (_) => Container(
                  margin: const EdgeInsets.symmetric(
                    horizontal: 4,
                    vertical: 8,
                  ),
                  decoration: BoxDecoration(
                    color: Colors.green,
                    borderRadius: BorderRadius.circular(8),
                  ),
                  alignment: Alignment.center,
                  padding: const EdgeInsets.symmetric(horizontal: 12),
                  child: const Text(
                    '一键同意',
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 14,
                      fontWeight: FontWeight.w600,
                    ),
                  ),
                ),
                onPressed: (_) async {
                  final confirmed = await showDialog<bool>(
                    context: ctx,
                    builder: (dCtx) => TDAlertDialog(
                      title: '确认审批',
                      content: '确认同意该加班申请？',
                      leftBtn: TDDialogButtonOptions(
                        title: '取消',
                        action: () => Navigator.of(dCtx).pop(false),
                      ),
                      rightBtn: TDDialogButtonOptions(
                        title: '确认',
                        action: () => Navigator.of(dCtx).pop(true),
                      ),
                    ),
                  );
                  if (confirmed == true) {
                    // TODO: 接入实际审批 API
                    if (ctx.mounted) {
                      TDToast.showSuccess('已审批通过', context: ctx);
                    }
                  }
                },
              ),
            ],
          ),
          cell: card,
        );
      },
    );
  }
}
