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 '../expense_apply/expense_apply_api.dart';
import '../expense_apply/report_model.dart';
import 'package:marquee/marquee.dart';
import '../../core/utils/amount_utils.dart';

/// 事前申请明细报表 - 页面22

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

class _ExpenseApplyDetailReportPageState
    extends ConsumerState<ExpenseApplyDetailReportPage> {
  final _startCtrl = TextEditingController();
  final _endCtrl = TextEditingController();
  bool _loading = true;
  bool _isInitialLoad = true;
  bool _filterLoading = false;
  String? _error;
  ReportData? _data;
  List<ReportDetailItem> _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(expenseApplyApiProvider);
      final data = await api.getExpenseApplyReport(
        startDate: _startCtrl.text.isNotEmpty ? _startCtrl.text : null,
        endDate: _endCtrl.text.isNotEmpty ? _endCtrl.text : null,
      );
      if (mounted) {
        setState(() {
          _data = data;
          _loading = false;
          _filterLoading = false;
        });
        _loadDetails();
      }
    } 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(expenseApplyApiProvider);
      final result = await api.getExpenseApplyReportDetail(
        startDate: _startCtrl.text.isNotEmpty ? _startCtrl.text : null,
        endDate: _endCtrl.text.isNotEmpty ? _endCtrl.text : null,
        page: 1,
      );
      if (!mounted) return;
      final list =
          (result['list'] as List<dynamic>?)
              ?.map((e) => ReportDetailItem.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(expenseApplyApiProvider);
      final result = await api.getExpenseApplyReportDetail(
        startDate: _startCtrl.text.isNotEmpty ? _startCtrl.text : null,
        endDate: _endCtrl.text.isNotEmpty ? _endCtrl.text : null,
        page: _detailPage + 1,
      );
      if (!mounted) return;
      final list =
          (result['list'] as List<dynamic>?)
              ?.map((e) => ReportDetailItem.fromJson(e as Map<String, dynamic>))
              .toList() ??
          [];
      setState(() {
        _details = [..._details, ...list];
        _detailPage++;
        _detailLoadingMore = false;
      });
    } catch (_) {
      if (mounted) setState(() => _detailLoadingMore = 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 SkeletonExpenseApplyDetailReportPage();
    }
    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(),
                    _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();
          },
        ),
      ),
    );
  }

  // ── 2 张统计卡片（一行两列）──
  Widget _buildStatCards() {
    final colors = Theme.of(context).extension<AppColorsExtension>()!;
    final l10n = AppLocalizations.of(context);
    final summary = _data?.summary ?? const ReportSummary();
    return Padding(
      padding: const EdgeInsets.fromLTRB(12, 12, 12, 0),
      child: Row(
        children: [
          Expanded(
            child: _statCard(
              l10n.get('statTotalCount'),
              '${summary.totalCount} ${l10n.get('unitItem')}',
              colors.textPrimary,
            ),
          ),
          const SizedBox(width: 8),
          Expanded(
            child: _statCard(
              l10n.get('statTotalApply'),
              formatAmount(summary.totalAmount),
              colors.amountPrimary,
            ),
          ),
        ],
      ),
    );
  }

  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: [
          _buildValue(value, valueColor),
          const SizedBox(height: 4),
          Text(
            label,
            maxLines: 1,
            overflow: TextOverflow.ellipsis,
            style: TextStyle(fontSize: 12, color: colors.textSecondary),
          ),
        ],
      ),
    );
  }

  Widget _buildValue(String value, Color valueColor) {
    return LayoutBuilder(
      builder: (context, constraints) {
        final style = TextStyle(
          fontSize: 18,
          fontWeight: FontWeight.w700,
          color: valueColor,
        );
        final tp = TextPainter(
          text: TextSpan(text: value, style: style),
          textDirection: TextDirection.ltr,
          textScaler: MediaQuery.textScalerOf(context),
          maxLines: 1,
        )..layout();
        if (tp.width > constraints.maxWidth) {
          return SizedBox(
            height: tp.height,
            child: Marquee(
              text: value,
              style: style,
              scrollAxis: Axis.horizontal,
              blankSpace: 40,
              velocity: 30,
              pauseAfterRound: const Duration(seconds: 1),
              startPadding: 0,
            ),
          );
        }
        return Text(value, softWrap: false, style: style);
      },
    );
  }

  // ── 图表区域 ──
  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('chartTitle6'),
              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('yearTotalApp'),
                  style: TextStyle(fontSize: 11, color: colors.textSecondary),
                ),
              ],
            ),
            const SizedBox(height: 16),
            SizedBox(height: 200, child: _buildApplyAmountLineChart()),
          ],
        ),
      ),
    );
  }

  // 申请金额折线图
  Widget _buildApplyAmountLineChart() {
    final colors = Theme.of(context).extension<AppColorsExtension>()!;

    // 根据日期区间生成月份列表
    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('${cur.month}月');
        monthKeys.add(cur.month);
        cur = DateTime(cur.year, cur.month + 1, 1);
      }
    }

    // 建立 API 数据索引
    final monthlyMap = <int, double>{};
    for (final item in (_data?.monthly ?? [])) {
      monthlyMap[item.month] = item.amount;
    }

    // 按日期区间生成金额数据，无数据的月份为 0
    final amountData = monthKeys.map((m) => monthlyMap[m] ?? 0.0).toList();

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

    // 计算 Y 轴最大值
    final maxVal = amountData.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: 80,
                interval: maxY / 4,
                getTitlesWidget: (v, meta) => Text(
                  formatAmount(v.toDouble()),
                  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${formatAmount(s.y)}',
                  const TextStyle(
                    color: Colors.white,
                    fontSize: 12,
                    fontWeight: FontWeight.w500,
                  ),
                );
              }).toList(),
            ),
          ),
          lineBarsData: [
            LineChartBarData(
              spots: List.generate(
                amountData.length,
                (i) => FlSpot(i.toDouble(), amountData[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),
              ),
            ),
          ],
        ),
      ),
    );
  }

  // ── 明细列表 ──
  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(ReportDetailItem 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)
        : '-';
    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(
                    formatAmount(d.amount),
                    maxLines: 1,
                    overflow: TextOverflow.ellipsis,
                    style: TextStyle(
                      fontSize: 16,
                      fontWeight: FontWeight.w700,
                      color: colors.amountPrimary,
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 6),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Text(
                    billDate,
                    style: TextStyle(fontSize: 12, color: colors.textSecondary),
                  ),
                  if (d.isTransferred)
                    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(
                        l10n.get('statusConvertedToExpense'),
                        style: TextStyle(
                          fontSize: 11,
                          fontWeight: FontWeight.w500,
                          color: colors.primary,
                        ),
                      ),
                    ),
                ],
              ),
              if (d.reason.isNotEmpty) ...[
                const SizedBox(height: 6),
                Text(
                  d.reason,
                  maxLines: 2,
                  overflow: TextOverflow.ellipsis,
                  style: TextStyle(fontSize: 14, color: colors.textSecondary),
                ),
              ],
            ],
          ),
        ),
        Divider(height: 1, color: colors.border),
      ],
    );
  }
}
