import 'dart:async';

import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:go_router/go_router.dart';
import 'package:intl/intl.dart' as intl;
import 'package:lucide_icons_flutter/lucide_icons.dart' as lucide;
import 'package:shadcn_ui/shadcn_ui.dart';

import '../../../../core/config/environment.dart';
import '../../../../core/constants/app_sections.dart';
import '../../../../core/permissions/permission_manager.dart';
import '../../../../core/permissions/permission_resources.dart';
import '../../../../widgets/app_layout.dart';
import '../../../../widgets/components/feedback.dart';
import '../../../../widgets/components/filter_bar.dart';
import '../../../../widgets/components/superport_dialog.dart';
import '../../../../widgets/components/superport_table.dart';
import '../../../../widgets/components/superport_pagination_controls.dart';
import '../../../../widgets/components/feature_disabled_placeholder.dart';
import '../../domain/entities/approval.dart';
import '../../domain/repositories/approval_repository.dart';
import '../../domain/repositories/approval_template_repository.dart';
import '../../domain/usecases/get_approval_draft_use_case.dart';
import '../../domain/usecases/list_approval_drafts_use_case.dart';
import '../../domain/usecases/save_approval_draft_use_case.dart';
import '../../../inventory/lookups/domain/repositories/inventory_lookup_repository.dart';
import '../../../inventory/shared/widgets/employee_autocomplete_field.dart';
import '../controllers/approval_controller.dart';
import '../dialogs/approval_detail_dialog.dart';

const _approvalsResourcePath = PermissionResources.approvals;

/// 결재 관리 최상위 페이지.
///
/// 기능 플래그에 따라 실제 화면 또는 비활성 안내 화면을 보여준다.
class ApprovalPage extends StatelessWidget {
  const ApprovalPage({super.key, this.routeUri});

  final Uri? routeUri;

  @override
  Widget build(BuildContext context) {
    final enabled = Environment.flag('FEATURE_APPROVALS_ENABLED');
    if (!enabled) {
      return AppLayout(
        title: '결재 관리',
        subtitle: '결재 요청 상태와 단계/이력을 한 화면에서 확인합니다.',
        breadcrumbs: const [
          AppBreadcrumbItem(label: '대시보드', path: dashboardRoutePath),
          AppBreadcrumbItem(label: '결재', path: '/approvals/requests'),
          AppBreadcrumbItem(label: '결재 관리'),
        ],
        actions: [
          Tooltip(
            message: '백엔드 연동 후 사용 가능합니다.',
            child: ShadButton(
              onPressed: null,
              leading: const Icon(lucide.LucideIcons.plus, size: 16),
              child: const Text('신규 결재'),
            ),
          ),
        ],
        child: const FeatureDisabledPlaceholder(
          title: '결재 관리 기능 준비 중',
          description: '결재 API 연결이 완료되면 실제 결재 요청 목록과 단계 정보를 제공합니다.',
        ),
      );
    }

    return _ApprovalEnabledPage(routeUri: routeUri);
  }
}

/// 결재 기능이 활성화되었을 때 사용되는 실제 페이지 위젯.
class _ApprovalEnabledPage extends StatefulWidget {
  const _ApprovalEnabledPage({this.routeUri});

  final Uri? routeUri;

  @override
  State<_ApprovalEnabledPage> createState() => _ApprovalEnabledPageState();
}

class _ApprovalEnabledPageState extends State<_ApprovalEnabledPage> {
  late final ApprovalController _controller;
  final TextEditingController _transactionController = TextEditingController();
  final TextEditingController _requesterController = TextEditingController();
  final FocusNode _transactionFocus = FocusNode();
  InventoryEmployeeSuggestion? _selectedRequester;
  final intl.DateFormat _dateTimeFormat = intl.DateFormat('yyyy-MM-dd HH:mm');
  String? _lastError;
  String? _lastAccessDeniedMessage;
  String? _pendingRouteSelection;

