import 'package:flutter/material.dart';
import 'package:get_it/get_it.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/filter_bar.dart';
import '../../../../../widgets/components/superport_dialog.dart';
import '../../../../../widgets/components/superport_pagination_controls.dart';
import '../../../../../widgets/components/superport_table.dart';
import '../../../../../widgets/components/feature_disabled_placeholder.dart';
import '../controllers/approval_step_controller.dart';
import '../dialogs/approval_step_detail_dialog.dart';
import '../../domain/entities/approval_step_input.dart';
import '../../domain/entities/approval_step_record.dart';
import '../../domain/repositories/approval_step_repository.dart';

const String _stepResourcePath = PermissionResources.approvalSteps;

/// 결재 단계 관리 진입 페이지. 기능 플래그에 따라 실제 화면 또는 준비중 화면을 노출한다.
class ApprovalStepPage extends StatelessWidget {
  const ApprovalStepPage({super.key});

  @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/steps'),
          AppBreadcrumbItem(label: '결재 단계'),
        ],
        actions: [
          Tooltip(
            message: 'API 연동 이후 단계 추가가 가능합니다.',
            child: ShadButton(
              onPressed: null,
              leading: const Icon(lucide.LucideIcons.plus, size: 16),
              child: const Text('단계 추가'),
            ),
          ),
        ],
        child: const FeatureDisabledPlaceholder(
          title: '결재 단계 기능 준비 중',
          description: '결재 단계 API 연동을 기다리는 중입니다. 연동 후 단계 생성/수정/삭제 기능이 활성화됩니다.',
        ),
      );
    }

    return const _ApprovalStepEnabledPage();
  }
}

/// 결재 단계 기능이 활성화된 경우 사용하는 실제 화면 위젯.
class _ApprovalStepEnabledPage extends StatefulWidget {
  const _ApprovalStepEnabledPage();

  @override
  State<_ApprovalStepEnabledPage> createState() =>
      _ApprovalStepEnabledPageState();
}

/// 결재 단계 목록과 필터 상태를 관리하는 상태 클래스.
class _ApprovalStepEnabledPageState extends State<_ApprovalStepEnabledPage> {
  late final ApprovalStepController _controller;
  final TextEditingController _searchController = TextEditingController();
  final FocusNode _searchFocus = FocusNode();
  final intl.DateFormat _dateFormat = intl.DateFormat('yyyy-MM-dd HH:mm');
  String? _lastError;

  @override
  void initState() {
    super.initState();
    _controller = ApprovalStepController(
      repository: GetIt.I<ApprovalStepRepository>(),
    )..addListener(_handleControllerUpdate);
    WidgetsBinding.instance.addPostFrameCallback((_) async {
      await _controller.fetch();
    });
  }

  void _handleControllerUpdate() {
    final error = _controller.errorMessage;
    if (error != null && error != _lastError && mounted) {
      _lastError = error;
      final messenger = ScaffoldMessenger.maybeOf(context);
      if (messenger != null) {
        messenger.showSnackBar(SnackBar(content: Text(error)));
      }
      _controller.clearError();
    }
  }

  @override
  void dispose() {
    _controller.removeListener(_handleControllerUpdate);
    _controller.dispose();
    _searchController.dispose();
    _searchFocus.dispose();
    super.dispose();
  }

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

