import 'package:flutter/foundation.dart';
import 'package:superport_v2/core/network/failure.dart';
import 'package:superport_v2/core/common/models/paginated_result.dart';
import 'package:superport_v2/core/common/utils/pagination_utils.dart';

import '../../../../../core/permissions/permission_manager.dart';
import '../../../group/domain/entities/group.dart';
import '../../../group/domain/repositories/group_repository.dart';
import '../../../group_permission/application/permission_synchronizer.dart';
import '../../../group_permission/domain/repositories/group_permission_repository.dart';
import '../../domain/entities/user.dart';
import '../../domain/repositories/user_repository.dart';

/// 사용자 활성 여부 필터.
enum UserStatusFilter { all, activeOnly, inactiveOnly }

/// 사용자 마스터 화면 상태를 관리하는 컨트롤러.
class UserController extends ChangeNotifier {
  UserController({
    required UserRepository userRepository,
    required GroupRepository groupRepository,
    GroupPermissionRepository? permissionRepository,
    PermissionManager? permissionManager,
  }) : _userRepository = userRepository,
       _groupRepository = groupRepository,
       _permissionRepository = permissionRepository,
       _permissionManager = permissionManager;

  final UserRepository _userRepository;
  final GroupRepository _groupRepository;
  final GroupPermissionRepository? _permissionRepository;
  final PermissionManager? _permissionManager;

  PaginatedResult<UserAccount>? _result;
  bool _isLoading = false;
  bool _isSubmitting = false;
  bool _isLoadingGroups = false;
  String _query = '';
  int? _groupFilter;
  UserStatusFilter _statusFilter = UserStatusFilter.all;
  String? _errorMessage;
  List<Group> _groups = const [];

  PaginatedResult<UserAccount>? get result => _result;
  bool get isLoading => _isLoading;
  bool get isSubmitting => _isSubmitting;
  bool get isLoadingGroups => _isLoadingGroups;
  String get query => _query;
  int? get groupFilter => _groupFilter;
  UserStatusFilter get statusFilter => _statusFilter;
  String? get errorMessage => _errorMessage;
  List<Group> get groups => _groups;

  /// 권한 그룹 목록을 로드한다.
  Future<void> loadGroups() async {
    _isLoadingGroups = true;
    notifyListeners();
    try {
      final groups = await fetchAllPaginatedItems<Group>(
        request: (page, pageSize) =>
            _groupRepository.list(page: page, pageSize: pageSize),
      );
      _groups = groups;
    } catch (error) {
      final failure = Failure.from(error);
      _errorMessage = failure.describe();
    } finally {
      _isLoadingGroups = false;
      notifyListeners();
    }
  }

