import 'package:flutter/material.dart';
import 'package:tdesign_flutter/tdesign_flutter.dart';
import '../../../core/i18n/app_localizations.dart';
import '../../../core/theme/app_colors.dart';
import '../../../core/theme/app_colors_extension.dart';
import '../../../core/data/mock_api_data.dart';

/// 费用明细输入数据。
class ExpenseDetailData {
  final String category;
  final String categoryName;
  final String acctSubjectId;
  final String acctSubjectName;
  final String purpose;
  final int projectId;
  final String projectName;
  final String costDeptId;
  final String costDeptName;
  final String startDate;
  final String endDate;
  final double estimatedAmount;
  final String remark;

  const ExpenseDetailData({
    required this.category,
    required this.categoryName,
    required this.acctSubjectId,
    required this.acctSubjectName,
    required this.purpose,
    required this.projectId,
    required this.projectName,
    required this.costDeptId,
    required this.costDeptName,
    required this.startDate,
    required this.endDate,
    required this.estimatedAmount,
    required this.remark,
  });
}

/// 添加费用明细弹窗。
///
/// 使用 [TDSlidePopupRoute] 从底部滑出，卡片化展示表单字段。
class ExpenseApplyDetailDialog extends StatefulWidget {
  final List<CostCategory> categories;
  final List<Project> projects;
  final List<CostDept> costDepts;
  final AppLocalizations l10n;
  final ExpenseDetailData? initialData;

  const ExpenseApplyDetailDialog({
    super.key,
    required this.categories,
    required this.projects,
    required this.costDepts,
    required this.l10n,
    this.initialData,
  });

  /// 显示弹窗，返回 [ExpenseDetailData] 或 `null`（取消时）。
  static Future<ExpenseDetailData?> show(
    BuildContext context, {
    required List<CostCategory> categories,
    required List<Project> projects,
    required List<CostDept> costDepts,
    required AppLocalizations l10n,
    ExpenseDetailData? initialData,
  }) {
    FocusScope.of(context).unfocus();
    return Navigator.push<ExpenseDetailData>(
      context,
      TDSlidePopupRoute<ExpenseDetailData>(
        slideTransitionFrom: SlideTransitionFrom.bottom,
        isDismissible: true,
        builder: (_) => ExpenseApplyDetailDialog(
          categories: categories,
          projects: projects,
          costDepts: costDepts,
          l10n: l10n,
          initialData: initialData,
        ),
      ),
    );
  }

  @override
  State<ExpenseApplyDetailDialog> createState() =>
      _ExpenseApplyDetailDialogState();
}