    return AnimatedBuilder(
      animation: _controller,
      builder: (context, _) {
        final result = _controller.result;
        final records = result?.items ?? const <ApprovalStepRecord>[];
        final totalCount = result?.total ?? 0;
        final currentPage = result?.page ?? 1;
        final pageSize = result?.pageSize ?? records.length;
        final totalPages = pageSize == 0
            ? 1
            : (totalCount / pageSize).ceil().clamp(1, 9999);
        final statusOptions = _buildStatusOptions(records);
        final selectedStatus = _controller.statusId ?? -1;
        final approverOptions = _buildApproverOptions(records);
        final selectedApprover = _controller.approverId ?? -1;
        final isSaving = _controller.isSaving;

        return AppLayout(
          title: '결재 단계 관리',
          subtitle: '결재 요청별 단계 현황을 조회하고 상세 정보를 확인합니다.',
          breadcrumbs: const [
            AppBreadcrumbItem(label: '대시보드', path: dashboardRoutePath),
            AppBreadcrumbItem(label: '결재', path: '/approvals/steps'),
            AppBreadcrumbItem(label: '결재 단계'),
          ],
          actions: [
            PermissionGate(
              resource: _stepResourcePath,
              action: PermissionAction.create,
              child: ShadButton(
                key: const ValueKey('approval_step_create'),
                onPressed: (_controller.isLoading || isSaving)
                    ? null
                    : _openCreateStepForm,
                leading: isSaving
                    ? const SizedBox(
                        width: 16,
                        height: 16,
                        child: CircularProgressIndicator(strokeWidth: 2),
                      )
                    : const Icon(lucide.LucideIcons.plus, size: 16),
                child: Text(isSaving ? '저장 중...' : '단계 추가'),
              ),
            ),
          ],
          toolbar: FilterBar(
            children: [
              SizedBox(
                width: 260,
                child: ShadInput(
                  controller: _searchController,
                  focusNode: _searchFocus,
                  placeholder: const Text('결재번호, 승인자 검색'),
                  leading: const Icon(lucide.LucideIcons.search, size: 16),
                  onSubmitted: (_) => _applyFilters(),
                ),
              ),
              if (statusOptions.length > 1)
                SizedBox(
                  width: 200,
                  child: ShadSelect<int>(
                    key: ValueKey(selectedStatus),
                    initialValue: selectedStatus,
                    onChanged: (value) {
                      _controller.updateStatusId(value == -1 ? null : value);
                    },
                    selectedOptionBuilder: (context, value) {
                      final option = statusOptions.firstWhere(
                        (element) => element.id == value,
                        orElse: () => _StatusOption(id: -1, name: '전체'),
                      );
                      return Text(option.name);
                    },
                    options: statusOptions
                        .map(
                          (opt) => ShadOption<int>(
                            value: opt.id,
                            child: Text(opt.name),
                          ),
                        )
                        .toList(),
                  ),
                ),
              if (approverOptions.length > 1)
                SizedBox(
                  width: 220,
                  child: ShadSelect<int>(
                    key: ValueKey(selectedApprover),
                    initialValue: selectedApprover,
                    onChanged: (value) {
                      _controller.updateApproverId(value == -1 ? null : value);
                    },
                    selectedOptionBuilder: (context, value) {
                      final option = approverOptions.firstWhere(
                        (element) => element.id == value,
                        orElse: () => const _ApproverOption(id: -1, name: '전체'),
                      );
                      return Text(option.name);
                    },
                    options: approverOptions
                        .map(
                          (opt) => ShadOption<int>(
                            value: opt.id,
                            child: Text(opt.name),
                          ),
                        )
                        .toList(),
                  ),
                ),
              ShadButton.outline(
                onPressed: (_controller.isLoading || isSaving)
                    ? null
                    : _applyFilters,
                child: const Text('검색 적용'),
              ),
              ShadButton.ghost(
                onPressed:
                    !_controller.isLoading &&
                        !isSaving &&
                        _controller.hasActiveFilters
                    ? _resetFilters
                    : null,
                child: const Text('필터 초기화'),
              ),
            ],
          ),
          child: ShadCard(
            child: _controller.isLoading
                ? const Padding(
                    padding: EdgeInsets.all(48),
                    child: Center(child: CircularProgressIndicator()),
                  )
                : records.isEmpty
                ? Padding(
                    padding: const EdgeInsets.all(32),
                    child: Text(
                      '조회된 결재 단계가 없습니다.',
                      style: theme.textTheme.muted,
                    ),
                  )
                : Column(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      SuperportTable(
                        columns: const [
                          Text('ID'),
                          Text('결재번호'),
                          Text('단계순서'),
                          Text('승인자'),
                          Text('상태'),
                          Text('배정일시'),
                          Text('결정일시'),
                        ],
                        rows: records.map((record) {
                          final step = record.step;
                          final isDeleted = step.isDeleted;
                          final decidedAt = step.decidedAt;
                          return [
                            Text(step.id?.toString() ?? '-'),
                            Text(record.approvalNo),
                            Text('${step.stepOrder}'),
                            Text(step.approver.name),
                            Row(
                              children: [
                                ShadBadge(child: Text(step.status.name)),
                                if (isDeleted) ...[
                                  const SizedBox(width: 8),
                                  const ShadBadge.destructive(
                                    child: Text('삭제됨'),
                                  ),
                                ],
                              ],
                            ),
                            Text(_formatDate(step.assignedAt)),
                            Text(
                              decidedAt == null ? '-' : _formatDate(decidedAt),
                            ),
                          ];
                        }).toList(),
                        rowHeight: 56,
                        maxHeight: 520,
                        columnSpanExtent: (index) {
                          switch (index) {
                            case 1:
                              return const FixedTableSpanExtent(160);
                            case 2:
                              return const FixedTableSpanExtent(100);
                            case 3:
                              return const FixedTableSpanExtent(150);
                            case 4:
                              return const FixedTableSpanExtent(200);
                            case 5:
                            case 6:
                              return const FixedTableSpanExtent(160);
                            default:
                              return const FixedTableSpanExtent(90);
                          }
                        },
                        onRowTap: (_controller.isLoading || isSaving)
                            ? null
                            : (index) {
                                if (records.isEmpty) {
                                  return;
                                }
                                final int safeIndex;
                                if (index < 0) {
                                  safeIndex = 0;
                                } else if (index >= records.length) {
                                  safeIndex = records.length - 1;
                                } else {
                                  safeIndex = index;
                                }
                                _openDetail(records[safeIndex]);
                              },
                      ),
                      const SizedBox(height: 16),
                      Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [
                          Text('총 $totalCount건', style: theme.textTheme.small),
                          Row(
                            children: [
                              SuperportPaginationControls(
                                currentPage: currentPage,
                                totalPages: totalPages,
                                isBusy: _controller.isLoading || isSaving,
                                onPageSelected: (page) =>
                                    _controller.fetch(page: page),
                              ),
                              const SizedBox(width: 12),
                              Text(
                                '페이지 $currentPage / $totalPages',
                                style: theme.textTheme.small,
                              ),
                            ],
                          ),
                        ],
                      ),
                    ],
                  ),
          ),
        );
      },
    );
  }

  List<_StatusOption> _buildStatusOptions(List<ApprovalStepRecord> records) {
    final options = <_StatusOption>{};
    options.add(const _StatusOption(id: -1, name: '전체'));
    for (final record in records) {
      final status = record.step.status;
      options.add(_StatusOption(id: status.id, name: status.name));
    }
    return options.toList()..sort((a, b) => a.id.compareTo(b.id));
  }

  List<_ApproverOption> _buildApproverOptions(
    List<ApprovalStepRecord> records,
  ) {
    final options = <_ApproverOption>{};
    options.add(const _ApproverOption(id: -1, name: '전체'));
    for (final record in records) {
      final approver = record.step.approver;
      options.add(_ApproverOption(id: approver.id, name: approver.name));
    }
    return options.toList()..sort((a, b) => a.name.compareTo(b.name));
  }

  Future<void> _applyFilters() async {
    _controller.updateQuery(_searchController.text.trim());
    await _controller.fetch(page: 1);
  }

  Future<void> _resetFilters() async {
    _searchController.clear();
    _controller.resetFilters();
    await _controller.fetch(page: 1);
    _searchFocus.requestFocus();
  }

  Future<void> _openCreateStepForm() async {
    final input = await showDialog<ApprovalStepInput>(
      context: context,
      builder: (dialogContext) {
        return _StepFormDialog(title: '결재 단계 추가', submitLabel: '저장');
      },
    );

    if (!mounted || input == null) {
      return;
    }

    final created = await _controller.createStep(input);
    if (!mounted || created == null) {
      return;
    }

    final messenger = ScaffoldMessenger.maybeOf(context);
    messenger?.showSnackBar(
      SnackBar(content: Text('결재번호 ${created.approvalNo} 단계가 추가되었습니다.')),
    );
  }

  Future<void> _openDetail(ApprovalStepRecord record) async {
    final stepId = record.step.id;
    if (stepId == null) {
      final messenger = ScaffoldMessenger.maybeOf(context);
      messenger?.showSnackBar(
        const SnackBar(content: Text('단계 식별자가 없어 상세 정보를 볼 수 없습니다.')),
      );
      return;
    }
    showDialog<void>(
      context: context,
      barrierDismissible: false,
      builder: (_) => const Center(child: CircularProgressIndicator()),
    );
    final detail = await _controller.fetchDetail(stepId);
    if (!mounted) return;
    Navigator.of(context, rootNavigator: true).pop();
    if (detail == null) {
      final error = _controller.errorMessage;
      if (error != null) {
        final messenger = ScaffoldMessenger.maybeOf(context);
        messenger?.showSnackBar(SnackBar(content: Text(error)));
        _controller.clearError();
      }
      return;
    }
    final permissionManager = PermissionScope.of(context);
    final canEdit = permissionManager.can(
      _stepResourcePath,
      PermissionAction.edit,
    );
    final canDelete = permissionManager.can(
      _stepResourcePath,
      PermissionAction.delete,
    );
    final canRestore = permissionManager.can(
      _stepResourcePath,
      PermissionAction.restore,
    );
    final result = await showApprovalStepDetailDialog(
      context: context,
      record: detail,
      dateFormat: _dateFormat,
      onUpdate: (id, input) => _controller.updateStep(id, input),
      onDelete: (id) => _controller.deleteStep(id),
      onRestore: (id) => _controller.restoreStep(id),
      canEdit: canEdit,
      canDelete: canDelete,
      canRestore: canRestore,
    );
    if (!mounted || result == null) {
      return;
    }
    final messenger = ScaffoldMessenger.maybeOf(context);
    messenger?.showSnackBar(SnackBar(content: Text(result.message)));
  }

  String _formatDate(DateTime date) {
    return _dateFormat.format(date.toLocal());
  }
}