  /// 사용자 목록을 조회한다.
  Future<void> fetch({int page = 1}) async {
    _isLoading = true;
    _errorMessage = null;
    notifyListeners();
    try {
      final previous = _result;
      final int resolvedPage;
      if (page < 1) {
        resolvedPage = 1;
      } else if (previous != null && previous.pageSize > 0) {
        final calculated = (previous.total / previous.pageSize).ceil();
        final maxPage = calculated < 1 ? 1 : calculated;
        resolvedPage = page > maxPage ? maxPage : page;
      } else {
        resolvedPage = page;
      }
      final isActive = switch (_statusFilter) {
        UserStatusFilter.all => null,
        UserStatusFilter.activeOnly => true,
        UserStatusFilter.inactiveOnly => false,
      };
      final response = await _userRepository.list(
        page: resolvedPage,
        pageSize: _result?.pageSize ?? 20,
        query: _query.isEmpty ? null : _query,
        groupId: _groupFilter,
        isActive: isActive,
      );
      _result = response;
    } catch (error) {
      final failure = Failure.from(error);
      _errorMessage = failure.describe();
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }

  /// 검색어를 변경한다.
  void updateQuery(String value) {
    _query = value;
    notifyListeners();
  }

  /// 그룹 필터를 변경한다.
  void updateGroupFilter(int? groupId) {
    _groupFilter = groupId;
    notifyListeners();
  }

  /// 사용자 상태 필터를 변경한다.
  void updateStatusFilter(UserStatusFilter filter) {
    _statusFilter = filter;
    notifyListeners();
  }

  /// 사용자를 생성한다.
  Future<UserAccount?> create(UserInput input) async {
    _setSubmitting(true);
    try {
      final created = await _userRepository.create(input);
      await fetch(page: 1);
      await _syncPermissions(input.groupId);
      return created;
    } catch (error) {
      final failure = Failure.from(error);
      _errorMessage = failure.describe();
      notifyListeners();
      return null;
    } finally {
      _setSubmitting(false);
    }
  }

  /// 사용자 정보를 수정한다.
  Future<UserAccount?> update(int id, UserInput input) async {
    _setSubmitting(true);
    try {
      final updated = await _userRepository.update(id, input);
      await fetch(page: _result?.page ?? 1);
      await _syncPermissions(input.groupId);
      return updated;
    } catch (error) {
      final failure = Failure.from(error);
      _errorMessage = failure.describe();
      notifyListeners();
      return null;
    } finally {
      _setSubmitting(false);
    }
  }

  /// 관리자가 사용자의 비밀번호를 재설정한다.
  Future<UserAccount?> resetPassword(int id) async {
    _setSubmitting(true);
    try {
      final updated = await _userRepository.resetPassword(id);
      await fetch(page: _result?.page ?? 1);
      return updated;
    } catch (error) {
      final failure = Failure.from(error);
      _errorMessage = failure.describe();
      notifyListeners();
      return null;
    } finally {
      _setSubmitting(false);
    }
  }

  /// 사용자를 삭제한다.
  Future<bool> delete(int id) async {
    _setSubmitting(true);
    try {
      final groupId = _resolveGroupId(id);
      await _userRepository.delete(id);
      await fetch(page: _result?.page ?? 1);
      if (groupId != null) {
        await _syncPermissions(groupId);
      }
      return true;
    } catch (error) {
      final failure = Failure.from(error);
      _errorMessage = failure.describe();
      notifyListeners();
      return false;
    } finally {
      _setSubmitting(false);
    }
  }

  /// 삭제된 사용자를 복구한다.
  Future<UserAccount?> restore(int id) async {
    _setSubmitting(true);
    try {
      final restored = await _userRepository.restore(id);
      await fetch(page: _result?.page ?? 1);
      final groupId = restored.group?.id;
      if (groupId != null) {
        await _syncPermissions(groupId);
      }
      return restored;
    } catch (error) {
      final failure = Failure.from(error);
      _errorMessage = failure.describe();
      notifyListeners();
      return null;
    } finally {
      _setSubmitting(false);
    }
  }

  /// 에러 메시지를 초기화한다.
  void clearError() {
    _errorMessage = null;
    notifyListeners();
  }

  /// 제출 상태 플래그를 갱신하고 리스너에게 알린다.
  void _setSubmitting(bool value) {
    _isSubmitting = value;
    notifyListeners();
  }

  Future<void> _syncPermissions(int groupId) async {
    final manager = _permissionManager;
    final repository = _permissionRepository;
    if (manager == null || repository == null) {
      return;
    }
    try {
      final synchronizer = PermissionSynchronizer(
        repository: repository,
        manager: manager,
      );
      await synchronizer.syncForGroup(groupId);
    } catch (_) {
      // 권한 동기화 실패는 무시하고 기존 흐름을 유지한다.
    }
  }

  int? _resolveGroupId(int userId) {
    final items = _result?.items;
    if (items == null) {
      return null;
    }
    for (final user in items) {
      if (user.id == userId) {
        return user.group?.id;
      }
    }
    return null;
  }
}
