import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:intl/intl.dart' as intl;
import 'package:shadcn_ui/shadcn_ui.dart';

import 'package:superport_v2/core/constants/app_sections.dart';
import 'package:superport_v2/widgets/app_layout.dart';
import 'package:superport_v2/widgets/components/filter_bar.dart';
import 'package:superport_v2/widgets/components/superport_pagination_controls.dart';
import 'package:superport_v2/widgets/components/superport_table.dart';

import '../../../../../core/config/environment.dart';
import '../../../../../core/permissions/permission_manager.dart';
import '../../../../../widgets/spec_page.dart';
import '../../../group/domain/entities/group.dart';
import '../../../group/domain/repositories/group_repository.dart';
import '../../../menu/domain/entities/menu.dart';
import '../../../menu/domain/repositories/menu_repository.dart';
import '../../domain/entities/group_permission.dart';
import '../../domain/repositories/group_permission_repository.dart';
import '../controllers/group_permission_controller.dart';
import '../dialogs/group_permission_detail_dialog.dart';

String _menuDisplayLabelFromPath(String? path, String fallback) {
  if (path != null && path.isNotEmpty) {
    final normalized = path.toLowerCase();
    for (final page in allAppPages) {
      if (page.path.toLowerCase() == normalized) {
        return page.label;
      }
    }
  }
  return fallback;
}

/// 그룹-메뉴 권한 설정 페이지. 기능 플래그에 따라 사양/실제 화면을 전환한다.
class GroupPermissionPage extends StatelessWidget {
  const GroupPermissionPage({super.key});

  @override
  Widget build(BuildContext context) {
    final enabled = Environment.flag('FEATURE_GROUP_PERMISSIONS_ENABLED');
    if (!enabled) {
      return SpecPage(
        title: '그룹 권한 관리',
        summary: '그룹과 메뉴별 CRUD 권한을 확인하고 수정합니다.',
        trailing: ShadBadge(
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
            child: Row(
              mainAxisSize: MainAxisSize.min,
              children: const [
                Icon(LucideIcons.info, size: 14),
                SizedBox(width: 6),
                Text('비활성화 (백엔드 준비 중)'),
              ],
            ),
          ),
        ),
        sections: const [
          SpecSection(
            title: '입력 폼',
            items: [
              '그룹 [Dropdown]',
              '메뉴 [Dropdown]',
              '생성권한 [Checkbox]',
              '조회권한 [Checkbox]',
              '수정권한 [Checkbox]',
              '삭제권한 [Checkbox]',
              '사용여부 [Switch]',
              '비고 [Text]',
            ],
          ),
          SpecSection(
            title: '수정 폼',
            items: ['그룹 [ReadOnly]', '메뉴 [ReadOnly]', '생성일시 [ReadOnly]'],
          ),
          SpecSection(
            title: '테이블 리스트',
            description: '1행 예시',
            table: SpecTable(
              columns: [
                '번호',
                '그룹명',
                '메뉴명',
                '생성',
                '조회',
                '수정',
                '삭제',
                '사용여부',
                '비고',
                '변경일시',
              ],
              rows: [
                [
                  '1',
                  '관리자',
                  '대시보드',
                  'Y',
                  'Y',
                  'Y',
                  'Y',
                  'Y',
                  '-',
                  '2024-03-01 10:00',
                ],
              ],
            ),
          ),
        ],
      );
    }

    return const _GroupPermissionEnabledPage();
  }
}

/// 그룹 권한 기능이 활성화된 경우 사용하는 실제 화면 위젯.
class _GroupPermissionEnabledPage extends StatefulWidget {
  const _GroupPermissionEnabledPage();

  @override
  State<_GroupPermissionEnabledPage> createState() =>
      _GroupPermissionEnabledPageState();
}

