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 '../../../vendor/domain/entities/vendor.dart';
import '../../../vendor/domain/repositories/vendor_repository.dart';
import '../../../uom/domain/entities/uom.dart';
import '../../../uom/domain/repositories/uom_repository.dart';
import '../../domain/entities/product.dart';
import '../../domain/repositories/product_repository.dart';

/// 제품 사용 여부 필터.
enum ProductStatusFilter { all, activeOnly, inactiveOnly }

/// 제품 마스터 화면 상태를 관리하는 컨트롤러.
class ProductController extends ChangeNotifier {
  static const int defaultPageSize = 20;

  ProductController({
    required ProductRepository productRepository,
    required VendorRepository vendorRepository,
    required UomRepository uomRepository,
  }) : _productRepository = productRepository,
       _vendorRepository = vendorRepository,
       _uomRepository = uomRepository;

  final ProductRepository _productRepository;
  final VendorRepository _vendorRepository;
  final UomRepository _uomRepository;

  PaginatedResult<Product>? _result;
  bool _isLoading = false;
  bool _isSubmitting = false;
  bool _isLoadingLookups = false;
  String _query = '';
  int? _vendorFilter;
  int? _uomFilter;
  ProductStatusFilter _statusFilter = ProductStatusFilter.all;
  int _pageSize = defaultPageSize;
  String? _errorMessage;

  List<Vendor> _vendorOptions = const [];
  List<Uom> _uomOptions = const [];
  bool _isDisposed = false;

  PaginatedResult<Product>? get result => _result;
  bool get isLoading => _isLoading;
  bool get isSubmitting => _isSubmitting;
  bool get isLoadingLookups => _isLoadingLookups;
  String get query => _query;
  int? get vendorFilter => _vendorFilter;
  int? get uomFilter => _uomFilter;
  ProductStatusFilter get statusFilter => _statusFilter;
  int get pageSize => _pageSize;
  String? get errorMessage => _errorMessage;
  List<Vendor> get vendorOptions => _vendorOptions;
  List<Uom> get uomOptions => _uomOptions;

  /// 제품 목록을 조회한다.
  Future<void> fetch({int page = 1}) async {
    _isLoading = true;
    _errorMessage = null;
    _notifySafely();
    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) {
        ProductStatusFilter.all => null,
        ProductStatusFilter.activeOnly => true,
        ProductStatusFilter.inactiveOnly => false,
      };
      final response = await _productRepository.list(
        page: resolvedPage,
        pageSize: _pageSize,
        query: _query.isEmpty ? null : _query,
        vendorId: _vendorFilter,
        uomId: _uomFilter,
        isActive: isActive,
      );
      _result = response;
      if (response.pageSize > 0 && response.pageSize != _pageSize) {
        _pageSize = response.pageSize;
      }
    } catch (error) {
      final failure = Failure.from(error);
      _errorMessage = failure.describe();
    } finally {
      _isLoading = false;
      _notifySafely();
    }
  }

  /// 필터/폼에서 사용할 공급업체와 단위 목록을 로드한다.
  Future<void> loadLookups() async {
    _isLoadingLookups = true;
    _notifySafely();
    try {
      debugPrint('[ProductController] 드롭다운 데이터 조회 시작');
      final vendors = await fetchAllPaginatedItems<Vendor>(
        request: (page, pageSize) =>
            _vendorRepository.list(page: page, pageSize: pageSize),
      );
      final uoms = await fetchAllPaginatedItems<Uom>(
        request: (page, pageSize) =>
            _uomRepository.list(page: page, pageSize: pageSize),
      );
      _vendorOptions = vendors;
      _uomOptions = uoms;
      debugPrint(
        '[ProductController] 드롭다운 데이터 조회 완료 '
        '(vendors=${vendors.length}, uoms=${uoms.length})',
      );
    } catch (error) {
      final failure = Failure.from(error);
      _errorMessage = failure.describe();
      debugPrint(
        '[ProductController] 드롭다운 데이터 조회 실패: ${_errorMessage ?? '알 수 없는 오류'}',
      );
    } finally {
      _isLoadingLookups = false;
      _notifySafely();
    }
  }

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

  /// 공급업체 필터를 변경한다.
  void updateVendorFilter(int? vendorId) {
    if (_vendorFilter == vendorId) {
      return;
    }
    _vendorFilter = vendorId;
    _notifySafely();
  }

  /// 단위(UOM) 필터를 변경한다.
  void updateUomFilter(int? uomId) {
    if (_uomFilter == uomId) {
      return;
    }
    _uomFilter = uomId;
    _notifySafely();
  }

  /// 사용 여부 필터를 변경한다.
  void updateStatusFilter(ProductStatusFilter filter) {
    if (_statusFilter == filter) {
      return;
    }
    _statusFilter = filter;
    _notifySafely();
  }

  /// 페이지 크기를 변경한다.
  void updatePageSize(int size) {
    if (size <= 0 || _pageSize == size) {
      return;
    }
    _pageSize = size;
    _notifySafely();
  }

  /// 제품을 생성한다.
  Future<Product?> create(ProductInput input) async {
    _setSubmitting(true);
    try {
      final created = await _productRepository.create(input);
      await fetch(page: 1);
      return created;
    } catch (error) {
      final failure = Failure.from(error);
      _errorMessage = failure.describe();
      _notifySafely();
      return null;
    } finally {
      _setSubmitting(false);
    }
  }

  /// 제품 정보를 수정한다.
  Future<Product?> update(int id, ProductInput input) async {
    _setSubmitting(true);
    try {
      final updated = await _productRepository.update(id, input);
      await fetch(page: _result?.page ?? 1);
      return updated;
    } catch (error) {
      final failure = Failure.from(error);
      _errorMessage = failure.describe();
      _notifySafely();
      return null;
    } finally {
      _setSubmitting(false);
    }
  }

  /// 제품을 삭제한다.
  Future<bool> delete(int id) async {
    _setSubmitting(true);
    try {
      await _productRepository.delete(id);
      await fetch(page: _result?.page ?? 1);
      return true;
    } catch (error) {
      final failure = Failure.from(error);
      _errorMessage = failure.describe();
      _notifySafely();
      return false;
    } finally {
      _setSubmitting(false);
    }
  }

  /// 삭제된 제품을 복구한다.
  Future<Product?> restore(int id) async {
    _setSubmitting(true);
    try {
      final restored = await _productRepository.restore(id);
      await fetch(page: _result?.page ?? 1);
      return restored;
    } catch (error) {
      final failure = Failure.from(error);
      _errorMessage = failure.describe();
      _notifySafely();
      return null;
    } finally {
      _setSubmitting(false);
    }
  }

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

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

  /// dispose 이후에는 알림을 중단하여 디버그 에러를 방지한다.
  void _notifySafely() {
    if (_isDisposed) {
      return;
    }
    super.notifyListeners();
  }

  @override
  void dispose() {
    _isDisposed = true;
    super.dispose();
  }
}
