import 'dart:typed_data';

import 'package:commons_core/commons_core.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import '../data/variety_repository.dart';
import '../db/enums.dart';

const Object _unset = Object();

/// Form state for the quick-add sheet. Only [label] is required; everything
/// else is progressive disclosure behind [expanded].
class QuickAddState extends Equatable {
  const QuickAddState({
    this.label = '',
    this.quantity,
    this.lotType = LotType.seed,
    this.photoBytes,
    this.expanded = false,
    this.submitting = false,
    this.submitted = false,
    this.showLabelError = false,
    this.addedCount = 0,
  });

  final String label;
  final Quantity? quantity;
  final LotType lotType;
  final Uint8List? photoBytes;
  final bool expanded;
  final bool submitting;
  final bool submitted;
  final bool showLabelError;

  /// How many seeds this sheet has saved via "save & add another" (it stays
  /// open); drives the "N added" feedback and resets of the label field.
  final int addedCount;

  bool get hasValidLabel => label.trim().isNotEmpty;

  QuickAddState copyWith({
    String? label,
    Object? quantity = _unset,
    LotType? lotType,
    Uint8List? photoBytes,
    bool? expanded,
    bool? submitting,
    bool? submitted,
    bool? showLabelError,
    int? addedCount,
  }) {
    return QuickAddState(
      label: label ?? this.label,
      quantity: identical(quantity, _unset)
          ? this.quantity
          : quantity as Quantity?,
      lotType: lotType ?? this.lotType,
      photoBytes: photoBytes ?? this.photoBytes,
      expanded: expanded ?? this.expanded,
      submitting: submitting ?? this.submitting,
      submitted: submitted ?? this.submitted,
      showLabelError: showLabelError ?? this.showLabelError,
      addedCount: addedCount ?? this.addedCount,
    );
  }

  @override
  List<Object?> get props => [
    label,
    quantity,
    lotType,
    photoBytes,
    expanded,
    submitting,
    submitted,
    showLabelError,
    addedCount,
  ];
}

/// Drives the 20-second quick-add flow and persists via [VarietyRepository].
class QuickAddCubit extends Cubit<QuickAddState> {
  QuickAddCubit(this._repo) : super(const QuickAddState());

  final VarietyRepository _repo;

  void labelChanged(String value) =>
      emit(state.copyWith(label: value, showLabelError: false));

  void setQuantity(Quantity? quantity) =>
      emit(state.copyWith(quantity: quantity));

  void setLotType(LotType type) => emit(state.copyWith(lotType: type));

  void photoPicked(Uint8List bytes) => emit(state.copyWith(photoBytes: bytes));

  void toggleExpanded() => emit(state.copyWith(expanded: !state.expanded));

  /// Validates and saves. No-op (sets [showLabelError]) if the label is empty.
  Future<void> submit() async {
    if (!state.hasValidLabel) {
      emit(state.copyWith(showLabelError: true));
      return;
    }
    if (state.submitting) return;
    emit(state.copyWith(submitting: true));
    await _repo.addQuickVariety(
      label: state.label.trim(),
      lotType: state.lotType,
      quantity: state.quantity,
      photoBytes: state.photoBytes,
    );
    emit(state.copyWith(submitting: false, submitted: true));
  }

  /// Saves and keeps the sheet open for the next seed: resets the form to a
  /// clean state (keeping the chosen [lotType]) and bumps [addedCount]. Lets a
  /// user rip through a whole shelf without reopening the sheet each time.
  Future<void> submitAndAddAnother() async {
    if (!state.hasValidLabel) {
      emit(state.copyWith(showLabelError: true));
      return;
    }
    if (state.submitting) return;
    emit(state.copyWith(submitting: true));
    await _repo.addQuickVariety(
      label: state.label.trim(),
      lotType: state.lotType,
      quantity: state.quantity,
      photoBytes: state.photoBytes,
    );
    emit(
      QuickAddState(lotType: state.lotType, addedCount: state.addedCount + 1),
    );
  }
}