/// 그룹 권한 목록/필터/폼 상태를 관리하는 상태 클래스.
class _GroupPermissionEnabledPageState
    extends State<_GroupPermissionEnabledPage> {
  late final GroupPermissionController _controller;
  final TextEditingController _searchController = TextEditingController();
  final FocusNode _searchFocus = FocusNode();
  final intl.DateFormat _dateFormat = intl.DateFormat('yyyy-MM-dd HH:mm');
  String? _lastError;

  bool _initialized = false;

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

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    if (_initialized) {
      return;
    }
    final permissionManager = PermissionScope.of(context);
    _controller = GroupPermissionController(
      permissionRepository: GetIt.I<GroupPermissionRepository>(),
      groupRepository: GetIt.I<GroupRepository>(),
      menuRepository: GetIt.I<MenuRepository>(),
      permissionManager: permissionManager,
    )..addListener(_handleControllerUpdate);
    _initialized = true;
    WidgetsBinding.instance.addPostFrameCallback((_) async {
      await _controller.loadGroups();
      await _controller.loadMenus();
      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 permissions = result?.items ?? const <GroupPermission>[];
        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);

        final showReset =
            _searchController.text.isNotEmpty ||
            _controller.groupFilter != null ||
            _controller.menuFilter != null ||
            _controller.statusFilter != GroupPermissionStatusFilter.all ||
            _controller.includeDeleted;

        return AppLayout(
          title: '그룹 권한 관리',
          subtitle: '그룹별 메뉴 CRUD 권한을 체크박스로 관리합니다.',
          breadcrumbs: const [
            AppBreadcrumbItem(label: '대시보드', path: dashboardRoutePath),
            AppBreadcrumbItem(label: '마스터', path: '/masters/group-permissions'),
            AppBreadcrumbItem(label: '그룹 권한'),
          ],
          actions: [
            ShadButton(
              leading: const Icon(LucideIcons.plus, size: 16),
              onPressed: _controller.isSubmitting
                  ? null
                  : _openPermissionCreateDialog,
              child: const Text('신규 등록'),
            ),
          ],
          toolbar: FilterBar(
            actions: [
              ShadButton.outline(
                onPressed: _controller.isLoading ? null : _applyFilters,
                child: const Text('검색 적용'),
              ),
              if (showReset)
                ShadButton.ghost(
                  onPressed: _controller.isLoading
                      ? null
                      : () {
                          _searchController.clear();
                          _searchFocus.requestFocus();
                          _controller.updateGroupFilter(null);
                          _controller.updateMenuFilter(null);
                          _controller.updateIncludeDeleted(false);
                          _controller.updateStatusFilter(
                            GroupPermissionStatusFilter.all,
                          );
                          _controller.fetch(page: 1);
                        },
                  child: const Text('초기화'),
                ),
            ],
            children: [
              SizedBox(
                width: 260,
                child: ShadInput(
                  controller: _searchController,
                  focusNode: _searchFocus,
                  placeholder: const Text('그룹/메뉴/비고 검색'),
                  leading: const Icon(LucideIcons.search, size: 16),
                  onSubmitted: (_) => _applyFilters(),
                ),
              ),
              SizedBox(
                width: 220,
                child: ShadSelect<int?>(
                  key: ValueKey(_controller.groupFilter),
                  initialValue: _controller.groupFilter,
                  placeholder: Text(
                    _controller.groups.isEmpty ? '그룹 로딩중...' : '그룹 전체',
                  ),
                  selectedOptionBuilder: (context, value) {
                    if (value == null) {
                      return Text(
                        _controller.groups.isEmpty ? '그룹 로딩중...' : '그룹 전체',
                      );
                    }
                    final group = _controller.groups.firstWhere(
                      (g) => g.id == value,
                      orElse: () => Group(id: value, groupName: ''),
                    );
                    return Text(group.groupName);
                  },
                  onChanged: (value) {
                    _controller.updateGroupFilter(value);
                  },
                  options: [
                    const ShadOption<int?>(value: null, child: Text('그룹 전체')),
                    ..._controller.groups.map(
                      (group) => ShadOption<int?>(
                        value: group.id,
                        child: Text(group.groupName),
                      ),
                    ),
                  ],
                ),
              ),
              SizedBox(
                width: 220,
                child: ShadSelect<int?>(
                  key: ValueKey(_controller.menuFilter),
                  initialValue: _controller.menuFilter,
                  placeholder: Text(
                    _controller.menus.isEmpty ? '메뉴 로딩중...' : '메뉴 전체',
                  ),
                  selectedOptionBuilder: (context, value) {
                    if (value == null) {
                      return Text(
                        _controller.menus.isEmpty ? '메뉴 로딩중...' : '메뉴 전체',
                      );
                    }
                    final menuItem = _controller.menus.firstWhere(
                      (m) => m.id == value,
                      orElse: () =>
                          MenuItem(id: value, menuCode: '', menuName: ''),
                    );
                    return Text(_menuDisplayLabel(menuItem));
                  },
                  onChanged: (value) {
                    _controller.updateMenuFilter(value);
                  },
                  options: [
                    const ShadOption<int?>(value: null, child: Text('메뉴 전체')),
                    ..._controller.menus.map(
                      (menuItem) => ShadOption<int?>(
                        value: menuItem.id,
                        child: Text(_menuDisplayLabel(menuItem)),
                      ),
                    ),
                  ],
                ),
              ),
              SizedBox(
                width: 200,
                child: ShadSelect<GroupPermissionStatusFilter>(
                  key: ValueKey(_controller.statusFilter),
                  initialValue: _controller.statusFilter,
                  selectedOptionBuilder: (context, filter) =>
                      Text(_statusLabel(filter)),
                  onChanged: (value) {
                    if (value == null) return;
                    _controller.updateStatusFilter(value);
                  },
                  options: GroupPermissionStatusFilter.values
                      .map(
                        (filter) => ShadOption(
                          value: filter,
                          child: Text(_statusLabel(filter)),
                        ),
                      )
                      .toList(),
                ),
              ),
              Row(
                mainAxisSize: MainAxisSize.min,
                children: [
                  ShadSwitch(
                    value: _controller.includeDeleted,
                    onChanged: (value) {
                      _controller.updateIncludeDeleted(value);
                    },
                  ),
                  const SizedBox(width: 8),
                  const Text('삭제 포함'),
                ],
              ),
            ],
          ),
          child: 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.isLoading,
                  onPageSelected: (page) => _controller.fetch(page: page),
                ),
              ],
            ),
            child: _controller.isLoading
                ? const Padding(
                    padding: EdgeInsets.all(48),
                    child: Center(child: CircularProgressIndicator()),
                  )
                : permissions.isEmpty
                ? Padding(
                    padding: const EdgeInsets.all(32),
                    child: Text(
                      '조건에 맞는 권한이 없습니다.',
                      style: theme.textTheme.muted,
                    ),
                  )
                : _PermissionTable(
                    permissions: permissions,
                    dateFormat: _dateFormat,
                    onRowTap: _controller.isSubmitting
                        ? null
                        : _openPermissionDetailDialog,
                  ),
          ),
        );
      },
    );
  }

  void _applyFilters() {
    _controller.fetch(page: 1);
  }

  String _statusLabel(GroupPermissionStatusFilter filter) {
    switch (filter) {
      case GroupPermissionStatusFilter.all:
        return '전체(사용/미사용)';
      case GroupPermissionStatusFilter.activeOnly:
        return '사용중';
      case GroupPermissionStatusFilter.inactiveOnly:
        return '미사용';
    }
  }

  String _menuDisplayLabel(MenuItem menu) {
    return _menuDisplayLabelFromPath(menu.path, menu.menuName);
  }

  Future<void> _openPermissionCreateDialog() async {
    final result = await showGroupPermissionDetailDialog(
      context: context,
      dateFormat: _dateFormat,
      groups: _controller.groups,
      isLoadingGroups: _controller.isLoadingGroups,
      menus: _controller.menus,
      isLoadingMenus: _controller.isLoadingMenus,
      onCreate: _controller.create,
      onUpdate: _controller.update,
      onDelete: _controller.delete,
      onRestore: _controller.restore,
    );
    if (result != null && mounted) {
      _showSnack(result.message);
    }
  }

  Future<void> _openPermissionDetailDialog(GroupPermission permission) async {
    final permissionId = permission.id;
    if (permissionId == null) {
      _showSnack('ID 정보가 없어 상세를 열 수 없습니다.');
      return;
    }
    final result = await showGroupPermissionDetailDialog(
      context: context,
      dateFormat: _dateFormat,
      permission: permission,
      groups: _controller.groups,
      isLoadingGroups: _controller.isLoadingGroups,
      menus: _controller.menus,
      isLoadingMenus: _controller.isLoadingMenus,
      onCreate: _controller.create,
      onUpdate: _controller.update,
      onDelete: _controller.delete,
      onRestore: _controller.restore,
    );
    if (result != null && mounted) {
      _showSnack(result.message);
    }
  }

  void _showSnack(String message) {
    if (!mounted) {
      return;
    }
    final messenger = ScaffoldMessenger.maybeOf(context);
    if (messenger == null) {
      return;
    }
    messenger.showSnackBar(SnackBar(content: Text(message)));
  }
}

