import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../domain/usecases/get_attendance_records_usecase.dart';
import '../../../domain/usecases/get_extra_hours_usecase.dart';
import '../../../domain/usecases/get_rewards_usecase.dart';
import '../../../domain/usecases/get_punishments_usecase.dart';
import '../../../domain/usecases/get_salary_summary_usecase.dart';
import '../../../domain/models/finance_record.dart';
import '../../../domain/models/finance_category.dart';
import '../../../core/error/exceptions.dart';

// Events
abstract class FinanceEvent {}

class LoadFinanceDataEvent extends FinanceEvent {
  final String employeeId;
  final FinanceCategory category;
  final int? month;
  final int? year;

  LoadFinanceDataEvent({
    required this.employeeId,
    required this.category,
    this.month,
    this.year,
  });
}

// States
abstract class FinanceState {}

class FinanceInitial extends FinanceState {}

class FinanceLoading extends FinanceState {}

class FinanceLoaded extends FinanceState {
  final List<FinanceRecord> records;
  final FinanceCategory category;
  final double netSalary;

  FinanceLoaded({
    required this.records,
    required this.category,
    this.netSalary = 0.0,
  });
}

class FinanceError extends FinanceState {
  final String message;

  FinanceError({required this.message});
}

// Bloc
class FinanceBloc extends Bloc<FinanceEvent, FinanceState> {
  final GetAttendanceRecordsUseCase getAttendanceRecordsUseCase;
  final GetExtraHoursUseCase getExtraHoursUseCase;
  final GetRewardsUseCase getRewardsUseCase;
  final GetPunishmentsUseCase getPunishmentsUseCase;
  final GetSalarySummaryUseCase getSalarySummaryUseCase;

  FinanceBloc({
    required this.getAttendanceRecordsUseCase,
    required this.getExtraHoursUseCase,
    required this.getRewardsUseCase,
    required this.getPunishmentsUseCase,
    required this.getSalarySummaryUseCase,
  }) : super(FinanceInitial()) {
    on<LoadFinanceDataEvent>(_onLoadFinanceData);
  }

  Future<void> _onLoadFinanceData(
    LoadFinanceDataEvent event,
    Emitter<FinanceState> emit,
  ) async {
    if (event.employeeId.isEmpty) {
      emit(FinanceError(message: 'Employee ID is missing or invalid'));
      return;
    }

    emit(FinanceLoading());
    try {
      final now = DateTime.now();
      final month = event.month ?? now.month;
      final year = event.year ?? now.year;
      double netSalary = 0.0;

      print(
        'Fetching salary for Employee: ${event.employeeId}, Month: $month, Year: $year',
      );
      try {
        final salaryModel = await getSalarySummaryUseCase.execute(
          employeeId: event.employeeId,
          month: month,
          year: year,
        );
        print('Salary Model fetched: ${salaryModel.netAmount}');
        netSalary = salaryModel.netAmount;
      } catch (e) {
        print('Error fetching salary: $e');
        // We continue even if salary fails, to show the list at least
      }

      List<FinanceRecord> records;
      switch (event.category) {
        case FinanceCategory.attendance:
          records = await getAttendanceRecordsUseCase.execute(
            employeeId: event.employeeId,
          );
          break;
        case FinanceCategory.overtime:
          records = await getExtraHoursUseCase.execute(
            employeeId: event.employeeId,
          );
          break;
        case FinanceCategory.bonus:
          records = await getRewardsUseCase.execute(
            employeeId: event.employeeId,
          );
          break;
        case FinanceCategory.penalty:
          records = await getPunishmentsUseCase.execute(
            employeeId: event.employeeId,
          );
          break;
      }
      emit(
        FinanceLoaded(
          records: records,
          category: event.category,
          netSalary: netSalary,
        ),
      );
    } on ServerException catch (e) {
      emit(FinanceError(message: e.message));
    } on NetworkException catch (e) {
      emit(FinanceError(message: e.message));
    } catch (e) {
      emit(FinanceError(message: 'Unexpected error occurred: ${e.toString()}'));
    }
  }
}
