import 'package:flutter/material.dart';
import 'package:tdesign_flutter/tdesign_flutter.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import '../../shared/widgets/nav_bar_config.dart';
import '../../core/utils/date_utils.dart' as du;
import '../../shared/widgets/form_section.dart';
import '../../shared/widgets/form_field_row.dart';
import '../../shared/widgets/approval_actions.dart';
import '../../shared/widgets/approval_timeline.dart';
import '../../shared/models/approval_status.dart';
import 'expense_apply_model.dart';
import '../../core/i18n/app_localizations.dart';
import '../../shared/widgets/loading_dialog.dart';
import '../../shared/models/bill_attachment.dart';
import 'expense_apply_api.dart';
import '../../core/theme/app_colors.dart';
import '../../core/theme/app_colors_extension.dart';

class ExpenseApplyDetailPage extends ConsumerStatefulWidget {
  final String billNo;
  final int queryId;
  const ExpenseApplyDetailPage({super.key, required this.billNo, this.queryId = 0});

  @override
  ConsumerState<ExpenseApplyDetailPage> createState() => _ExpenseApplyDetailPageState();
}

class _ExpenseApplyDetailPageState extends ConsumerState<ExpenseApplyDetailPage> {
  bool _loading = true;
  String? _error;
  ExpenseApplyModel? _data;
  List<BillAttachment> _attachments = [];

  List<ApprovalRecord> _approvalRecords = [];
  List<String> _approvalChain = [];
  String _currentApproverId = '';

  @override
  void initState() {
    super.initState();
    _loadData();
  }

  Future<void> _loadData() async {
    setState(() { _loading = true; _error = null; });
    try {
      final api = ref.read(expenseApplyApiProvider);
      final detail = await api.fetchDetail(widget.billNo);

      // Load approval timeline (non-critical, best-effort)
      List<ApprovalRecord> records = [];
      List<String> chain = [];
      String currentId = '';
      try {
        final timeline = await api.fetchApprovalTimeline('AE', widget.billNo);
        records = (timeline['records'] as List<dynamic>?)
                ?.map((e) => ApprovalRecord.fromJson(e as Map<String, dynamic>))
                .toList() ??
            [];
        chain = (timeline['chain'] as List<dynamic>?)
                ?.map((e) => e as String)
                .toList() ??
            [];
        currentId = timeline['currentApproverId'] as String? ?? '';
      } catch (_) {
        // Timeline load failure is non-fatal
      }

      // Load attachments (non-critical, best-effort)
      List<BillAttachment> attachments = [];
      try {
        attachments = await api.getAttachments('AE', widget.billNo);
      } catch (_) {
        // Attachment load failure is non-fatal
      }

      if (mounted) {
        setState(() {
          _data = detail;
          _approvalRecords = records;
          _approvalChain = chain;
          _currentApproverId = currentId;
          _attachments = attachments;
          _loading = false;
        });
      }
    } catch (e) {
      if (mounted) {
        setState(() { _error = e.toString(); _loading = false; });
      }
    }
  }

  void _handleApprove() async {
    final l10n = AppLocalizations.of(context);
    final rem = await _showOpinionDialog(
      title: l10n.get('confirmApprove'),
      hint: l10n.get('approvalComment'),
    );
    if (rem == null || !mounted) return;
    await _doAudit('approve', rem: rem);
  }

  void _handleReject() async {
    final l10n = AppLocalizations.of(context);
    final rem = await _showOpinionDialog(
      title: l10n.get('confirmReject'),
      hint: l10n.get('rejectReason'),
    );
    if (rem == null || !mounted) return;
    await _doAudit('reject', rem: rem);
  }