  @override
  void initState() {
    super.initState();
    _pendingRouteSelection = _parseRouteSelection(widget.routeUri);
    _controller = ApprovalController(
      approvalRepository: GetIt.I<ApprovalRepository>(),
      templateRepository: GetIt.I<ApprovalTemplateRepository>(),
      lookupRepository: GetIt.I.isRegistered<InventoryLookupRepository>()
          ? GetIt.I<InventoryLookupRepository>()
          : null,
      saveDraftUseCase: GetIt.I.isRegistered<SaveApprovalDraftUseCase>()
          ? GetIt.I<SaveApprovalDraftUseCase>()
          : null,
      getDraftUseCase: GetIt.I.isRegistered<GetApprovalDraftUseCase>()
          ? GetIt.I<GetApprovalDraftUseCase>()
          : null,
      listDraftsUseCase: GetIt.I.isRegistered<ListApprovalDraftsUseCase>()
          ? GetIt.I<ListApprovalDraftsUseCase>()
          : null,
    )..addListener(_handleControllerUpdate);
    WidgetsBinding.instance.addPostFrameCallback((_) async {
      await Future.wait([
        _controller.loadActionOptions(),
        _controller.loadTemplates(),
        _controller.loadStatusLookups(),
      ]);
      await _controller.fetch();
      _applyRouteSelectionIfNeeded(
        _controller.result?.items ?? const <Approval>[],
      );
    });
  }