class _PermissionTable extends StatelessWidget {
  const _PermissionTable({
    required this.permissions,
    required this.dateFormat,
    required this.onRowTap,
  });

  final List<GroupPermission> permissions;
  final intl.DateFormat dateFormat;
  final void Function(GroupPermission permission)? onRowTap;

  @override
  Widget build(BuildContext context) {
    final columns = const [
      Text('ID'),
      Text('그룹명'),
      Text('메뉴명'),
      Text('라우트 경로'),
      Text('생성'),
      Text('조회'),
      Text('수정'),
      Text('삭제'),
      Text('사용'),
      Text('삭제'),
      Text('비고'),
      Text('변경일시'),
    ];

    final rows = permissions
        .map(
          (permission) => <Widget>[
            Text(permission.id?.toString() ?? '-'),
            Text(permission.group.groupName),
            Text(
              _menuDisplayLabelFromPath(
                permission.menu.path,
                permission.menu.menuName,
              ),
            ),
            Text(permission.menu.path ?? '-'),
            Text(permission.canCreate ? 'Y' : '-'),
            Text(permission.canRead ? 'Y' : '-'),
            Text(permission.canUpdate ? 'Y' : '-'),
            Text(permission.canDelete ? 'Y' : '-'),
            Text(permission.isActive ? 'Y' : 'N'),
            Text(permission.isDeleted ? 'Y' : '-'),
            Text(permission.note?.isEmpty ?? true ? '-' : permission.note!),
            Text(
              permission.updatedAt == null
                  ? '-'
                  : dateFormat.format(permission.updatedAt!.toLocal()),
            ),
          ],
        )
        .toList();

    return SuperportTable(
      columns: columns,
      rows: rows,
      rowHeight: 56,
      maxHeight: 56.0 * (permissions.length + 1),
      onRowTap: onRowTap == null
          ? null
          : (index) {
              if (index < 0 || index >= permissions.length) {
                return;
              }
              onRowTap!(permissions[index]);
            },
      columnSpanExtent: (index) => switch (index) {
        1 => const FixedTableSpanExtent(180),
        2 => const FixedTableSpanExtent(200),
        3 => const FixedTableSpanExtent(220),
        10 => const FixedTableSpanExtent(220),
        11 => const FixedTableSpanExtent(200),
        _ => const FixedTableSpanExtent(110),
      },
    );
  }
}
