import 'package:logging/logging.dart'; import 'package:share_plus/share_plus.dart'; import 'package:pshared/api/errors/unauthorized.dart'; import 'package:pshared/api/responses/organization.dart'; import 'package:pshared/models/describable.dart'; import 'package:pshared/models/organization/organization.dart'; import 'package:pshared/data/mapper/organization.dart'; import 'package:pshared/service/authorization/service.dart'; import 'package:pshared/service/files.dart'; import 'package:pshared/service/services.dart'; import 'package:pshared/utils/http/requests.dart'; class OrganizationService { static final _logger = Logger('service.organization'); static const String _objectType = Services.organization; static Future> list() async { _logger.fine('Loading all organizations'); return _getOrganizations(AuthorizationService.getGETResponse(_objectType, '')); } static Future load(String organizationRef) async { _logger.fine('Loading organization $organizationRef'); final orgs = await _getOrganizations(AuthorizationService.getGETResponse(_objectType, organizationRef)); return orgs.first; } static Future loadByInvitation(String invitationRef) async { _logger.fine('Loading organization by invitation ref $invitationRef'); final orgs = await _getOrganizations(getGETResponse(_objectType, 'invitation/$invitationRef')); return orgs.first; } static Future> update(Organization organization) async { _logger.fine('Patching organization ${organization.id}'); // Convert domain object to DTO, then to JSON return _getOrganizations( AuthorizationService.getPUTResponse(_objectType, '', organization.toDTO().toJson()) ); } static Future updateSettings( Organization organization, { String? name, String? description, String? timeZone, String? logoUrl, }) async { _logger.fine('Updating organization settings ${organization.id}'); final updatedDescribable = (name != null || description != null) ? organization.describable.copyWith( name: name, description: description != null ? () => description : null, ) : organization.describable; final updatedOrg = organization.copyWith( describable: updatedDescribable, timeZone: timeZone, logoUrl: logoUrl != null ? () => logoUrl : null, ); final updated = await update(updatedOrg); return updated.firstWhere( (org) => org.id == organization.id, orElse: () => updated.first, ); } static Future uploadLogoAndUpdate(Organization organization, XFile logoFile) async { _logger.fine('Uploading logo for organization ${organization.id}'); final url = await uploadLogo(organization.id, logoFile); return updateSettings(organization, logoUrl: url); } static Future uploadLogo(String organizationRef, XFile logoFile) async { _logger.fine('Uploading logo'); return FilesService.uploadImage(_objectType, organizationRef, logoFile); } static Future> _getOrganizations(Future> future) async { try { final responseJson = await future; final response = OrganizationResponse.fromJson(responseJson); final orgs = response.organizations.map((dto) => dto.toDomain()).toList(); if (orgs.isEmpty) throw ErrorUnauthorized(); _logger.fine('Fetched ${orgs.length} organization(s)'); return orgs; } catch (e, stackTrace) { _logger.severe('Failed to fetch organizations', e, stackTrace); rethrow; } } }