  void _handleReverseAudit() async {
    final l10n = AppLocalizations.of(context);
    final confirmed = await showDialog<bool>(
      context: context,
      builder: (ctx) => TDAlertDialog(
        title: l10n.get('withdrawConfirm'),
        content: l10n.get('withdrawConfirmTip'),
        leftBtn: TDDialogButtonOptions(title: l10n.get('cancel'), action: () => Navigator.pop(ctx, false)),
        rightBtn: TDDialogButtonOptions(title: l10n.get('confirm'), action: () => Navigator.pop(ctx, true)),
      ),
    );
    if (confirmed != true || !mounted) return;
    final rem = await _showOpinionDialog(
      title: l10n.get('withdrawConfirm'),
      hint: l10n.get('approvalComment'),
    );
    if (rem == null || !mounted) return;
    await _doAudit('reverseAudit', rem: rem);
  }

  /// 弹出审批意见输入框，返回 null 表示取消
  Future<String?> _showOpinionDialog({
    required String title,
    required String hint,
  }) async {
    final ctrl = TextEditingController();
    return showDialog<String>(
      context: context,
      builder: (ctx) => TDAlertDialog(
        title: title,
        content: hint,
        leftBtn: TDDialogButtonOptions(
          title: AppLocalizations.of(context).get('cancel'),
          action: () => Navigator.pop(ctx),
        ),
        rightBtn: TDDialogButtonOptions(
          title: AppLocalizations.of(context).get('confirm'),
          action: () => Navigator.pop(ctx, ctrl.text),
        ),
      ),
    );
  }

  Future<void> _doAudit(String action, {String rem = ''}) async {
    try {
      LoadingDialog.show(context);
      final api = ref.read(expenseApplyApiProvider);
      await api.executeApproval(bilId: 'AE', bilNo: widget.billNo, action: action, rem: rem);
      if (mounted) {
        LoadingDialog.hide(context);
        TDToast.showSuccess(AppLocalizations.of(context).get('submitSuccess'), context: context);
        if (mounted) context.pop();
      }
    } catch (e) {
      if (mounted) {
        LoadingDialog.hide(context);
        TDToast.showFail(e.toString(), context: context);
      }
    }
  }

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

    ref
        .read(navBarConfigProvider.notifier)
        .update(
          NavBarConfig(
            title: l10n.get('expenseApplyDetail'),
            showBack: true,
            onBack: () => context.pop(),
          ),
        );

    if (_loading) {
      return const Center(
        child: TDLoading(size: TDLoadingSize.large, icon: TDLoadingIcon.activity),
      );
    }

