import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:tdesign_flutter/tdesign_flutter.dart';
import '../../core/i18n/app_localizations.dart';
import '../../core/theme/app_colors_extension.dart';
import '../../shared/widgets/app_skeletons.dart';
import '../../shared/widgets/date_range_picker.dart';
import 'package:skeletonizer/skeletonizer.dart';
import '../../shared/widgets/list_footer.dart';
import '../overtime/overtime_apply_api.dart';
import '../overtime/ot_report_model.dart';

/// 加班明细报表 - 页面24

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

class _OvertimeDetailReportPageState
    extends ConsumerState<OvertimeDetailReportPage> {
  static const _monthI18nKeys = [
    '', 'tdJanuary', 'tdFebruary', 'tdMarch', 'tdApril', 'tdMay', 'tdJune',
    'tdJuly', 'tdAugust', 'tdSeptember', 'tdOctober', 'tdNovember', 'tdDecember',
  ];
  final _startCtrl = TextEditingController();
  final _endCtrl = TextEditingController();
  bool _loading = true;
  bool _isInitialLoad = true;
  bool _filterLoading = false;
  String? _error;
  OTReportData? _data;
  List<OTSubordinateItem> _subordinateData = [];
  bool _subordinateLoading = false;
  List<OTReportDetailItem> _details = [];
  int _detailPage = 1;
  int _detailTotal = 0;
  bool _detailLoading = false;
  bool _detailLoadingMore = false;
  final _scrollCtrl = ScrollController();
  String _activeStartDate = '';
  String _activeEndDate = '';

  @override
  void initState() {
    super.initState();
    final now = DateTime.now();
    final twelveMonthsAgo = DateTime(now.year, now.month - 11, 1);
    _startCtrl.text =
        '${twelveMonthsAgo.year}-${twelveMonthsAgo.month.toString().padLeft(2, '0')}-01';
    final lastDay = DateTime(now.year, now.month + 1, 0).day;
    _endCtrl.text =
        '${now.year}-${now.month.toString().padLeft(2, '0')}-${lastDay.toString().padLeft(2, '0')}';
    _loadData();
    _scrollCtrl.addListener(_onScroll);
  }

  @override
  void dispose() {
    _startCtrl.dispose();
    _endCtrl.dispose();
    _scrollCtrl.dispose();
    super.dispose();
  }

  Future<void> _loadData({bool isRefresh = false}) async {
    _activeStartDate = _startCtrl.text;
    _activeEndDate = _endCtrl.text;
    setState(() {
      if (isRefresh) {
        _filterLoading = true;
      } else {
        _loading = true;
      }
      _error = null;
    });
    try {
      final api = ref.read(overtimeApplyApiProvider);
      final data = await api.getOTReport(
        startDate: _startCtrl.text.isNotEmpty ? _startCtrl.text : '',
        endDate: _endCtrl.text.isNotEmpty ? _endCtrl.text : '',
      );
      if (mounted) {
        setState(() {
          _data = data;
          _loading = false;
          _filterLoading = false;
        });
        _loadDetails();
        _loadSubordinate();
      }
    } catch (e) {
      if (mounted) {
        setState(() {
          _error = e.toString();
          _loading = false;
          _filterLoading = false;
        });
      }
    }
  }

  Future<void> _loadDetails() async {
    if (_detailLoading) return;
    setState(() => _detailLoading = true);
    try {
      final api = ref.read(overtimeApplyApiProvider);
      final result = await api.getOTReportDetail(
        startDate: _startCtrl.text.isNotEmpty ? _startCtrl.text : '',
        endDate: _endCtrl.text.isNotEmpty ? _endCtrl.text : '',
        page: 1,
      );
      if (!mounted) return;
      final list =
          (result['list'] as List<dynamic>?)
              ?.map(
                (e) => OTReportDetailItem.fromJson(e as Map<String, dynamic>),
              )
              .toList() ??
          [];
      setState(() {
        _details = list;
        _detailTotal = result['total'] as int? ?? 0;
        _detailPage = 1;
        _detailLoading = false;
      });
    } catch (_) {
      if (mounted) setState(() => _detailLoading = false);
    }
  }

  Future<void> _loadMoreDetails() async {
    if (_detailLoadingMore) return;
    if (_details.length >= _detailTotal) return;
    setState(() => _detailLoadingMore = true);
    try {
      final api = ref.read(overtimeApplyApiProvider);
      final result = await api.getOTReportDetail(
        startDate: _startCtrl.text.isNotEmpty ? _startCtrl.text : '',
        endDate: _endCtrl.text.isNotEmpty ? _endCtrl.text : '',
        page: _detailPage + 1,
      );
      if (!mounted) return;
      final list =
          (result['list'] as List<dynamic>?)
              ?.map(
                (e) => OTReportDetailItem.fromJson(e as Map<String, dynamic>),
              )
              .toList() ??
          [];
      setState(() {
        _details = [..._details, ...list];
        _detailPage++;
        _detailLoadingMore = false;
      });
    } catch (_) {
      if (mounted) setState(() => _detailLoadingMore = false);
    }
  }

  Future<void> _loadSubordinate() async {
    setState(() => _subordinateLoading = true);
    try {
      final api = ref.read(overtimeApplyApiProvider);
      final data = await api.getOTSubordinateReport(
        startDate: _startCtrl.text.isNotEmpty ? _startCtrl.text : '',
        endDate: _endCtrl.text.isNotEmpty ? _endCtrl.text : '',
      );
      if (mounted) {
        setState(() {
          _subordinateData = data;
          _subordinateLoading = false;
        });
      }
    } catch (_) {
      if (mounted) setState(() => _subordinateLoading = false);
    }
  }

  void _onScroll() {
    if (_scrollCtrl.position.pixels <
        _scrollCtrl.position.maxScrollExtent - 200) {
      return;
    }
    if (_detailTotal > 0 &&
        _details.length < _detailTotal &&
        !_detailLoadingMore) {
      _loadMoreDetails();
    }
  }

  @override
  Widget build(BuildContext context) {
    final colors = Theme.of(context).extension<AppColorsExtension>()!;
    final l10n = AppLocalizations.of(context);
    if (_loading && _isInitialLoad) {
      return const SkeletonOTDetailReportPage();
    }
    if (_loading) {
      return Column(
        children: [
          _buildDateFilter(),
          Expanded(
            child: SingleChildScrollView(
              child: Column(
                children: [
                  const SizedBox(height: 16),
                  Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 12),
                    child: Bone(
                      height: 80,
                      borderRadius: BorderRadius.circular(12),
                    ),
                  ),
                  const SizedBox(height: 16),
                  Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 12),
                    child: Bone(
                      height: 200,
                      borderRadius: BorderRadius.circular(12),
                    ),
                  ),
                  const SizedBox(height: 16),
                  Center(
                    child: TDLoading(
                      size: TDLoadingSize.medium,
                      icon: TDLoadingIcon.activity,
                    ),
                  ),
                ],
              ),
            ),
          ),
        ],
      );
    }
    if (_error != null) {
      return Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text(_error!, style: TextStyle(color: colors.textSecondary)),
            const SizedBox(height: 12),
            TDButton(
              text: l10n.get('retry'),
              theme: TDButtonTheme.primary,
              onTap: _loadData,
            ),
          ],
        ),
      );
    }
    return Stack(
      children: [
        Column(
          children: [
            _buildDateFilter(),
            Expanded(
              child: SingleChildScrollView(
                controller: _scrollCtrl,
                child: Column(
                  children: [
                    _buildStatCards(),
                    _buildChartSection(),
                    _buildBarChartSection(),
                    _buildDetailList(),
                    const SizedBox(height: 80),
                  ],
                ),
              ),
            ),
          ],
        ),
        if (_filterLoading) ...[
          Container(color: colors.bgPage.withValues(alpha: 0.6)),
          const Center(
            child: TDLoading(
              size: TDLoadingSize.medium,
              icon: TDLoadingIcon.activity,
            ),
          ),
        ],
      ],
    );
  }

  // ── 日期筛选 ──
  Widget _buildDateFilter() {
    final tdTheme = TDTheme.of(context);
    final colors = Theme.of(context).extension<AppColorsExtension>()!;
    return Container(
      decoration: BoxDecoration(
        color: colors.bgCard,
        border: Border(bottom: BorderSide(color: tdTheme.componentStrokeColor)),
      ),
      child: Padding(
        padding: const EdgeInsets.fromLTRB(12, 8, 12, 12),
        child: DateRangePicker(
          startCtrl: _startCtrl,
          endCtrl: _endCtrl,
          onChanged: () {
            setState(() {});
            _details = [];
            _detailPage = 1;
            _detailTotal = 0;
            _isInitialLoad = false;
            _loadData(isRefresh: true);
            _loadDetails();
          },
        ),
      ),
    );
  }

  // ── 4 张统计卡片（2行2列）──
  Widget _buildStatCards() {
    final colors = Theme.of(context).extension<AppColorsExtension>()!;
    final l10n = AppLocalizations.of(context);
    final summary = _data?.summary ?? const OTReportSummary();
    return Column(
      children: [
        Padding(
          padding: const EdgeInsets.fromLTRB(12, 12, 12, 0),
          child: Row(
            children: [
              Expanded(
                child: _statCard(
                  l10n.get('statTotalHours'),
                  summary.totalHours.toStringAsFixed(1),
                  colors.amountPrimary,
                ),
              ),
              const SizedBox(width: 8),
              Expanded(
                child: _statCard(
                  l10n.get('statTotalOvertimeCount'),
                  '${summary.totalCount}',
                  colors.textPrimary,
                ),
              ),
            ],
          ),
        ),
        const SizedBox(height: 8),
        Padding(
          padding: const EdgeInsets.symmetric(horizontal: 12),
          child: Row(
            children: [
              Expanded(
                child: _statCard(
                  l10n.get('compHours'),
                  summary.compensatoryHours.toStringAsFixed(1),
                  colors.success,
                ),
              ),
              const SizedBox(width: 8),
              Expanded(
                child: _statCard(
                  l10n.get('statSettleHours'),
                  summary.overtimePayHours.toStringAsFixed(1),
                  colors.warning,
                ),
              ),
            ],
          ),
        ),
      ],
    );
  }

  Widget _statCard(String label, String value, Color valueColor) {
    final colors = Theme.of(context).extension<AppColorsExtension>()!;
    return Container(
      padding: const EdgeInsets.symmetric(vertical: 14, horizontal: 8),
      decoration: BoxDecoration(
        color: colors.bgCard,
        borderRadius: BorderRadius.circular(8),
        boxShadow: const [
          BoxShadow(
            color: Color(0x08000000),
            blurRadius: 4,
            offset: Offset(0, 1),
          ),
        ],
      ),
      child: Column(
        children: [
          Text(
            value,
            softWrap: false,
            style: TextStyle(
              fontSize: 18,
              fontWeight: FontWeight.w700,
              color: valueColor,
            ),
          ),
          const SizedBox(height: 4),
          Text(
            label,
            maxLines: 1,
            overflow: TextOverflow.ellipsis,
            style: TextStyle(fontSize: 12, color: colors.textSecondary),
          ),
        ],
      ),
    );
  }

  // ── 图表区域 ──
  Widget _buildChartSection() {
    final colors = Theme.of(context).extension<AppColorsExtension>()!;
    final l10n = AppLocalizations.of(context);
    return Padding(
      padding: const EdgeInsets.all(12),
      child: Container(
        width: double.infinity,
        padding: const EdgeInsets.all(16),
        decoration: BoxDecoration(
          color: colors.bgCard,
          borderRadius: BorderRadius.circular(8),
          boxShadow: const [
            BoxShadow(
              color: Color(0x08000000),
              blurRadius: 4,
              offset: Offset(0, 1),
            ),
          ],
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              l10n.get('chartTitle2'),
              style: TextStyle(
                fontSize: 14,
                fontWeight: FontWeight.w600,
                color: colors.textPrimary,
              ),
            ),
            const SizedBox(height: 8),
            Row(
              children: [
                Container(
                  width: 8,
                  height: 8,
                  decoration: BoxDecoration(
                    color: colors.amountPrimary,
                    shape: BoxShape.circle,
                  ),
                ),
                const SizedBox(width: 4),
                Text(
                  l10n.get('overtimeHours'),
                  style: TextStyle(fontSize: 11, color: colors.textSecondary),
                ),
              ],
            ),
            const SizedBox(height: 16),
            SizedBox(height: 200, child: _buildHoursLineChart()),
          ],
        ),
      ),
    );
  }

  // 加班时数折线图
  Widget _buildHoursLineChart() {
    final colors = Theme.of(context).extension<AppColorsExtension>()!;
    final l10n = AppLocalizations.of(context);

    final start = DateTime.tryParse(_activeStartDate);
    final end = DateTime.tryParse(_activeEndDate);
    final monthLabels = <String>[];
    final monthKeys = <int>[];
    if (start != null && end != null) {
      var cur = DateTime(start.year, start.month, 1);
      final endMonth = DateTime(end.year, end.month, 1);
      while (!cur.isAfter(endMonth)) {
        monthLabels.add(l10n.get(_monthI18nKeys[cur.month]));
        monthKeys.add(cur.month);
        cur = DateTime(cur.year, cur.month + 1, 1);
      }
    }

    final monthlyMap = <int, double>{};
    for (final item in (_data?.monthly ?? [])) {
      monthlyMap[item.month] = item.hours;
    }

    final hoursData = monthKeys.map((m) => monthlyMap[m] ?? 0.0).toList();

    if (hoursData.isEmpty) {
      return SizedBox(
        height: 200,
        child: Center(
          child: Text(
            AppLocalizations.of(context).get('noData'),
            style: TextStyle(fontSize: 14, color: colors.textPlaceholder),
          ),
        ),
      );
    }

    final maxVal = hoursData.reduce((a, b) => a > b ? a : b);
    final maxY = (maxVal > 0 ? maxVal * 1.2 : 100).toDouble();

    return Padding(
      padding: const EdgeInsets.only(top: 8),
      child: LineChart(
        LineChartData(
          gridData: FlGridData(
            show: true,
            drawVerticalLine: false,
            horizontalInterval: maxY / 4,
            getDrawingHorizontalLine: (v) =>
                FlLine(color: colors.border, strokeWidth: 0.5),
          ),
          titlesData: FlTitlesData(
            leftTitles: AxisTitles(
              sideTitles: SideTitles(
                showTitles: true,
                reservedSize: 48,
                interval: maxY / 4,
                getTitlesWidget: (v, meta) => Text(
                  '${v.toInt()}',
                  style: TextStyle(fontSize: 10, color: colors.textPlaceholder),
                ),
              ),
            ),
            bottomTitles: AxisTitles(
              sideTitles: SideTitles(
                showTitles: true,
                interval: 1,
                reservedSize: 26,
                getTitlesWidget: (v, meta) {
                  final i = v.toInt();
                  if (i < 0 || i >= monthLabels.length) return const SizedBox();
                  return Padding(
                    padding: const EdgeInsets.only(top: 4),
                    child: Text(
                      monthLabels[i],
                      style: TextStyle(
                        fontSize: 9,
                        color: colors.textPlaceholder,
                      ),
                    ),
                  );
                },
              ),
            ),
            topTitles: const AxisTitles(
              sideTitles: SideTitles(showTitles: false),
            ),
            rightTitles: const AxisTitles(
              sideTitles: SideTitles(showTitles: false),
            ),
          ),
          borderData: FlBorderData(show: false),
          minY: 0,
          maxY: maxY,
          lineTouchData: LineTouchData(
            enabled: true,
            touchTooltipData: LineTouchTooltipData(
              fitInsideHorizontally: true,
              fitInsideVertically: true,
              getTooltipColor: (_) =>
                  colors.textPrimary.withValues(alpha: 0.85),
              getTooltipItems: (spots) => spots.map((s) {
                return LineTooltipItem(
                  '${monthLabels[s.spotIndex]}\n${s.y.toStringAsFixed(1)}',
                  const TextStyle(
                    color: Colors.white,
                    fontSize: 12,
                    fontWeight: FontWeight.w500,
                  ),
                );
              }).toList(),
            ),
          ),
          lineBarsData: [
            LineChartBarData(
              spots: List.generate(
                hoursData.length,
                (i) => FlSpot(i.toDouble(), hoursData[i]),
              ),
              isCurved: true,
              preventCurveOverShooting: true,
              color: colors.amountPrimary,
              barWidth: 2.5,
              dotData: FlDotData(
                show: true,
                getDotPainter: (spot, percent, barData, index) =>
                    FlDotCirclePainter(
                      radius: 3,
                      color: colors.amountPrimary,
                      strokeWidth: 0,
                    ),
              ),
              belowBarData: BarAreaData(
                show: true,
                color: colors.amountPrimary.withValues(alpha: 0.08),
              ),
            ),
          ],
        ),
      ),
    );
  }

  // ── 明细列表 ──
  // ── 下属加班时数柱形图（参照 expense_detail_report_page） ──
  Widget _buildBarChartSection() {
    final colors = Theme.of(context).extension<AppColorsExtension>()!;
    final l10n = AppLocalizations.of(context);
    if (_subordinateLoading || _subordinateData.isEmpty) {
      return Padding(
        padding: const EdgeInsets.only(top: 16),
        child: Center(
          child: _subordinateLoading
              ? const TDLoading(size: TDLoadingSize.small)
              : Column(
                  children: [
                    Icon(Icons.people_outline,
                        size: 32, color: colors.textPlaceholder),
                    const SizedBox(height: 8),
                    Text(l10n.get('noDetailData'),
                        style: TextStyle(color: colors.textPlaceholder)),
                  ],
                ),
        ),
      );
    }
    final styleLabels = [
      colors.chart1,
      colors.chart2,
      colors.chart3,
      colors.chart4,
      colors.chart5,
      colors.primary,
      colors.success,
      colors.warning,
      colors.infoText,
      colors.danger,
    ];
    final barCount = _subordinateData.length;
    final barWidth = barCount <= 1 ? 40.0 : 20.0;
    final chartWidth = barCount * 60.0;
    return Padding(
      padding: const EdgeInsets.all(12),
      child: Container(
        width: double.infinity,
        padding: const EdgeInsets.all(16),
        decoration: BoxDecoration(
          color: colors.bgCard,
          borderRadius: BorderRadius.circular(8),
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(l10n.get('chartTitleOT'),
                style: TextStyle(
                  fontSize: 14,
                  fontWeight: FontWeight.w600,
                  color: colors.textPrimary,
                )),
            const SizedBox(height: 16),
            SizedBox(
              height: 220,
              child: SingleChildScrollView(
                scrollDirection: Axis.horizontal,
                child: SizedBox(
                  width: chartWidth < MediaQuery.of(context).size.width - 64
                      ? MediaQuery.of(context).size.width - 64
                      : chartWidth,
                  child: BarChart(
                    BarChartData(
                      alignment: BarChartAlignment.spaceAround,
                      maxY: _subordinateData
                              .map((e) => e.hours)
                              .reduce((a, b) => a > b ? a : b) *
                          1.3,
                      barGroups: _subordinateData.asMap().entries.map((e) {
                        final color =
                            styleLabels[e.key % styleLabels.length];
                        return BarChartGroupData(
                          x: e.key,
                          barRods: [
                            BarChartRodData(
                              toY: e.value.hours,
                              color: color,
                              width: barWidth,
                              borderRadius: const BorderRadius.vertical(
                                  top: Radius.circular(4)),
                            ),
                          ],
                        );
                      }).toList(),
                      titlesData: FlTitlesData(
                        topTitles: const AxisTitles(
                            sideTitles: SideTitles(showTitles: false)),
                        rightTitles: const AxisTitles(
                            sideTitles: SideTitles(showTitles: false)),
                        leftTitles: AxisTitles(
                          sideTitles: SideTitles(
                            showTitles: true,
                            reservedSize: 36,
                            interval: (_subordinateData
                                    .map((e) => e.hours)
                                    .reduce((a, b) => a > b ? a : b) *
                                1.3) / 4,
                            getTitlesWidget: (v, _) => Text(
                              v.toInt().toString(),
                              style: TextStyle(
                                  fontSize: 10, color: colors.textPlaceholder),
                            ),
                          ),
                        ),
                        bottomTitles: AxisTitles(
                          sideTitles: SideTitles(
                            showTitles: true,
                            getTitlesWidget: (v, _) {
                              final i = v.toInt();
                              if (i < 0 || i >= _subordinateData.length) {
                                return const SizedBox();
                              }
                              final name =
                                  _subordinateData[i].usrName;
                              final display = name.length > 4
                                  ? '${name.substring(0, 4)}…'
                                  : name;
                              return Padding(
                                padding: const EdgeInsets.only(top: 4),
                                child: Text(display,
                                    style: TextStyle(
                                        fontSize: 11,
                                        color: colors.textSecondary)),
                              );
                            },
                          ),
                        ),
                      ),
                      borderData: FlBorderData(show: false),
                      gridData: FlGridData(
                        show: true,
                        drawVerticalLine: false,
                        getDrawingHorizontalLine: (v) =>
                            FlLine(color: colors.border.withValues(alpha: 0.3), strokeWidth: 0.5),
                      ),
                      barTouchData: BarTouchData(
                        touchTooltipData: BarTouchTooltipData(
                          getTooltipItem: (group, groupIndex, rod, rodIndex) {
                            final item =
                                _subordinateData[group.x.toInt()];
                            return BarTooltipItem(
                              '${item.usrName}\n${item.hours}',
                              const TextStyle(
                                  color: Colors.white,
                                  fontSize: 12),
                            );
                          },
                        ),
                      ),
                    ),
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildDetailList() {
    final l10n = AppLocalizations.of(context);
    final colors = Theme.of(context).extension<AppColorsExtension>()!;
    if (_detailLoading && _details.isEmpty) {
      return const Padding(
        padding: EdgeInsets.only(top: 32),
        child: Center(
          child: TDLoading(
            size: TDLoadingSize.medium,
            icon: TDLoadingIcon.activity,
          ),
        ),
      );
    }
    if (_details.isEmpty) {
      return Padding(
        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
        child: Container(
          width: double.infinity,
          decoration: BoxDecoration(
            color: colors.bgCard,
            borderRadius: BorderRadius.circular(8),
          ),
          child: Padding(
            padding: const EdgeInsets.symmetric(vertical: 48),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Icon(
                  Icons.inbox_outlined,
                  size: 48,
                  color: colors.textPlaceholder,
                ),
                const SizedBox(height: 12),
                Text(
                  l10n.get('noDetailData'),
                  style: TextStyle(fontSize: 14, color: colors.textSecondary),
                ),
              ],
            ),
          ),
        ),
      );
    }

    final hasMore = _details.length < _detailTotal;

    return Padding(
      padding: const EdgeInsets.fromLTRB(12, 0, 12, 8),
      child: Container(
        width: double.infinity,
        decoration: BoxDecoration(
          color: colors.bgCard,
          borderRadius: BorderRadius.circular(8),
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Padding(
              padding: const EdgeInsets.fromLTRB(16, 12, 16, 8),
              child: Row(
                children: [
                  Text(
                    l10n.get('detailList'),
                    style: TextStyle(
                      fontSize: 14,
                      fontWeight: FontWeight.w600,
                      color: colors.textPrimary,
                    ),
                  ),
                  const Spacer(),
                  Text(
                    '${l10n.get('total')} $_detailTotal ${l10n.get('unitItem')}',
                    style: TextStyle(fontSize: 12, color: colors.textSecondary),
                  ),
                ],
              ),
            ),
            Divider(height: 1, color: colors.border),
            ListView.builder(
              shrinkWrap: true,
              physics: const NeverScrollableScrollPhysics(),
              padding: EdgeInsets.zero,
              itemCount: _details.length + 1,
              itemBuilder: (_, i) {
                if (i == _details.length) {
                  if (_detailLoadingMore) {
                    return const Padding(
                      padding: EdgeInsets.symmetric(vertical: 16),
                      child: Center(
                        child: TDLoading(
                          size: TDLoadingSize.small,
                          icon: TDLoadingIcon.activity,
                        ),
                      ),
                    );
                  }
                  return ListFooter(
                    itemCount: _details.length,
                    hasMore: hasMore,
                  );
                }
                return _buildDetailItem(_details[i]);
              },
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildDetailItem(OTReportDetailItem d) {
    final colors = Theme.of(context).extension<AppColorsExtension>()!;
    final l10n = AppLocalizations.of(context);
    final billDate = d.billDate != null && d.billDate!.length >= 10
        ? d.billDate!.substring(0, 10)
        : '-';
    final jbTypeLabel = _jbTypeLabel(d.jbType, l10n);
    final compensationLabel = _compensationTypeLabel(d.compensationType, l10n);
    return Column(
      children: [
        Padding(
          padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Flexible(
                    child: Text(
                      d.billNo,
                      maxLines: 1,
                      overflow: TextOverflow.ellipsis,
                      style: TextStyle(
                        fontSize: 14,
                        fontWeight: FontWeight.w600,
                        color: colors.textPrimary,
                      ),
                    ),
                  ),
                  const SizedBox(width: 12),
                  Text(
                    '${d.hours.toStringAsFixed(1)}${l10n.get('unitHours')}',
                    maxLines: 1,
                    overflow: TextOverflow.ellipsis,
                    style: TextStyle(
                      fontSize: 16,
                      fontWeight: FontWeight.w700,
                      color: colors.timePrimary,
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 6),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Text(
                    billDate,
                    style: TextStyle(fontSize: 12, color: colors.textSecondary),
                  ),
                  Text(
                    d.employeeName,
                    style: TextStyle(fontSize: 12, color: colors.textSecondary),
                  ),
                ],
              ),
              const SizedBox(height: 6),
              Row(
                children: [
                  if (jbTypeLabel.isNotEmpty) ...[
                    Container(
                      padding: const EdgeInsets.symmetric(
                        horizontal: 6,
                        vertical: 1,
                      ),
                      decoration: BoxDecoration(
                        color: colors.primary.withValues(alpha: 0.1),
                        borderRadius: BorderRadius.circular(4),
                        border: Border.all(color: colors.primary, width: 0.5),
                      ),
                      child: Text(
                        jbTypeLabel,
                        style: TextStyle(
                          fontSize: 11,
                          fontWeight: FontWeight.w500,
                          color: colors.primary,
                        ),
                      ),
                    ),
                    const SizedBox(width: 6),
                  ],
                  if (compensationLabel.isNotEmpty)
                    Container(
                      padding: const EdgeInsets.symmetric(
                        horizontal: 6,
                        vertical: 1,
                      ),
                      decoration: BoxDecoration(
                        color: colors.success.withValues(alpha: 0.1),
                        borderRadius: BorderRadius.circular(4),
                        border: Border.all(color: colors.success, width: 0.5),
                      ),
                      child: Text(
                        compensationLabel,
                        style: TextStyle(
                          fontSize: 11,
                          fontWeight: FontWeight.w500,
                          color: colors.success,
                        ),
                      ),
                    ),
                ],
              ),
              if (d.reason.isNotEmpty) ...[
                const SizedBox(height: 6),
                Text(
                  d.reason,
                  maxLines: 2,
                  overflow: TextOverflow.ellipsis,
                  style: TextStyle(fontSize: 12, color: colors.textSecondary),
                ),
              ],
            ],
          ),
        ),
        Divider(height: 1, color: colors.border),
      ],
    );
  }

  String _jbTypeLabel(String type, AppLocalizations l10n) {
    switch (type) {
      case 'WORKING_DAY':
        return l10n.get('workingDay');
      case 'REST_DAY':
        return l10n.get('restDay');
      case 'PUBLIC_HOLIDAY':
        return l10n.get('publicHoliday');
      case 'SPECIAL_HOLIDAY':
        return l10n.get('specialHoliday');
      default:
        return type;
    }
  }

  String _compensationTypeLabel(String type, AppLocalizations l10n) {
    switch (type) {
      case 'OVERTIME_PAY':
        return l10n.get('overtimePay');
      case 'COMPENSATORY_LEAVE':
        return l10n.get('compensatoryLeave');
      case 'NO_COMPENSATION':
        return l10n.get('noCompensation');
      default:
        return type;
    }
  }
}
