import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:tdesign_flutter/tdesign_flutter.dart';

import '../../core/i18n/app_localizations.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/app_skeletons.dart';
import '../../shared/widgets/bill_status_bar.dart';
import '../../core/navigation/host_app_channel.dart';
import '../../core/theme/app_colors.dart';
import '../../core/theme/app_colors_extension.dart';
import 'overtime_apply_model.dart';
import 'widgets/overtime_apply_detail_view_dialog.dart';
import 'overtime_apply_api.dart';

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

  @override
  ConsumerState<OvertimeApplyDetailPage> createState() =>
      _OvertimeApplyDetailPageState();
}

class _OvertimeApplyDetailPageState
    extends ConsumerState<OvertimeApplyDetailPage> {
  bool _loading = true;
  String? _error;
  OvertimeApplyModel? _data;
  BillStatusBar? _billStatusBar;

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

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

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

      if (mounted) {
        setState(() {
          _data = detail;
          _loading = false;
        });
      }

      // 单据状态（非关键，尽力加载）
      try {
        final status = await api.getBillStatus(widget.billNo);
        if (mounted) {
          setState(() {
            _billStatusBar = BillStatusBar(
              billStatus: status,
              onEdit: () {
                context
                    .push('/overtime-apply/edit/${widget.billNo}')
                    .then((_) => _loadData());
              },
              onSubmit: () {
                final api = ref.read(overtimeApplyApiProvider);
                final jbDdStr = _data?.jbDd != null
                    ? du.DateUtils.formatDate(_data!.jbDd!)
                    : '';
                if (jbDdStr.isNotEmpty) {
                  api
                      .shSubmit(bilNo: widget.billNo, bilDd: jbDdStr)
                      .then((_) => _loadData());
                }
              },
              onCancelSubmit: () {
                final api = ref.read(overtimeApplyApiProvider);
                final jbDdStr = _data?.jbDd != null
                    ? du.DateUtils.formatDate(_data!.jbDd!)
                    : '';
                if (jbDdStr.isNotEmpty) {
                  api
                      .shSubmit(
                        bilNo: widget.billNo,
                        bilDd: jbDdStr,
                        isCancel: true,
                      )
                      .then((_) => _loadData());
                }
              },
              onTapStatusTag: () {
                _showAuditTrail('OT');
              },
            );
          });
        }
      } catch (_) {} // ignore non-critical status load failure
    } catch (e) {
      if (mounted) {
        setState(() {
          _error = e.toString();
          _loading = false;
        });
      }
    }
  }

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

    if (_loading) {
      return const SkeletonDetailPage(sectionRows: [8, 3]);
    }

    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(
            physics: const AlwaysScrollableScrollPhysics(),
            padding: const EdgeInsets.all(16),
            child: Column(
              children: [
                _buildBasicInfoSection(app, l10n, colors),
                const SizedBox(height: 16),
                _buildOvertimeDetailSection(app, l10n, colors),
                const SizedBox(height: 24),
                _billStatusBar?.buildActions(context) ??
                    const SizedBox.shrink(),
                _buildPageFooter(colors),
              ],
            ),
          ),
        ),
      ],
    );
  }

  Future<void> _showAuditTrail(String billId) async {
    await HostAppChannel.showAuditTrail(billId, widget.billNo);
  }

  // ═══ 基本信息 ═══
  Widget _buildBasicInfoSection(
    OvertimeApplyModel app,
    AppLocalizations l10n,
    AppColorsExtension colors,
  ) {
    return FormSection(
      title: l10n.get('basicInfo'),
      leadingIcon: Icons.info_outline,
      trailing: _billStatusBar?.buildStatusTag(context),
      children: [
        FormFieldRow(
          label: l10n.get('overtimeApplyNo'),
          value: app.jbNo,
          readOnly: true,
          showArrow: false,
        ),
        const SizedBox(height: 16),
        FormFieldRow(
          label: l10n.get('date'),
          value: app.jbDd != null ? du.DateUtils.formatDate(app.jbDd!) : '-',
          readOnly: true,
          showArrow: false,
        ),
        const SizedBox(height: 16),
        FormFieldRow(
          label: l10n.get('applicant'),
          value: app.salNo.isNotEmpty
              ? '${app.salNo}${app.salName.isNotEmpty ? '/${app.salName}' : ''}'
              : '-',
          readOnly: true,
          showArrow: false,
        ),
        const SizedBox(height: 16),
        FormFieldRow(
          label: l10n.get('dep'),
          value: app.dep.isNotEmpty
              ? '${app.dep}${app.depName.isNotEmpty ? '/${app.depName}' : ''}'
              : '-',
          readOnly: true,
          showArrow: false,
        ),
        const SizedBox(height: 16),
        FormFieldRow(
          label: l10n.get('overtimeReason'),
          value: app.reason.isNotEmpty ? app.reason : '-',
          readOnly: true,
          showArrow: false,
          bold: true,
          showMoreOnOverflow: true,
        ),
        const SizedBox(height: 16),
        FormFieldRow(
          label: l10n.get('remark'),
          value: app.rem.isNotEmpty ? app.rem : '-',
          readOnly: true,
          showArrow: false,
          bold: false,
          showMoreOnOverflow: true,
        ),
        const SizedBox(height: 16),
        FormFieldRow(
          label: l10n.get('chkMan'),
          value: app.chkMan.isNotEmpty ? app.chkMan : '-',
          readOnly: true,
          showArrow: false,
        ),
        const SizedBox(height: 16),
        FormFieldRow(
          label: l10n.get('clsDate'),
          value: app.clsDate != null
              ? du.DateUtils.formatDate(app.clsDate!)
              : '-',
          readOnly: true,
          showArrow: false,
        ),
      ],
    );
  }

  // ═══ 加班明细 ═══
  Widget _buildOvertimeDetailSection(
    OvertimeApplyModel app,
    AppLocalizations l10n,
    AppColorsExtension colors,
  ) {
    return FormSection(
      title: l10n.get('overtimeDetails'),
      leadingIcon: Icons.access_time_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.map((d) => _buildDetailCard(d, l10n, colors)),
        if (app.details.isNotEmpty) ...[
          const SizedBox(height: 8),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Text(
                l10n.get('totalOvertimeHours'),
                style: TextStyle(
                  fontSize: AppFontSizes.body,
                  fontWeight: FontWeight.w600,
                  color: colors.textPrimary,
                ),
              ),
              Text(
                '${_totalHours(app).toStringAsFixed(1)}${l10n.get('hours')}',
                style: TextStyle(
                  fontSize: AppFontSizes.subtitle,
                  fontWeight: FontWeight.w700,
                  color: colors.timePrimary,
                ),
              ),
            ],
          ),
        ],
      ],
    );
  }

  double _totalHours(OvertimeApplyModel app) =>
      app.details.fold(0.0, (s, d) => s + d.jbHours);

  Widget _buildDetailCard(
    OvertimeApplyDetailModel d,
    AppLocalizations l10n,
    AppColorsExtension colors,
  ) {
    // 开始/结束时间格式化
    String formatDateTime(DateTime dt) {
      return '${dt.year}-${dt.month.toString().padLeft(2, '0')}-${dt.day.toString().padLeft(2, '0')} '
          '${dt.hour.toString().padLeft(2, '0')}:${dt.minute.toString().padLeft(2, '0')}';
    }

    return GestureDetector(
      onTap: () => OvertimeApplyDetailViewDialog.show(context, d),
      child: Container(
        margin: const EdgeInsets.symmetric(vertical: 6),
        padding: const EdgeInsets.all(12),
        decoration: BoxDecoration(
          color: colors.bgPage,
          borderRadius: BorderRadius.circular(8),
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 第一行：员工 + 时长
            Row(
              children: [
                Expanded(
                  child: Text(
                    '${d.salNo}${d.salName.isNotEmpty ? '/${d.salName}' : ''}',
                    maxLines: 1,
                    overflow: TextOverflow.ellipsis,
                    style: TextStyle(
                      fontSize: AppFontSizes.body,
                      fontWeight: FontWeight.w500,
                      color: colors.textPrimary,
                    ),
                  ),
                ),
                Text(
                  '${d.jbHours.toStringAsFixed(1)}${l10n.get('hours')}',
                  style: TextStyle(
                    fontSize: AppFontSizes.body,
                    fontWeight: FontWeight.w600,
                    color: colors.timePrimary,
                  ),
                ),
              ],
            ),
            if (d.jbType.isNotEmpty) ...[
              const SizedBox(height: 2),
              _detailLabel(
                '${l10n.get('jbType')}: ${_jbTypeLabel(d.jbType, l10n)}',
                colors,
              ),
              if (d.jbDate != null)
                _detailLabel(
                  '${l10n.get('applyDate')}: ${du.DateUtils.formatDate(d.jbDate!)}',
                  colors,
                ),
            ],
            if (d.startTime != null) ...[
              const SizedBox(height: 2),
              Row(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  Expanded(
                    child: _detailLabel(
                      '${l10n.get('startTime')}: ${formatDateTime(d.startTime!)}',
                      colors,
                    ),
                  ),
                  _dayOfWeekTag(_dayOfWeekLabelFromDate(d.startTime!, l10n)),
                ],
              ),
            ],
            if (d.endTime != null) ...[
              const SizedBox(height: 2),
              Row(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  Expanded(
                    child: _detailLabel(
                      '${l10n.get('endTime')}: ${formatDateTime(d.endTime!)}',
                      colors,
                    ),
                  ),
                  _dayOfWeekTag(_dayOfWeekLabelFromDate(d.endTime!, l10n)),
                ],
              ),
            ],
            if (d.jbDays > 0) ...[
              const SizedBox(height: 2),
              _detailLabel(
                '${l10n.get('overtimeDays')}: ${d.jbDays.toStringAsFixed(1)}',
                colors,
              ),
            ],
            if (d.attPeriod.isNotEmpty) ...[
              const SizedBox(height: 2),
              _detailLabel('${l10n.get('attPeriod')}: ${d.attPeriod}', colors),
            ],
            if (d.compensationType.isNotEmpty) ...[
              const SizedBox(height: 2),
              _detailLabel(
                '${l10n.get('compensationType')}: ${_compensationTypeLabel(d.compensationType, l10n)}',
                colors,
              ),
              if (d.compensationType != 'NO_COMPENSATION' &&
                  d.compensationCount > 0)
                _detailLabel(
                  '${l10n.get('compensationCount')}: ${d.compensationCount.toStringAsFixed(1)}',
                  colors,
                ),
            ],
            if (d.adr.isNotEmpty) ...[
              const SizedBox(height: 2),
              _detailLabel('${l10n.get('adr')}: ${d.adr}', colors),
            ],
            if (d.reason.isNotEmpty) ...[
              const SizedBox(height: 2),
              _detailLabel(
                '${l10n.get('overtimeDetailReason')}: ${d.reason}',
                colors,
              ),
            ],
            if (d.rem.isNotEmpty) ...[
              const SizedBox(height: 2),
              _detailLabel('${l10n.get('remark')}: ${d.rem}', colors),
            ],
          ],
        ),
      ),
    );
  }

  String _dayOfWeekLabelFromDate(DateTime dt, AppLocalizations l10n) {
    switch (dt.weekday) {
      case 1:
        return l10n.get('monday');
      case 2:
        return l10n.get('tuesday');
      case 3:
        return l10n.get('wednesday');
      case 4:
        return l10n.get('thursday');
      case 5:
        return l10n.get('friday');
      case 6:
        return l10n.get('saturday');
      case 7:
        return l10n.get('sunday');
      default:
        return '';
    }
  }

  Widget _detailLabel(String text, AppColorsExtension colors) {
    return Padding(
      padding: const EdgeInsets.only(top: 2),
      child: Text(
        text,
        maxLines: 2,
        overflow: TextOverflow.ellipsis,
        style: TextStyle(
          fontSize: AppFontSizes.caption,
          color: colors.textSecondary,
        ),
      ),
    );
  }

  Widget _dayOfWeekTag(String label) {
    final tdTheme = TDTheme.of(context);
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 6),
      decoration: BoxDecoration(
        color: tdTheme.brandColor1,
        borderRadius: BorderRadius.circular(4),
      ),
      child: TDText(
        label,
        font: tdTheme.fontBodySmall,
        fontWeight: FontWeight.w500,
        textColor: tdTheme.brandColor7,
      ),
    );
  }

  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');
      case 'OTHER':
        return l10n.get('other');
      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');
      case 'OTHER':
        return l10n.get('other');
      default:
        return type;
    }
  }

  Widget _buildPageFooter(AppColorsExtension colors) {
    final l10n = AppLocalizations.of(context);
    return Center(
      child: Padding(
        padding: const EdgeInsets.only(bottom: 16),
        child: Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(
              Icons.rocket_launch_outlined,
              size: 16,
              color: colors.textPlaceholder,
            ),
            const SizedBox(width: 6),
            Text(
              l10n.get('pageFooter'),
              style: TextStyle(
                fontSize: AppFontSizes.caption,
                color: colors.textPlaceholder,
              ),
            ),
          ],
        ),
      ),
    );
  }
}