class _StatusOption {
  const _StatusOption({required this.id, required this.name});

  final int id;
  final String name;

  @override
  bool operator ==(Object other) {
    return other is _StatusOption && other.id == id;
  }

  @override
  int get hashCode => id.hashCode;
}

class _ApproverOption {
  const _ApproverOption({required this.id, required this.name});

  final int id;
  final String name;

  @override
  bool operator ==(Object other) {
    return other is _ApproverOption && other.id == id;
  }

  @override
  int get hashCode => id.hashCode;
}

class _StepFormDialog extends StatefulWidget {
  const _StepFormDialog({required this.title, required this.submitLabel});

  final String title;
  final String submitLabel;

  @override
  State<_StepFormDialog> createState() => _StepFormDialogState();
}

class _StepFormDialogState extends State<_StepFormDialog> {
  late final TextEditingController _approvalIdController;
  late final TextEditingController _stepOrderController;
  late final TextEditingController _approverIdController;
  late final TextEditingController _noteController;
  Map<String, String?> _errors = const {};

  @override
  void initState() {
    super.initState();
    _approvalIdController = TextEditingController();
    _stepOrderController = TextEditingController();
    _approverIdController = TextEditingController();
    _noteController = TextEditingController();
  }

  @override
  void dispose() {
    _approvalIdController.dispose();
    _stepOrderController.dispose();
    _approverIdController.dispose();
    _noteController.dispose();
    super.dispose();
  }

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