class _ExpenseApplyDetailDialogState
    extends State<ExpenseApplyDetailDialog> {
  // 费用类别
  late CostCategory _selCat;
  // 关联项目
  Project? _selProject;
  // 费用承担部门
  CostDept? _selDept;
  // 预计开始/结束日期
  String _startDate = '';
  String _endDate = '';
  // 费用事由
  final _purposeCtrl = TextEditingController();
  final _purposeFocus = FocusNode();
  // 预估金额
  final _amountCtrl = TextEditingController();
  final _amountFocus = FocusNode();
  // 备注
  final _remarkCtrl = TextEditingController();
  final _remarkFocus = FocusNode();
  // 滚动控制
  final _scrollCtrl = ScrollController();

  List<CostCategory> get _cats => widget.categories;
  List<Project> get _projects => widget.projects;
  List<CostDept> get _depts => widget.costDepts;
  AppLocalizations get _l10n => widget.l10n;

  bool get _isEdit => widget.initialData != null;

  @override
  void initState() {
    super.initState();
    final d = widget.initialData;
    if (_cats.isEmpty) {
      // 费用类别无数据，弹窗无法使用
      WidgetsBinding.instance.addPostFrameCallback((_) {
        if (mounted) {
          TDToast.showText(_l10n.get('noData'), context: context);
          Navigator.pop(context);
        }
      });
    }
    _selCat = _cats.isNotEmpty
        ? (d != null
            ? _cats.firstWhere((c) => c.code == d.category, orElse: () => _cats.first)
            : _cats.first)
        : const CostCategory(code: '', nameKey: '', acctSubjectId: '', acctSubjectName: '');
    _selProject = (d != null && d.projectId != 0 && _projects.isNotEmpty)
        ? _projects.firstWhere((p) => p.id == d.projectId, orElse: () => _projects.first)
        : null;
    _selDept = (d != null && d.costDeptId.isNotEmpty && _depts.isNotEmpty)
        ? _depts.firstWhere((dept) => dept.id == d.costDeptId, orElse: () => _depts.first)
        : null;
    _startDate = d?.startDate ?? '';
    _endDate = d?.endDate ?? '';
    if (d != null) {
      _purposeCtrl.text = d.purpose;
      _amountCtrl.text = d.estimatedAmount > 0 ? d.estimatedAmount.toStringAsFixed(2) : '';
      _remarkCtrl.text = d.remark;
    }
    _purposeFocus.addListener(() => _ensureVisible(_purposeFocus));
    _amountFocus.addListener(() => _ensureVisible(_amountFocus));
    _remarkFocus.addListener(() => _ensureVisible(_remarkFocus));
  }

  void _ensureVisible(FocusNode node) {
    if (!node.hasFocus) return;
    // 延迟一帧，等键盘 viewInsets 生效后再滚动
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (node.hasFocus && _scrollCtrl.hasClients) {
        final ctx = node.context;
        if (ctx != null) {
          Scrollable.ensureVisible(
            ctx,
            alignment: 0.3,
            duration: const Duration(milliseconds: 300),
          );
        }
      }
    });
  }

  @override
  void dispose() {
    _purposeCtrl.dispose();
    _purposeFocus.dispose();
    _amountCtrl.dispose();
    _amountFocus.dispose();
    _remarkCtrl.dispose();
    _remarkFocus.dispose();
    _scrollCtrl.dispose();
    super.dispose();
  }

  void _confirm() {
    final amt = double.tryParse(_amountCtrl.text) ?? 0;
    if (amt <= 0) {
      TDToast.showText(_l10n.get('estimatedAmountPositive'), context: context);
      return;
    }
    if (_startDate.isNotEmpty &&
        _endDate.isNotEmpty &&
        _startDate.compareTo(_endDate) > 0) {
      TDToast.showText(
        _l10n.get('startDateNotAfterEndDate'),
        context: context,
      );
      return;
    }
    Navigator.pop(
      context,
      ExpenseDetailData(
        category: _selCat.code,
        categoryName: _l10n.get(_selCat.nameKey),
        acctSubjectId: _selCat.acctSubjectId,
        acctSubjectName: _selCat.acctSubjectName,
        purpose: _purposeCtrl.text.trim(),
        projectId: _selProject?.id ?? 0,
        projectName: _selProject?.name ?? '',
        costDeptId: _selDept?.id ?? '',
        costDeptName: _selDept?.name ?? '',
        startDate: _startDate,
        endDate: _endDate,
        estimatedAmount: amt,
        remark: _remarkCtrl.text,
      ),
    );
  }

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

    return SafeArea(
      child: ConstrainedBox(
          constraints: BoxConstraints(
            maxHeight: MediaQuery.of(context).size.height * 0.8,
          ),
          child: Container(
            decoration: BoxDecoration(
              color: colors.bgPage,
              borderRadius:
                  const BorderRadius.vertical(top: Radius.circular(16)),
            ),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                _buildHeader(colors),
                Flexible(
                  child: GestureDetector(
                  onTap: () => FocusScope.of(context).unfocus(),
                  behavior: HitTestBehavior.translucent,
                  child: SingleChildScrollView(
                  controller: _scrollCtrl,
                  keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
                  padding: const EdgeInsets.fromLTRB(16, 0, 16, 12),
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: [
                      _buildCategoryPicker(colors),
                      const SizedBox(height: 12),
                      _buildAcctSubjectCard(colors),
                      const SizedBox(height: 12),
                      _buildAmountInput(colors),
                      const SizedBox(height: 12),
                      _buildProjectPicker(colors),
                      const SizedBox(height: 12),
                      _buildCostDeptPicker(colors),
                      const SizedBox(height: 12),
                      _buildStartDatePicker(colors),
                      const SizedBox(height: 12),
                      _buildEndDatePicker(colors),
                      const SizedBox(height: 12),
                      _buildRemarkInput(colors),
                    ],
                  ),
                ),
              ),
              ),
              Container(
                padding: const EdgeInsets.fromLTRB(16, 12, 16, 16),
                decoration: BoxDecoration(
                  color: colors.bgCard,
                  border: Border(
                    top: BorderSide(color: colors.border, width: 0.5),
                  ),
                ),
                child: _buildActions(),
              ),
            ],
          ),
        ),
      ),
    );
  }

  // ── 标题栏 ──
  Widget _buildHeader(AppColorsExtension colors) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Center(
          child: Container(
            margin: const EdgeInsets.only(top: 8, bottom: 4),
            width: 36,
            height: 4,
            decoration: BoxDecoration(
              color: colors.border,
              borderRadius: BorderRadius.circular(2),
            ),
          ),
        ),
        Padding(
          padding: const EdgeInsets.fromLTRB(20, 8, 12, 16),
          child: Row(
            children: [
              const SizedBox(width: 28),
              Expanded(
                child: Center(
                  child: Text(
                    _l10n.get('addDetail'),
                    style: TextStyle(
                      fontSize: AppFontSizes.title,
                      fontWeight: FontWeight.w600,
                      color: colors.textPrimary,
                    ),
                  ),
                ),
              ),
              GestureDetector(
                onTap: () => Navigator.pop(context),
                child: Padding(
                  padding: const EdgeInsets.all(4),
                  child: Icon(
                    Icons.close,
                    size: 20,
                    color: colors.textSecondary,
                  ),
                ),
              ),
            ],
          ),
        ),
      ],
    );
  }

  // ── 通用 Picker 卡片 ──
  Widget _pickerCard({
    required String label,
    required bool required,
    required String currentLabel,
    required List<String> labels,
    required ValueChanged<int> onSelected,
    required AppColorsExtension colors,
    VoidCallback? onClear,
  }) {
    final tdTheme = TDTheme.of(context);
    final hasValue = onClear != null;
    return GestureDetector(
      onTap: () {
        if (labels.isEmpty) {
          TDToast.showText(_l10n.get('noData'), context: context);
          return;
        }
        TDPicker.showMultiPicker(
          context,
          title: label,
          backgroundColor: colors.bgCard,
          data: [labels],
          onConfirm: (selected) {
            if (selected.isNotEmpty && selected[0] is int) {
              final idx = selected[0] as int;
              if (idx >= 0 && idx < labels.length) {
                Navigator.of(context).pop();
                onSelected(idx);
              }
            }
          },
        );
      },
      child: Container(
        padding: const EdgeInsets.only(
          left: 16, right: 10, top: 12, bottom: 12,
        ),
        decoration: BoxDecoration(
          color: tdTheme.bgColorContainer,
          borderRadius: BorderRadius.circular(tdTheme.radiusDefault),
          border: Border.all(color: tdTheme.componentStrokeColor),
        ),
        child: Row(
          children: [
            TDText(
              label,
              maxLines: 1,
              overflow: TextOverflow.visible,
              font: tdTheme.fontBodyLarge,
              fontWeight: FontWeight.w400,
              style: const TextStyle(letterSpacing: 0),
            ),
            if (required)
              Padding(
                padding: const EdgeInsets.only(left: 4),
                child: TDText(
                  '*',
                  font: tdTheme.fontBodyLarge,
                  fontWeight: FontWeight.w400,
                  style: TextStyle(color: tdTheme.errorColor6),
                ),
              ),
            const SizedBox(width: 12),
            Expanded(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.end,
                mainAxisSize: MainAxisSize.max,
                children: [
                  Flexible(
                    child: TDText(
                      currentLabel,
                      maxLines: 1,
                      overflow: TextOverflow.ellipsis,
                      font: tdTheme.fontBodyLarge,
                      fontWeight: FontWeight.w400,
                      textColor: tdTheme.textColorPrimary,
                      textAlign: TextAlign.end,
                    ),
                  ),
                  const SizedBox(width: 4),
                  SizedBox(
                    width: 18, height: 18,
                    child: hasValue
                        ? GestureDetector(
                            onTap: onClear,
                            child: Icon(Icons.close, size: 18, color: tdTheme.textColorPlaceholder),
                          )
                        : Icon(Icons.chevron_right, size: 18, color: tdTheme.textColorPlaceholder),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  // ── 只读信息卡片（会计科目） ──
  Widget _readOnlyCard({
    required String label,
    required String value,
    required AppColorsExtension colors,
  }) {
    final tdTheme = TDTheme.of(context);
    return Container(
      padding: const EdgeInsets.only(
        left: 16, right: 16, top: 12, bottom: 12,
      ),
      decoration: BoxDecoration(
        color: tdTheme.bgColorContainer,
        borderRadius: BorderRadius.circular(tdTheme.radiusDefault),
        border: Border.all(color: tdTheme.componentStrokeColor),
      ),
      child: Row(
        children: [
          TDText(
            label,
            maxLines: 1,
            overflow: TextOverflow.visible,
            font: tdTheme.fontBodyLarge,
            fontWeight: FontWeight.w400,
            style: const TextStyle(letterSpacing: 0),
          ),
          const SizedBox(width: 12),
          Expanded(
            child: TDText(
              value,
              maxLines: 1,
              overflow: TextOverflow.ellipsis,
              font: tdTheme.fontBodyLarge,
              fontWeight: FontWeight.w400,
              textColor: tdTheme.textColorPrimary,
              textAlign: TextAlign.end,
            ),
          ),
        ],
      ),
    );
  }

  // ── 1. 费用类别 ──
  Widget _buildCategoryPicker(AppColorsExtension colors) {
    return _pickerCard(
      label: _l10n.get('expenseCategory'),
      required: true,
      currentLabel: '${_selCat.code}/${_l10n.get(_selCat.nameKey)}',
      labels: _cats.map((c) => '${c.code}/${_l10n.get(c.nameKey)}').toList(),
      colors: colors,
      onSelected: (idx) => setState(() => _selCat = _cats[idx]),
    );
  }

  // ── 2. 会计科目（只读，选择类别后自动带出） ──
  Widget _buildAcctSubjectCard(AppColorsExtension colors) {
    return _readOnlyCard(
      label: _l10n.get('acctSubject'),
      value: '${_selCat.acctSubjectId}/${_selCat.acctSubjectName}',
      colors: colors,
    );
  }

  // ── 3. 关联项目 ──
  Widget _buildProjectPicker(AppColorsExtension colors) {
    return _pickerCard(
      label: _l10n.get('relatedProject'),
      required: false,
      currentLabel: _selProject != null ? '${_selProject!.id}/${_selProject!.name}' : _l10n.get('pleaseSelect'),
      labels: _projects.map((p) => '${p.id}/${p.name}').toList(),
      colors: colors,
      onSelected: (idx) => setState(() => _selProject = _projects[idx]),
      onClear: _selProject != null ? () => setState(() => _selProject = null) : null,
    );
  }

  // ── 5. 费用承担部门 ──
  Widget _buildCostDeptPicker(AppColorsExtension colors) {
    return _pickerCard(
      label: _l10n.get('costDept'),
      required: false,
      currentLabel: _selDept != null ? '${_selDept!.id}/${_selDept!.name}' : _l10n.get('pleaseSelect'),
      labels: _depts.map((d) => '${d.id}/${d.name}').toList(),
      colors: colors,
      onSelected: (idx) => setState(() => _selDept = _depts[idx]),
      onClear: _selDept != null ? () => setState(() => _selDept = null) : null,
    );
  }

  // ── 6. 预计开始日期 ──
  Widget _buildStartDatePicker(AppColorsExtension colors) {
    return _datePickerCard(
      label: _l10n.get('estimatedStartDate'),
      value: _startDate,
      hint: _l10n.get('pleaseSelect'),
      colors: colors,
      onPick: (d) => setState(() => _startDate = d),
      onClear: _startDate.isNotEmpty ? () => setState(() => _startDate = '') : null,
    );
  }

  // ── 7. 预计结束日期 ──
  Widget _buildEndDatePicker(AppColorsExtension colors) {
    return _datePickerCard(
      label: _l10n.get('estimatedEndDate'),
      value: _endDate,
      hint: _l10n.get('pleaseSelect'),
      colors: colors,
      onPick: (d) => setState(() => _endDate = d),
      onClear: _endDate.isNotEmpty ? () => setState(() => _endDate = '') : null,
    );
  }

  Widget _datePickerCard({
    required String label,
    required String value,
    required String hint,
    required AppColorsExtension colors,
    required ValueChanged<String> onPick,
    VoidCallback? onClear,
  }) {
    final tdTheme = TDTheme.of(context);
    final hasValue = value.isNotEmpty;
    return GestureDetector(
      onTap: () => _pickDate(onPick),
      child: Container(
        padding: const EdgeInsets.only(
          left: 16, right: 10, top: 12, bottom: 12,
        ),
        decoration: BoxDecoration(
          color: tdTheme.bgColorContainer,
          borderRadius: BorderRadius.circular(tdTheme.radiusDefault),
          border: Border.all(color: tdTheme.componentStrokeColor),
        ),
        child: Row(
          children: [
            TDText(
              label,
              maxLines: 1,
              overflow: TextOverflow.visible,
              font: tdTheme.fontBodyLarge,
              fontWeight: FontWeight.w400,
              style: const TextStyle(letterSpacing: 0),
            ),
            const SizedBox(width: 12),
            Expanded(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.end,
                mainAxisSize: MainAxisSize.max,
                children: [
                  Flexible(
                    child: TDText(
                      value.isEmpty ? hint : value,
                      maxLines: 1,
                      overflow: TextOverflow.ellipsis,
                      font: tdTheme.fontBodyLarge,
                      fontWeight: FontWeight.w400,
                      textColor: value.isEmpty
                          ? tdTheme.textColorPlaceholder
                          : tdTheme.textColorPrimary,
                      textAlign: TextAlign.end,
                    ),
                  ),
                  const SizedBox(width: 4),
                  SizedBox(
                    width: 18, height: 18,
                    child: hasValue
                        ? GestureDetector(
                            onTap: onClear,
                            child: Icon(Icons.close, size: 18, color: tdTheme.textColorPlaceholder),
                          )
                        : Icon(Icons.chevron_right, size: 18, color: tdTheme.textColorPlaceholder),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  void _pickDate(ValueChanged<String> onPick) {
    final l10n = AppLocalizations.of(context);
    final colors = Theme.of(context).extension<AppColorsExtension>()!;
    final now = DateTime.now();
    TDPicker.showDatePicker(
      context,
      title: l10n.get('selectDate'),
      backgroundColor: colors.bgCard,
      useYear: true, useMonth: true, useDay: true,
      useHour: false, useMinute: false, useSecond: false, useWeekDay: false,
      dateStart: const [2020, 1, 1],
      dateEnd: [now.year + 1, 12, 31],
      initialDate: [now.year, now.month, now.day],
      onConfirm: (selected) {
        onPick(
          '${selected['year']}-${selected['month'].toString().padLeft(2, '0')}-${selected['day'].toString().padLeft(2, '0')}',
        );
        Navigator.of(context).pop();
      },
    );
  }

  // ── 8. 预估金额 ──
  Widget _buildAmountInput(AppColorsExtension colors) {
    final tdTheme = TDTheme.of(context);
    final hasValue = _amountCtrl.text.isNotEmpty;
    return Container(
      padding: const EdgeInsets.only(left: 16, right: 10, top: 0, bottom: 0),
      decoration: BoxDecoration(
        color: tdTheme.bgColorContainer,
        borderRadius: BorderRadius.circular(tdTheme.radiusDefault),
        border: Border.all(color: tdTheme.componentStrokeColor),
      ),
      child: Row(
        children: [
          TDText(
            _l10n.get('estimatedAmount'),
            maxLines: 1,
            overflow: TextOverflow.visible,
            font: tdTheme.fontBodyLarge,
            fontWeight: FontWeight.w400,
            style: const TextStyle(letterSpacing: 0),
          ),
          Padding(
            padding: const EdgeInsets.only(left: 4),
            child: TDText(
              '*',
              font: tdTheme.fontBodyLarge,
              fontWeight: FontWeight.w400,
              style: TextStyle(color: tdTheme.errorColor6),
            ),
          ),
          const SizedBox(width: 12),
          Expanded(
            child: TextField(
              controller: _amountCtrl,
              focusNode: _amountFocus,
              textAlign: TextAlign.end,
              keyboardType: const TextInputType.numberWithOptions(decimal: true),
              style: TextStyle(
                fontSize: 16,
                color: tdTheme.textColorPrimary,
              ),
              decoration: InputDecoration(
                hintText: _l10n.get('enterEstimatedAmount'),
                hintStyle: TextStyle(
                  color: tdTheme.textColorPlaceholder,
                ),
                border: InputBorder.none,
                isDense: true,
                contentPadding: const EdgeInsets.symmetric(vertical: 12),
              ),
              onChanged: (_) => setState(() {}),
            ),
          ),
          if (hasValue)
            GestureDetector(
              onTap: () {
                _amountCtrl.clear();
                setState(() {});
              },
              child: Padding(
                padding: const EdgeInsets.all(4),
                child: Icon(
                  Icons.close,
                  size: 18,
                  color: tdTheme.textColorPlaceholder,
                ),
              ),
            ),
        ],
      ),
    );
  }

  // ── 9. 备注 ──
  Widget _buildRemarkInput(AppColorsExtension colors) {
    final tdTheme = TDTheme.of(context);
    return TDTextarea(
      controller: _remarkCtrl,
      focusNode: _remarkFocus,
      label: _l10n.get('remark'),
      hintText: _l10n.get('enterRemark'),
      maxLines: 3,
      minLines: 1,
      maxLength: 500,
      indicator: true,
      decoration: BoxDecoration(
        color: tdTheme.bgColorContainer,
        borderRadius: BorderRadius.circular(tdTheme.radiusDefault),
        border: Border.all(color: tdTheme.componentStrokeColor),
      ),
      onChanged: (_) => setState(() {}),
    );
  }

  // ── 操作按钮 ──
  Widget _buildActions() {
    return Row(
      children: [
        Expanded(
          child: TDButton(
            text: _l10n.get('cancel'),
            size: TDButtonSize.large,
            type: TDButtonType.outline,
            shape: TDButtonShape.rectangle,
            theme: TDButtonTheme.defaultTheme,
            onTap: () => Navigator.pop(context),
          ),
        ),
        const SizedBox(width: 12),
        Expanded(
          child: TDButton(
            text: _isEdit ? _l10n.get('confirmEdit') : _l10n.get('add'),
            size: TDButtonSize.large,
            type: TDButtonType.fill,
            shape: TDButtonShape.rectangle,
            theme: TDButtonTheme.primary,
            onTap: _confirm,
          ),
        ),
      ],
    );
  }
}
