import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:krow_core/core.dart';
import 'package:krow_domain/krow_domain.dart';

import '../../domain/arguments/save_attire_arguments.dart';
import '../../domain/arguments/upload_attire_photo_arguments.dart';
import '../../domain/usecases/get_attire_options_usecase.dart';
import '../../domain/usecases/save_attire_usecase.dart';
import '../../domain/usecases/upload_attire_photo_usecase.dart';
import 'attire_state.dart';

class AttireCubit extends Cubit<AttireState>
    with BlocErrorHandler<AttireState> {
  final GetAttireOptionsUseCase _getAttireOptionsUseCase;
  final SaveAttireUseCase _saveAttireUseCase;
  final UploadAttirePhotoUseCase _uploadAttirePhotoUseCase;

  AttireCubit(
    this._getAttireOptionsUseCase,
    this._saveAttireUseCase,
    this._uploadAttirePhotoUseCase,
  ) : super(const AttireState()) {
    loadOptions();
  }

  Future<void> loadOptions() async {
    emit(state.copyWith(status: AttireStatus.loading));
    await handleError(
      emit: emit,
      action: () async {
        final List<AttireItem> options = await _getAttireOptionsUseCase();

        // Auto-select mandatory items initially as per prototype
        final List<String> mandatoryIds =
            options
                .where((AttireItem e) => e.isMandatory)
                .map((AttireItem e) => e.id)
                .toList();

        final List<String> initialSelection = List<String>.from(
          state.selectedIds,
        );
        for (final String id in mandatoryIds) {
          if (!initialSelection.contains(id)) {
            initialSelection.add(id);
          }
        }

        emit(
          state.copyWith(
            status: AttireStatus.success,
            options: options,
            selectedIds: initialSelection,
          ),
        );
      },
      onError:
          (String errorKey) => state.copyWith(
            status: AttireStatus.failure,
            errorMessage: errorKey,
          ),
    );
  }

  void toggleSelection(String id) {
    // Prevent unselecting mandatory items
    if (state.isMandatory(id)) return;

    final List<String> currentSelection = List<String>.from(state.selectedIds);
    if (currentSelection.contains(id)) {
      currentSelection.remove(id);
    } else {
      currentSelection.add(id);
    }
    emit(state.copyWith(selectedIds: currentSelection));
  }

  void toggleAttestation(bool value) {
    emit(state.copyWith(attestationChecked: value));
  }

  Future<void> uploadPhoto(String itemId) async {
    final Map<String, bool> currentUploading = Map<String, bool>.from(
      state.uploadingStatus,
    );
    currentUploading[itemId] = true;
    emit(state.copyWith(uploadingStatus: currentUploading));

    await handleError(
      emit: emit,
      action: () async {
        final String url = await _uploadAttirePhotoUseCase(
          UploadAttirePhotoArguments(itemId: itemId),
        );

        final Map<String, String> currentPhotos = Map<String, String>.from(
          state.photoUrls,
        );
        currentPhotos[itemId] = url;

        // Auto-select item on upload success if not selected
        final List<String> currentSelection = List<String>.from(
          state.selectedIds,
        );
        if (!currentSelection.contains(itemId)) {
          currentSelection.add(itemId);
        }

        final Map<String, bool> updatedUploading = Map<String, bool>.from(
          state.uploadingStatus,
        );
        updatedUploading[itemId] = false;

        emit(
          state.copyWith(
            uploadingStatus: updatedUploading,
            photoUrls: currentPhotos,
            selectedIds: currentSelection,
          ),
        );
      },
      onError: (String errorKey) {
        final Map<String, bool> updatedUploading = Map<String, bool>.from(
          state.uploadingStatus,
        );
        updatedUploading[itemId] = false;
        // Could handle error specifically via snackbar event
        // For now, attaching the error message but keeping state generally usable
        return state.copyWith(
          uploadingStatus: updatedUploading,
          errorMessage: errorKey,
        );
      },
    );
  }

  Future<void> save() async {
    if (!state.canSave) return;

    emit(state.copyWith(status: AttireStatus.saving));
    await handleError(
      emit: emit,
      action: () async {
        await _saveAttireUseCase(
          SaveAttireArguments(
            selectedItemIds: state.selectedIds,
            photoUrls: state.photoUrls,
          ),
        );
        emit(state.copyWith(status: AttireStatus.saved));
      },
      onError:
          (String errorKey) => state.copyWith(
            status: AttireStatus.failure,
            errorMessage: errorKey,
          ),
    );
  }
}

