import 'dart:async';

import 'package:be_happy/domain/usecase/verify_pin_usecase.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../domain/usecase/is_pin_set_usecase.dart';
import '../event/pin_event.dart';
import '../state/pin_state.dart';
import '../../domain/usecase/create_pin_usecase.dart';

class PinBloc extends Bloc<PinEvent, PinState> {
  final CreatePinUseCase createPinUseCase;
  final VerifyPinUseCase verifyPinUsecase;
  final IsPinSetUsecase isPinSetUsecase;

  PinBloc({
    required this.createPinUseCase,
    required this.verifyPinUsecase,
    required this.isPinSetUsecase,
    bool isRegistration = true,
  }) : super(const PinLoading()) {
    on<PinDigitChanged>(_onPinChanged);
    on<PinSubmitted>(_onPinSubmitted);
    on<PinScreenStarted>(_onPinScreenStarted);
  }

  void _onPinChanged(
      PinDigitChanged event,
      Emitter<PinState> emit,
      ) {
    if (state is PinCreateInProgress) {
      emit(PinCreateInProgress(pin: event.pin));
    } else if (state is PinLoginInProgress) {
      emit(PinLoginInProgress(pin: event.pin));
    }
  }

  Future<void> _onPinSubmitted(
      PinSubmitted event,
      Emitter<PinState> emit,
      ) async {
    final currentPin = event.pin;
    final bool isCreateMode = state is PinCreateInProgress;

    emit(const PinLoading());

    try {
      if (isCreateMode) {
        await createPinUseCase(currentPin);
        emit(const PinSuccess());
      } else {
        final isValid = await verifyPinUsecase(currentPin);
        if (isValid) {
          emit(const PinSuccess());
        } else {
          throw Exception("Неверный ПИН-код");
        }
      }
    } catch (e) {
      if (isCreateMode) {
        emit(PinCreateInProgress(pin: '', error: e.toString()));
      } else {
        emit(PinLoginInProgress(pin: '', error: e.toString().contains("Неверный")
            ? "Неверный ПИН-код"
            : "Ошибка при проверке"));
      }
    }
  }

  FutureOr<void> _onPinScreenStarted(PinScreenStarted event, Emitter<PinState> emit) async {
    try {
      final bool hasPin = await isPinSetUsecase();

      if (hasPin) {
        // Пин ЕСТЬ в базе — значит, нужно его ВВЕСТИ (Login)
        emit(const PinLoginInProgress(pin: ''));
      } else {
        // Пина НЕТ в базе — значит, нужно его СОЗДАТЬ (Create)
        emit(const PinCreateInProgress(pin: ''));
      }
    } catch (e) {
      emit(PinLoginInProgress(pin: '', error: "Ошибка доступа к хранилищу"));
    }
  }
}