    return SuperportDialog(
      title: widget.title,
      constraints: const BoxConstraints(maxWidth: 560),
      primaryAction: ShadButton(
        key: const ValueKey('step_form_submit'),
        onPressed: _handleSubmit,
        child: Text(widget.submitLabel),
      ),
      secondaryAction: ShadButton.ghost(
        onPressed: () => Navigator.of(context, rootNavigator: true).pop(),
        child: const Text('취소'),
      ),
      contentPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
      child: SingleChildScrollView(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          mainAxisSize: MainAxisSize.min,
          children: [
            _FormFieldBlock(
              label: '결재 ID',
              errorText: _errors['approvalId'],
              child: ShadInput(
                key: const ValueKey('step_form_approval_id'),
                controller: _approvalIdController,
                onChanged: (_) => _clearError('approvalId'),
              ),
            ),
            const SizedBox(height: 16),
            _FormFieldBlock(
              label: '단계 순서',
              errorText: _errors['stepOrder'],
              child: ShadInput(
                key: const ValueKey('step_form_step_order'),
                controller: _stepOrderController,
                onChanged: (_) => _clearError('stepOrder'),
              ),
            ),
            const SizedBox(height: 16),
            _FormFieldBlock(
              label: '승인자 ID',
              errorText: _errors['approverId'],
              child: ShadInput(
                key: const ValueKey('step_form_approver_id'),
                controller: _approverIdController,
                onChanged: (_) => _clearError('approverId'),
              ),
            ),
            const SizedBox(height: 16),
            _FormFieldBlock(
              label: '비고',
              helperText: '필요 시 단계에 대한 참고 내용을 남길 수 있습니다.',
              child: ShadTextarea(
                key: const ValueKey('step_form_note'),
                controller: _noteController,
                minHeight: 100,
                maxHeight: 200,
              ),
            ),
            if (_errors['form'] != null)
              Padding(
                padding: const EdgeInsets.only(top: 12),
                child: Text(
                  _errors['form']!,
                  style: theme.textTheme.small.copyWith(
                    color: materialTheme.colorScheme.error,
                  ),
                ),
              ),
          ],
        ),
      ),
    );
  }

  void _handleSubmit() {
    final Map<String, String?> nextErrors = {};
    final approvalId = int.tryParse(_approvalIdController.text.trim());
    if (approvalId == null || approvalId <= 0) {
      nextErrors['approvalId'] = '결재 ID를 1 이상의 숫자로 입력하세요.';
    }

    final stepOrder = int.tryParse(_stepOrderController.text.trim());
    if (stepOrder == null || stepOrder <= 0) {
      nextErrors['stepOrder'] = '단계 순서를 1 이상의 숫자로 입력하세요.';
    }

    final approverId = int.tryParse(_approverIdController.text.trim());
    if (approverId == null || approverId <= 0) {
      nextErrors['approverId'] = '승인자 ID를 1 이상의 숫자로 입력하세요.';
    }

    setState(() => _errors = nextErrors);
    if (nextErrors.isNotEmpty) {
      return;
    }

    final note = _noteController.text.trim();
    final input = ApprovalStepInput(
      approvalId: approvalId,
      stepOrder: stepOrder!,
      approverId: approverId!,
      note: note.isEmpty ? null : note,
    );

    Navigator.of(context, rootNavigator: true).pop(input);
  }

  void _clearError(String field) {
    if (_errors[field] == null) {
      return;
    }
    setState(() {
      final updated = Map<String, String?>.from(_errors);
      updated.remove(field);
      _errors = updated;
    });
  }
}

class _FormFieldBlock extends StatelessWidget {
  const _FormFieldBlock({
    required this.label,
    this.errorText,
    this.helperText,
    required this.child,
  });

  final String label;
  final Widget child;
  final String? errorText;
  final String? helperText;

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

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          label,
          style: theme.textTheme.small.copyWith(fontWeight: FontWeight.w600),
        ),
        const SizedBox(height: 8),
        child,
        if (errorText != null)
          Padding(
            padding: const EdgeInsets.only(top: 6),
            child: Text(
              errorText!,
              style: theme.textTheme.small.copyWith(
                color: materialTheme.colorScheme.error,
              ),
            ),
          ),
        if (helperText != null && helperText!.isNotEmpty)
          Padding(
            padding: const EdgeInsets.only(top: 6),
            child: Text(helperText!, style: theme.textTheme.muted),
          ),
      ],
    );
  }
}
