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 '../../domain/entities/menu.dart';
import '../../domain/repositories/menu_repository.dart';

/// 메뉴 사용 여부 필터.
enum MenuStatusFilter { all, activeOnly, inactiveOnly }

/// 메뉴 마스터 상태 컨트롤러
///
/// - 목록, 필터, 페이지 상태를 관리한다.
/// - CRUD 및 복구 요청을 처리한다.
class MenuController extends ChangeNotifier {
  MenuController({required MenuRepository repository})
    : _repository = repository;

  final MenuRepository _repository;

  PaginatedResult<MenuItem>? _result;
  bool _isLoading = false;
  bool _isSubmitting = false;
  bool _isLoadingParents = false;
  String _query = '';
  int? _parentFilter;
  MenuStatusFilter _statusFilter = MenuStatusFilter.all;
  bool _includeDeleted = false;
  String? _errorMessage;
  List<MenuItem> _parents = const [];

  PaginatedResult<MenuItem>? get result => _result;
  bool get isLoading => _isLoading;
  bool get isSubmitting => _isSubmitting;
  bool get isLoadingParents => _isLoadingParents;
  String get query => _query;
  int? get parentFilter => _parentFilter;
  MenuStatusFilter get statusFilter => _statusFilter;
  bool get includeDeleted => _includeDeleted;
  String? get errorMessage => _errorMessage;
  List<MenuItem> get parents => _parents;

  /// 상위 메뉴 목록을 로드해 드롭다운에 표시한다.
  Future<void> loadParents() async {
    _isLoadingParents = true;
    notifyListeners();
    try {
      final parents = await fetchAllPaginatedItems<MenuItem>(
        request: (page, pageSize) => _repository.list(
          page: page,
          pageSize: pageSize,
          includeDeleted: false,
        ),
      );
      _parents = parents;
    } catch (error) {
      final failure = Failure.from(error);
      _errorMessage = failure.describe();
    } finally {
      _isLoadingParents = 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) {
        MenuStatusFilter.all => null,
        MenuStatusFilter.activeOnly => true,
        MenuStatusFilter.inactiveOnly => false,
      };
      final response = await _repository.list(
        page: resolvedPage,
        pageSize: _result?.pageSize ?? 20,
        query: _query.isEmpty ? null : _query,
        parentId: _parentFilter,
        isActive: isActive,
        includeDeleted: _includeDeleted,
      );
      _result = response;
    } catch (error) {
      final failure = Failure.from(error);
      _errorMessage = failure.describe();
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }

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

  /// 상위 메뉴 필터를 변경한다.
  void updateParentFilter(int? parentId) {
    _parentFilter = parentId;
    notifyListeners();
  }

  /// 메뉴 사용 여부 필터를 변경한다.
  void updateStatusFilter(MenuStatusFilter filter) {
    _statusFilter = filter;
    notifyListeners();
  }

  /// 삭제 포함 여부를 변경한다.
  void updateIncludeDeleted(bool value) {
    _includeDeleted = value;
    notifyListeners();
  }

  /// 메뉴를 생성한다.
  Future<MenuItem?> create(MenuInput input) async {
    _setSubmitting(true);
    try {
      final created = await _repository.create(input);
      await fetch(page: 1);
      await loadParents();
      return created;
    } catch (error) {
      final failure = Failure.from(error);
      _errorMessage = failure.describe();
      notifyListeners();
      return null;
    } finally {
      _setSubmitting(false);
    }
  }

  /// 메뉴 정보를 수정한다.
  Future<MenuItem?> update(int id, MenuInput input) async {
    _setSubmitting(true);
    try {
      final updated = await _repository.update(id, input);
      await fetch(page: _result?.page ?? 1);
      await loadParents();
      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 {
      await _repository.delete(id);
      await fetch(page: _result?.page ?? 1);
      await loadParents();
      return true;
    } catch (error) {
      final failure = Failure.from(error);
      _errorMessage = failure.describe();
      notifyListeners();
      return false;
    } finally {
      _setSubmitting(false);
    }
  }

  /// 삭제된 메뉴를 복구한다.
  Future<MenuItem?> restore(int id) async {
    _setSubmitting(true);
    try {
      final restored = await _repository.restore(id);
      await fetch(page: _result?.page ?? 1);
      await loadParents();
      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();
  }
}
