import 'package:bloc/bloc.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'organization_event.dart';
import 'organization_state.dart';
import '../permission/permission_bloc.dart';
import '../permission/permission_event.dart';
import '../file_browser/file_browser_bloc.dart';
import '../file_browser/file_browser_event.dart';
import '../upload/upload_bloc.dart';
import '../upload/upload_event.dart';
import '../../services/org_api.dart';
import '../../models/api_error.dart';

class OrganizationBloc extends Bloc<OrganizationEvent, OrganizationState> {
  final PermissionBloc permissionBloc;
  final FileBrowserBloc fileBrowserBloc;
  final UploadBloc uploadBloc;
  final OrgApi orgApi;

  OrganizationBloc(
    this.permissionBloc,
    this.fileBrowserBloc,
    this.uploadBloc,
    this.orgApi,
  ) : super(OrganizationInitial()) {
    on<LoadOrganizations>(_onLoadOrganizations);
    on<SelectOrganization>(_onSelectOrganization);
    on<CreateOrganization>(_onCreateOrganization);
  }

  String _getErrorMessage(dynamic error) {
    if (error is ApiError) {
      switch (error.code) {
        case 'UNAUTHENTICATED':
          return 'Session expired. Please log in again.';
        case 'PERMISSION_DENIED':
          return 'You do not have permission to perform this action.';
        case 'NOT_FOUND':
          return 'The requested resource was not found.';
        case 'CONFLICT':
          return 'A conflict occurred. Please try again.';
        case 'INVALID_ARGUMENT':
          return 'Invalid input provided.';
        case 'INTERNAL':
        default:
          return 'An internal error occurred. Please try again later.';
      }
    }
    return error.toString();
  }

  void _onLoadOrganizations(
    LoadOrganizations event,
    Emitter<OrganizationState> emit,
  ) async {
    emit(OrganizationLoading());
    try {
      final orgs = await orgApi.getOrganizations();
      emit(
        OrganizationLoaded(
          organizations: orgs,
          selectedOrg: orgs.isNotEmpty ? orgs.first : null,
        ),
      );
    } catch (e) {
      emit(OrganizationError(_getErrorMessage(e)));
    }
  }

  void _onSelectOrganization(
    SelectOrganization event,
    Emitter<OrganizationState> emit,
  ) {
    final currentState = state;
    if (currentState is OrganizationLoaded) {
      Organization? selected;

      if (event.orgId.isEmpty) {
        // Personal workspace - set to null to indicate no org selected
        selected = null;
      } else {
        selected = currentState.organizations.firstWhere(
          (org) => org.id == event.orgId,
          orElse: () => currentState.selectedOrg!,
        );
      }

      emit(
        OrganizationLoaded(
          organizations: currentState.organizations,
          selectedOrg: selected,
          isLoading: false,
        ),
      );
      // Reset all dependent blocs
      permissionBloc.add(PermissionsReset());
      fileBrowserBloc.add(ResetFileBrowser(event.orgId));
      uploadBloc.add(ResetUploads());
      // Load permissions for the selected org
      permissionBloc.add(LoadPermissions(event.orgId));
    }
  }

  void _onCreateOrganization(
    CreateOrganization event,
    Emitter<OrganizationState> emit,
  ) async {
    final name = event.name.trim();
    if (name.isEmpty) {
      // Try to preserve current state if possible
      if (state is OrganizationLoaded) {
        emit(
          OrganizationLoaded(
            organizations: (state as OrganizationLoaded).organizations,
            selectedOrg: (state as OrganizationLoaded).selectedOrg,
            isLoading: false,
            error: 'Organization name cannot be empty',
          ),
        );
      }
      return;
    }

    // Get existing organizations list
    List<Organization> existingOrgs = [];
    Organization? selectedOrg;

    if (state is OrganizationLoaded) {
      existingOrgs = (state as OrganizationLoaded).organizations;
      selectedOrg = (state as OrganizationLoaded).selectedOrg;

      // Check for duplicate name (client-side validation)
      if (existingOrgs.any((org) => org.name == name)) {
        emit(
          OrganizationLoaded(
            organizations: existingOrgs,
            selectedOrg: selectedOrg,
            isLoading: false,
            error: 'Organization with this name already exists',
          ),
        );
        return;
      }
    }

    // Set loading state
    emit(
      OrganizationLoaded(
        organizations: existingOrgs,
        selectedOrg: selectedOrg,
        isLoading: true,
      ),
    );

    try {
      final newOrg = await orgApi.createOrganization(name);

      final updatedOrgs = [...existingOrgs, newOrg];
      emit(OrganizationLoaded(organizations: updatedOrgs, selectedOrg: newOrg));
      // Reset blocs and load permissions for new org
      permissionBloc.add(PermissionsReset());
      fileBrowserBloc.add(ResetFileBrowser(newOrg.id));
      uploadBloc.add(ResetUploads());
      permissionBloc.add(LoadPermissions(newOrg.id));
    } catch (e) {
      emit(
        OrganizationLoaded(
          organizations: existingOrgs,
          selectedOrg: selectedOrg,
          isLoading: false,
          error: _getErrorMessage(e),
        ),
      );
    }
  }
}