  @override
  void didUpdateWidget(covariant _ApprovalEnabledPage oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.routeUri != widget.routeUri) {
      _pendingRouteSelection = _parseRouteSelection(widget.routeUri);
      final currentResult = _controller.result;
      if (currentResult != null) {
        _applyRouteSelectionIfNeeded(currentResult.items);
      }
    }
  }

  void _handleControllerUpdate() {
    final error = _controller.errorMessage;
    if (_controller.isAccessDenied) {
      final message = _controller.accessDeniedMessage ?? '결재를 조회할 권한이 없습니다.';
      if (mounted) {
        if (_lastAccessDeniedMessage != message) {
          SuperportToast.warning(context, message);
          _lastAccessDeniedMessage = message;
        }
        final router = GoRouter.maybeOf(context);
        router?.go(dashboardRoutePath);
      }
      _controller.acknowledgeAccessDenied();
      return;
    } else {
      _lastAccessDeniedMessage = null;
    }
    if (error != null && error != _lastError && mounted) {
      _lastError = error;
      SuperportToast.error(context, error);
      _controller.clearError();
    }
  }

  /// 라우트 쿼리에서 선택된 결재번호를 읽어온다.
  String? _parseRouteSelection(Uri? routeUri) {
    final value = routeUri?.queryParameters['selected']?.trim();
    if (value == null || value.isEmpty) {
      return null;
    }
    return value;
  }

  /// 최초 로딩 시 라우트에서 전달된 결재번호가 있으면 자동으로 상세를 연다.
  void _applyRouteSelectionIfNeeded(List<Approval> approvals) {
    final target = _pendingRouteSelection;
    if (target == null) {
      return;
    }
    for (final approval in approvals) {
      if (approval.approvalNo == target && approval.id != null) {
        WidgetsBinding.instance.addPostFrameCallback((_) {
          if (!mounted) return;
          unawaited(_openApprovalDetailDialog(approval));
        });
        break;
      }
    }
    _pendingRouteSelection = null;
  }

  Future<void> _openApprovalDetailDialog(Approval approval) async {
    final id = approval.id;
    if (id == null) {
      SuperportToast.error(context, 'ID 정보가 없어 상세를 열 수 없습니다.');
      return;
    }

    await _controller.selectApproval(id);
    if (!mounted) {
      return;
    }

    final selected = _controller.selected;
    final error = _controller.errorMessage;
    if (selected == null) {
      if (error != null) {
        SuperportToast.error(context, error);
        _controller.clearError();
      } else {
        SuperportToast.error(context, '결재 상세 정보를 불러오지 못했습니다.');
      }
      return;
    }

    if (_controller.templates.isEmpty && !_controller.isLoadingTemplates) {
      await _controller.loadTemplates(force: true);
      if (!mounted) {
        return;
      }
    }

    final permissionScope = PermissionScope.of(context);
    final canPerformStepActions = permissionScope.can(
      _approvalsResourcePath,
      PermissionAction.approve,
    );
    final canApplyTemplate = permissionScope.can(
      _approvalsResourcePath,
      PermissionAction.edit,
    );

    await showApprovalDetailDialog(
      context: context,
      controller: _controller,
      dateFormat: _dateTimeFormat,
      canPerformStepActions: canPerformStepActions,
      canApplyTemplate: canApplyTemplate,
    );

    if (!mounted) {
      return;
    }

    _controller.clearSelection();
  }

  @override
  void dispose() {
    _controller.removeListener(_handleControllerUpdate);
    _controller.dispose();
    _transactionController.dispose();
    _requesterController.dispose();
    _transactionFocus.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final theme = ShadTheme.of(context);

    return AnimatedBuilder(
      animation: _controller,
      builder: (context, _) {
        final result = _controller.result;
        final approvals = result?.items ?? const <Approval>[];
        if (result != null) {
          _applyRouteSelectionIfNeeded(approvals);
        }
        final totalCount = result?.total ?? 0;
        final currentPage = result?.page ?? 1;
        final totalPages = result == null || result.pageSize == 0
            ? 1
            : (result.total / result.pageSize).ceil().clamp(1, 9999);

        return AppLayout(
          title: '결재 관리',
          subtitle: '결재 요청 상태와 단계/이력을 한 화면에서 확인합니다.',
          breadcrumbs: const [
            AppBreadcrumbItem(label: '대시보드', path: dashboardRoutePath),
            AppBreadcrumbItem(label: '결재', path: '/approvals/requests'),
            AppBreadcrumbItem(label: '결재 관리'),
          ],
          actions: [
            ShadButton(
              leading: const Icon(lucide.LucideIcons.plus, size: 16),
              onPressed: _openCreateApprovalDialog,
              child: const Text('신규 결재'),
            ),
          ],
          toolbar: FilterBar(
            actionConfig: FilterBarActionConfig(
              onApply: _applyFilters,
              onReset: _resetFilters,
              hasPendingChanges: false,
              hasActiveFilters: _hasFilters(),
              applyEnabled: !_controller.isLoadingList,
              resetLabel: '필터 초기화',
              resetKey: const ValueKey('approval_filter_reset'),
              resetEnabled: !_controller.isLoadingList && _hasFilters(),
              showReset: true,
            ),
            children: [
              SizedBox(
                width: 180,
                child: ShadInput(
                  controller: _transactionController,
                  focusNode: _transactionFocus,
                  enabled: !_controller.isLoadingList,
                  keyboardType: TextInputType.number,
                  placeholder: const Text('트랜잭션 ID 입력'),
                  leading: const Icon(lucide.LucideIcons.hash, size: 16),
                  onChanged: (_) => setState(() {}),
                  onSubmitted: (_) => _applyFilters(),
                ),
              ),
              SizedBox(
                width: 280,
                child: InventoryEmployeeAutocompleteField(
                  controller: _requesterController,
                  initialSuggestion: _selectedRequester,
                  enabled: !_controller.isLoadingList,
                  onSuggestionSelected: (suggestion) {
                    setState(() => _selectedRequester = suggestion);
                  },
                  onChanged: () {
                    setState(() {
                      final selectedLabel = _selectedRequester == null
                          ? ''
                          : '${_selectedRequester!.name} (${_selectedRequester!.employeeNo})';
                      if (_requesterController.text.trim() != selectedLabel) {
                        _selectedRequester = null;
                      }
                    });
                  },
                ),
              ),
              SizedBox(
                width: 200,
                child: Tooltip(
                  message: '전체 상태 선택 시 임시저장·상신·진행중 결재까지 함께 조회합니다.',
                  waitDuration: const Duration(milliseconds: 200),
                  child: ShadSelect<ApprovalStatusFilter>(
                    key: ValueKey(_controller.statusFilter),
                    initialValue: _controller.statusFilter,
                    selectedOptionBuilder: (context, value) =>
                        Text(_statusLabel(value)),
                    onChanged: (value) {
                      if (value == null) return;
                      _controller.updateStatusFilter(value);
                      _controller.fetch(page: 1);
                    },
                    options: ApprovalStatusFilter.values
                        .map(
                          (filter) => ShadOption(
                            value: filter,
                            child: Text(_statusLabel(filter)),
                          ),
                        )
                        .toList(),
                  ),
                ),
              ),
            ],
          ),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              ShadCard(
                title: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text('결재 목록', style: theme.textTheme.h3),
                    Text('$totalCount건', style: theme.textTheme.muted),
                  ],
                ),
                footer: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text(
                      '페이지 $currentPage / $totalPages',
                      style: theme.textTheme.small,
                    ),
                    SuperportPaginationControls(
                      currentPage: currentPage,
                      totalPages: totalPages,
                      isBusy: _controller.isLoadingList,
                      onPageSelected: (page) => _controller.fetch(page: page),
                    ),
                  ],
                ),
                child: _controller.isLoadingList
                    ? const Padding(
                        padding: EdgeInsets.all(48),
                        child: Center(child: CircularProgressIndicator()),
                      )
                    : approvals.isEmpty
                    ? Padding(
                        padding: const EdgeInsets.all(32),
                        child: Text(
                          '조건에 맞는 결재 내역이 없습니다.',
                          style: theme.textTheme.muted,
                        ),
                      )
                    : _ApprovalTable(
                        approvals: approvals,
                        dateFormat: _dateTimeFormat,
                        onView: (approval) {
                          unawaited(_openApprovalDetailDialog(approval));
                        },
                      ),
              ),
              const SizedBox(height: 24),
            ],
          ),
        );
      },
    );
  }

  /// 신규 결재 등록 다이얼로그를 열어 UI 단계에서 필요한 필드와 안내를 제공한다.
  Future<void> _openCreateApprovalDialog() async {
    final transactionController = TextEditingController();
    final requesterController = TextEditingController();
    final noteController = TextEditingController();
    String? createdApprovalNo;
    InventoryEmployeeSuggestion? requesterSelection;
    int? statusId = _controller.defaultApprovalStatusId;
    String? transactionError;
    String? statusError;
    String? requesterError;

    final created = await showDialog<bool>(
      context: context,
      builder: (_) {
        return StatefulBuilder(
          builder: (context, setState) {
            return AnimatedBuilder(
              animation: _controller,
              builder: (context, _) {
                final shadTheme = ShadTheme.of(context);
                final materialTheme = Theme.of(context);
                final statusOptions = _controller.approvalStatusOptions;
                final isSubmitting = _controller.isSubmitting;
                statusId ??= _controller.defaultApprovalStatusId;

                return SuperportDialog(
                  title: '신규 결재 등록',
                  description: '트랜잭션과 결재 정보를 입력하면 즉시 생성됩니다.',
                  constraints: const BoxConstraints(maxWidth: 540),
                  actions: [
                    ShadButton.ghost(
                      onPressed: isSubmitting
                          ? null
                          : () => Navigator.of(
                              context,
                              rootNavigator: true,
                            ).pop(false),
                      child: const Text('취소'),
                    ),
                    ShadButton(
                      key: const ValueKey('approval_create_submit'),
                      onPressed: isSubmitting
                          ? null
                          : () async {
                              final transactionText = transactionController.text
                                  .trim();
                              final transactionId = int.tryParse(
                                transactionText,
                              );
                              final note = noteController.text.trim();
                              final hasStatuses = statusOptions.isNotEmpty;

                              setState(() {
                                transactionError = transactionText.isEmpty
                                    ? '트랜잭션 ID를 입력하세요.'
                                    : (transactionId == null
                                          ? '트랜잭션 ID는 숫자만 입력하세요.'
                                          : null);
                                statusError = (!hasStatuses || statusId == null)
                                    ? '결재 상태를 선택하세요.'
                                    : null;
                                requesterError = requesterSelection == null
                                    ? '상신자를 선택하세요.'
                                    : null;
                              });

                              if (transactionError != null ||
                                  statusError != null ||
                                  requesterError != null) {
                                return;
                              }

                              final input = ApprovalCreateInput(
                                transactionId: transactionId!,
                                approvalStatusId: statusId!,
                                requestedById: requesterSelection!.id,
                                note: note.isEmpty ? null : note,
                              );
                              final result = await _controller.createApproval(
                                input,
                              );
                              if (!mounted || !context.mounted) {
                                return;
                              }
                              if (result != null) {
                                createdApprovalNo = result.approvalNo;
                                Navigator.of(
                                  context,
                                  rootNavigator: true,
                                ).pop(true);
                              }
                            },
                      child: isSubmitting
                          ? const SizedBox(
                              width: 16,
                              height: 16,
                              child: CircularProgressIndicator(strokeWidth: 2),
                            )
                          : const Text('등록'),
                    ),
                  ],
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Container(
                        padding: const EdgeInsets.all(12),
                        decoration: BoxDecoration(
                          color: shadTheme.colorScheme.mutedForeground
                              .withValues(alpha: 0.08),
                          borderRadius: BorderRadius.circular(12),
                        ),
                        child: Text(
                          '결재번호는 저장 시 자동으로 생성됩니다.',
                          style: shadTheme.textTheme.muted,
                        ),
                      ),
                      const SizedBox(height: 16),
                      Text('트랜잭션 ID', style: shadTheme.textTheme.small),
                      const SizedBox(height: 8),
                      ShadInput(
                        key: const ValueKey('approval_create_transaction'),
                        controller: transactionController,
                        enabled: !isSubmitting,
                        placeholder: const Text('예: 9001'),
                        onChanged: (_) {
                          if (transactionError != null) {
                            setState(() => transactionError = null);
                          }
                        },
                      ),
                      if (transactionError != null)
                        Padding(
                          padding: const EdgeInsets.only(top: 6),
                          child: Text(
                            transactionError!,
                            style: shadTheme.textTheme.small.copyWith(
                              color: materialTheme.colorScheme.error,
                            ),
                          ),
                        ),
                      const SizedBox(height: 16),
                      Text('결재 상태', style: shadTheme.textTheme.small),
                      const SizedBox(height: 8),
                      if (statusOptions.isEmpty)
                        Container(
                          padding: const EdgeInsets.all(12),
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(12),
                            border: Border.all(
                              color: shadTheme.colorScheme.border,
                            ),
                          ),
                          child: Text(
                            '결재 상태 정보를 불러오지 못했습니다. 다시 시도해주세요.',
                            style: shadTheme.textTheme.muted,
                          ),
                        )
                      else
                        Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            ShadSelect<int>(
                              key: ValueKey(statusOptions.length),
                              initialValue: statusId,
                              enabled: !isSubmitting,
                              placeholder: const Text('결재 상태 선택'),
                              onChanged: (value) {
                                setState(() {
                                  statusId = value;
                                  statusError = null;
                                });
                              },
                              selectedOptionBuilder: (context, value) {
                                final selected = _controller.approvalStatusById(
                                  value,
                                );
                                return Text(selected?.name ?? '결재 상태 선택');
                              },
                              options: statusOptions
                                  .map(
                                    (item) => ShadOption<int>(
                                      value: item.id,
                                      child: Text(item.name),
                                    ),
                                  )
                                  .toList(),
                            ),
                            if (statusError != null)
                              Padding(
                                padding: const EdgeInsets.only(top: 6),
                                child: Text(
                                  statusError!,
                                  style: shadTheme.textTheme.small.copyWith(
                                    color: materialTheme.colorScheme.error,
                                  ),
                                ),
                              ),
                          ],
                        ),
                      const SizedBox(height: 16),
                      Text('상신자', style: shadTheme.textTheme.small),
                      const SizedBox(height: 8),
                      Row(
                        children: [
                          Expanded(
                            child: InventoryEmployeeAutocompleteField(
                              controller: requesterController,
                              initialSuggestion: requesterSelection,
                              onSuggestionSelected: (suggestion) {
                                setState(() {
                                  requesterSelection = suggestion;
                                  requesterError = null;
                                });
                              },
                              onChanged: () {
                                if (requesterController.text.trim().isEmpty) {
                                  setState(() {
                                    requesterSelection = null;
                                  });
                                }
                              },
                              enabled: !isSubmitting,
                              placeholder: '상신자 이름 또는 사번 검색',
                            ),
                          ),
                          const SizedBox(width: 8),
                          ShadButton.ghost(
                            onPressed:
                                requesterSelection == null &&
                                    requesterController.text.isEmpty
                                ? null
                                : () {
                                    setState(() {
                                      requesterSelection = null;
                                      requesterController.clear();
                                      requesterError = null;
                                    });
                                  },
                            child: const Text('초기화'),
                          ),
                        ],
                      ),
                      if (requesterError != null)
                        Padding(
                          padding: const EdgeInsets.only(top: 6),
                          child: Text(
                            requesterError!,
                            style: shadTheme.textTheme.small.copyWith(
                              color: materialTheme.colorScheme.error,
                            ),
                          ),
                        ),
                      const SizedBox(height: 16),
                      Text('비고 (선택)', style: shadTheme.textTheme.small),
                      const SizedBox(height: 8),
                      ShadTextarea(
                        key: const ValueKey('approval_create_note'),
                        controller: noteController,
                        enabled: !isSubmitting,
                        minHeight: 120,
                        maxHeight: 220,
                      ),
                      const SizedBox(height: 16),
                      Container(
                        padding: const EdgeInsets.all(12),
                        decoration: BoxDecoration(
                          color: shadTheme.colorScheme.mutedForeground
                              .withValues(alpha: 0.08),
                          borderRadius: BorderRadius.circular(12),
                        ),
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: const [
                            Text(
                              '저장 안내',
                              style: TextStyle(fontWeight: FontWeight.w600),
                            ),
                            SizedBox(height: 6),
                            Text(
                              '저장 시 결재가 생성되고 첫 단계와 현재 상태가 API 규격에 맞춰 초기화됩니다. 등록 후 목록이 자동으로 갱신됩니다.',
                            ),
                          ],
                        ),
                      ),
                    ],
                  ),
                );
              },
            );
          },
        );
      },
    );

    transactionController.dispose();
    requesterController.dispose();
    noteController.dispose();

    if (created == true && mounted) {
      final number = createdApprovalNo ?? '-';
      SuperportToast.success(context, '결재를 생성했습니다. ($number)');
    }
  }

  void _applyFilters() {
    final transactionText = _transactionController.text.trim();
    if (transactionText.isNotEmpty) {
      final transactionId = int.tryParse(transactionText);
      if (transactionId == null) {
        SuperportToast.error(context, '트랜잭션 ID는 숫자만 입력해야 합니다.');
        return;
      }
      _controller.updateTransactionFilter(transactionId);
    } else {
      _controller.updateTransactionFilter(null);
    }

    final requester = _selectedRequester;
    if (requester != null) {
      _controller.updateRequestedByFilter(
        id: requester.id,
        name: requester.name,
        employeeNo: requester.employeeNo,
      );
    } else if (_requesterController.text.trim().isEmpty) {
      _controller.updateRequestedByFilter(id: null);
    }

    _controller.fetch(page: 1);
  }

  void _resetFilters() {
    _transactionController.clear();
    _requesterController.clear();
    setState(() => _selectedRequester = null);
    _transactionFocus.requestFocus();
    _controller.clearFilters();
    _controller.fetch(page: 1);
  }

  bool _hasFilters() {
    return _transactionController.text.trim().isNotEmpty ||
        _requesterController.text.trim().isNotEmpty ||
        _selectedRequester != null ||
        _controller.transactionIdFilter != null ||
        _controller.requestedById != null ||
        _controller.statusFilter != ApprovalStatusFilter.all;
  }

  String _statusLabel(ApprovalStatusFilter filter) {
    return _controller.statusLabel(filter);
  }
}