    if (_error != null) {
      return Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(Icons.error_outline, size: 48, color: colors.danger),
            const SizedBox(height: 16),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 32),
              child: Text(
                _error!,
                textAlign: TextAlign.center,
                style: TextStyle(fontSize: AppFontSizes.body, color: colors.textSecondary),
              ),
            ),
            const SizedBox(height: 16),
            TDButton(
              text: l10n.get('retry'),
              size: TDButtonSize.medium,
              onTap: _loadData,
            ),
          ],
        ),
      );
    }

    final app = _data!;

    return Column(
      children: [
        Expanded(
          child: SingleChildScrollView(
            padding: const EdgeInsets.all(16),
            child: Column(
              children: [
                _buildBasicInfoSection(app, l10n, colors),
                const SizedBox(height: 16),
                _buildExpenseDetailSection(app, l10n, colors),
                const SizedBox(height: 16),
                _buildAttachmentSection(l10n, colors),
                const SizedBox(height: 16),
                if (_approvalChain.isNotEmpty)
                  Container(
                    padding: const EdgeInsets.all(16),
                    decoration: BoxDecoration(
                      color: colors.bgCard,
                      borderRadius: BorderRadius.circular(8),
                    ),
                    child: ApprovalTimeline(
                      records: _approvalRecords,
                      chain: _approvalChain,
                      currentApproverId: _currentApproverId,
                    ),
                  ),
              ],
            ),
          ),
        ),
        ApprovalActions(
          queryId: widget.queryId,
          onApprove: _handleApprove,
          onReject: _handleReject,
          onReverseAudit: _handleReverseAudit,
        ),
      ],
    );
  }

  // ═══ 基本信息 ═══
  Widget _buildBasicInfoSection(
    ExpenseApplyModel app,
    AppLocalizations l10n,
    AppColorsExtension colors,
  ) {
    String urgencyLabel = switch (app.urgency) {
      'urgent' => l10n.get('urgent'),
      'normal' => l10n.get('normal'),
      'critical' => l10n.get('critical'),
      _ => app.urgency,
    };
    return FormSection(
      title: l10n.get('basicInfo'),
      leadingIcon: Icons.info_outline,
      children: [
        FormFieldRow(label: l10n.get('expenseApplyNo'), value: app.expenseApplyNo, readOnly: true, showArrow: false),
        const SizedBox(height: 16),
        FormFieldRow(label: l10n.get('applicant'), value: app.applicantName, readOnly: true, showArrow: false),
        const SizedBox(height: 16),
        FormFieldRow(label: l10n.get('department'), value: app.deptName, readOnly: true, showArrow: false),
        const SizedBox(height: 16),
        FormFieldRow(label: l10n.get('date'), value: du.DateUtils.formatDateTime(app.createTime), readOnly: true, showArrow: false),
        const SizedBox(height: 16),
        SizedBox(
          height: 24,
          child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
            Text(l10n.get('emergencyLevel'), style: TextStyle(fontSize: AppFontSizes.subtitle, color: colors.textSecondary)),
            Text(urgencyLabel, style: TextStyle(
              fontSize: AppFontSizes.subtitle, fontWeight: FontWeight.w600,
              color: app.urgency == 'urgent' || app.urgency == 'critical' ? colors.danger : colors.textPrimary,
            )),
          ]),
        ),
        const SizedBox(height: 16),
        FormFieldRow(label: l10n.get('feeReason'), value: app.purpose, readOnly: true, showArrow: false),
        const SizedBox(height: 16),
        FormFieldRow(label: l10n.get('remark'), value: app.remark.isNotEmpty ? app.remark : '-', readOnly: true, showArrow: false),
      ],
    );
  }

  // ═══ 费用明细 ═══
  Widget _buildExpenseDetailSection(
    ExpenseApplyModel app,
    AppLocalizations l10n,
    AppColorsExtension colors,
  ) {
    return FormSection(
      title: l10n.get('expenseDetails'),
      leadingIcon: Icons.receipt_long_outlined,
      children: [
        if (app.details.isEmpty)
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 8),
            child: Text(l10n.get('noDetailData'), style: TextStyle(fontSize: AppFontSizes.body, color: colors.textPlaceholder)),
          )
        else
          ...app.details.asMap().entries.map((e) {
            final d = e.value;
            final catLabel = d.categoryName.isNotEmpty
                ? '${d.expenseCategory}/${d.categoryName}'
                : d.expenseCategory;
            return Container(
              margin: const EdgeInsets.symmetric(vertical: 8),
              padding: const EdgeInsets.all(12),
              decoration: BoxDecoration(color: colors.bgPage, borderRadius: BorderRadius.circular(8)),
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  Expanded(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Row(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            Expanded(
                              child: Text(
                                catLabel,
                                maxLines: 1,
                                overflow: TextOverflow.ellipsis,
                                style: TextStyle(fontSize: AppFontSizes.subtitle, color: colors.textPrimary),
                              ),
                            ),
                            const SizedBox(width: 12),
                            Text(
                              '¥${d.estimatedAmount.toStringAsFixed(2)}',
                              style: TextStyle(fontSize: AppFontSizes.caption, fontWeight: FontWeight.w600, color: colors.amountPrimary),
                            ),
                          ],
                        ),
                        if (d.acctSubjectId.isNotEmpty && d.acctSubjectName.isNotEmpty) ...[
                          const SizedBox(height: 4),
                          Text(
                            '${d.acctSubjectId}/${d.acctSubjectName}',
                            maxLines: 1,
                            overflow: TextOverflow.ellipsis,
                            style: TextStyle(fontSize: AppFontSizes.caption, color: colors.textSecondary),
                          ),
                        ],
                        if (d.projectId.isNotEmpty && d.projectName.isNotEmpty) ...[
                          const SizedBox(height: 4),
                          Text(
                            '${d.projectId}/${d.projectName}',
                            maxLines: 1,
                            overflow: TextOverflow.ellipsis,
                            style: TextStyle(fontSize: AppFontSizes.caption, color: colors.textSecondary),
                          ),
                        ],
                        if (d.costDeptId.isNotEmpty && d.costDeptName.isNotEmpty) ...[
                          const SizedBox(height: 4),
                          Text(
                            '${d.costDeptId}/${d.costDeptName}',
                            maxLines: 1,
                            overflow: TextOverflow.ellipsis,
                            style: TextStyle(fontSize: AppFontSizes.caption, color: colors.textSecondary),
                          ),
                        ],
                        if (d.estimatedStartDate != null) ...[
                          const SizedBox(height: 4),
                          Text(
                            '${du.DateUtils.formatDate(d.estimatedStartDate!)} ~ ${d.estimatedEndDate != null ? du.DateUtils.formatDate(d.estimatedEndDate!) : ''}',
                            maxLines: 1,
                            overflow: TextOverflow.ellipsis,
                            style: TextStyle(fontSize: AppFontSizes.caption, color: colors.textSecondary),
                          ),
                        ],
                        if (d.remark.isNotEmpty) ...[
                          const SizedBox(height: 4),
                          Text(
                            d.remark,
                            maxLines: 2,
                            overflow: TextOverflow.ellipsis,
                            style: TextStyle(fontSize: AppFontSizes.caption, color: colors.textSecondary),
                          ),
                        ],
                      ],
                    ),
                  ),
                ],
              ),
            );
          }),
        if (app.details.isNotEmpty) ...[
          const SizedBox(height: 8),
          Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
            Text(l10n.get('total'), style: TextStyle(fontSize: AppFontSizes.body, fontWeight: FontWeight.w600, color: colors.textPrimary)),
            Text('¥${app.estimatedAmount.toStringAsFixed(2)}',
                style: TextStyle(fontSize: AppFontSizes.subtitle, fontWeight: FontWeight.w700, color: colors.amountPrimary)),
          ]),
        ],
      ],
    );
  }

  // ═══ 附件 ═══
  Widget _buildAttachmentSection(AppLocalizations l10n, AppColorsExtension colors) {
    return FormSection(
      title: l10n.get('attachments'),
      leadingIcon: Icons.attach_file_outlined,
      children: [
        if (_attachments.isEmpty)
          Text(l10n.get('noAttachment'), style: TextStyle(fontSize: AppFontSizes.body, color: colors.textPlaceholder))
        else
          ..._attachments.map((a) => _buildAttachmentRow(a, colors)),
      ],
    );
  }

  Widget _buildAttachmentRow(BillAttachment a, AppColorsExtension colors) {
    return Container(
      margin: const EdgeInsets.symmetric(vertical: 4),
      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
      decoration: BoxDecoration(
        color: colors.bgPage,
        borderRadius: BorderRadius.circular(8),
      ),
      child: Row(children: [
        Icon(_fileTypeIcon(a.ext), size: 24, color: colors.primary),
        const SizedBox(width: 10),
        Expanded(
          child: Text(a.fileName,
              maxLines: 1, overflow: TextOverflow.ellipsis,
              style: TextStyle(fontSize: AppFontSizes.body, color: colors.textPrimary)),
        ),
      ]),
    );
  }

  IconData _fileTypeIcon(String ext) {
    switch (ext.toLowerCase()) {
      case 'pdf': return Icons.picture_as_pdf;
      case 'doc': case 'docx': return Icons.description;
      case 'xls': case 'xlsx': return Icons.table_chart;
      case 'jpg': case 'jpeg': case 'png': case 'gif': case 'bmp': return Icons.image_outlined;
      default: return Icons.insert_drive_file;
    }
  }
}