class _ApprovalTable extends StatelessWidget {
  const _ApprovalTable({
    required this.approvals,
    required this.dateFormat,
    required this.onView,
  });

  final List<Approval> approvals;
  final intl.DateFormat dateFormat;
  final void Function(Approval approval) onView;

  @override
  Widget build(BuildContext context) {
    final header = [
      'ID',
      '결재번호',
      '트랜잭션번호',
      '상태',
      '상신자',
      '요청일시',
      '최종결정일시',
      '비고',
    ].map((text) => ShadTableCell.header(child: Text(text))).toList();

    final rows = <List<ShadTableCell>>[];
    for (var index = 0; index < approvals.length; index++) {
      final approval = approvals[index];
      final cells = <ShadTableCell>[
        ShadTableCell(
          child: GestureDetector(
            key: ValueKey('approval_row_${approval.id ?? index}'),
            behavior: HitTestBehavior.opaque,
            onTap: () => onView(approval),
            child: Text(approval.id?.toString() ?? '-'),
          ),
        ),
        ShadTableCell(child: Text(approval.approvalNo)),
        ShadTableCell(child: Text(approval.transactionNo)),
        ShadTableCell(child: Text(approval.status.name)),
        ShadTableCell(child: Text(approval.requester.name)),
        ShadTableCell(
          child: Text(dateFormat.format(approval.requestedAt.toLocal())),
        ),
        ShadTableCell(
          child: Text(
            approval.decidedAt == null
                ? '-'
                : dateFormat.format(approval.decidedAt!.toLocal()),
          ),
        ),
        ShadTableCell(
          child: Text(approval.note?.isEmpty ?? true ? '-' : approval.note!),
        ),
      ];

      rows.add(cells);
    }

    return SuperportTable.fromCells(
      header: header,
      rows: rows,
      rowHeight: 56,
      maxHeight: 520,
      onRowTap: (index) {
        if (index < 0 || index >= approvals.length) {
          return;
        }
        onView(approvals[index]);
      },
      columnSpanExtent: (index) {
        switch (index) {
          case 1:
          case 2:
            return const FixedTableSpanExtent(180);
          case 3:
          case 4:
            return const FixedTableSpanExtent(140);
          case 7:
            return const FixedTableSpanExtent(220);
          default:
            return const FixedTableSpanExtent(140);
        }
      },
    );
  }
}
