import 'models.dart'; /// Local DTO boundary: transport fields never escape services into providers/UI. class DestinationDTO { const DestinationDTO(this.value); final Map value; } abstract final class DestinationMapper { static DestinationDTO details(DestinationDetails value) => DestinationDTO(switch (value) { CryptoDestination d => { 'type': 'crypto', 'assetId': d.assetId, 'networkId': d.networkId, 'address': d.address, 'memo': d.memo, 'assetLabel': d.assetLabel, 'networkLabel': d.networkLabel, }, CardDestination d => { 'type': 'card', 'capture': d.capture, 'identity': d.identity, 'brand': d.brand, 'last4': d.last4, 'expiryMonth': d.expiryMonth, 'expiryYear': d.expiryYear, }, RussianBankDestination d => { 'type': 'russianBank', 'firstName': d.firstName, 'lastName': d.lastName, 'patronymic': d.patronymic, 'account': d.account, 'bank': bank(d.bank), }, }); static Map bank(Bank b) => { 'bik': b.bik, 'name': b.name, 'city': b.city, 'correspondent': b.correspondent, 'revision': b.revision, 'supported': b.supported, }; static Bank fromBank(Map v) => Bank( bik: v['bik'] as String, name: v['name'] as String, city: v['city'] as String, correspondent: v['correspondent'] as String, revision: v['revision'] as String, supported: v['supported'] as bool, ); static DestinationDetails fromDTO(DestinationDTO dto) { final d = dto.value; return switch (d['type']) { 'crypto' => CryptoDestination( assetId: d['assetId'] as String, networkId: d['networkId'] as String, address: d['address'] as String, memo: d['memo'] as String, assetLabel: d['assetLabel'] as String, networkLabel: d['networkLabel'] as String, ), 'card' => CardDestination( capture: d['capture'] as String, identity: d['identity'] as String, brand: d['brand'] as String, last4: d['last4'] as String, expiryMonth: d['expiryMonth'] as int, expiryYear: d['expiryYear'] as int, ), 'russianBank' => RussianBankDestination( firstName: d['firstName'] as String, lastName: d['lastName'] as String, patronymic: d['patronymic'] as String, account: d['account'] as String, bank: fromBank(Map.from(d['bank'] as Map)), ), _ => throw const DestinationException(DestinationIssue.unsupported), }; } static DestinationDetails clone(DestinationDetails d) => fromDTO(details(d)); } sealed class DestinationInputDTO { const DestinationInputDTO(); } class SavedInputDTO extends DestinationInputDTO { const SavedInputDTO(this.id, this.executionRevision); final String id; final int executionRevision; } class OneTimeInputDTO extends DestinationInputDTO { const OneTimeInputDTO(this.details); final DestinationDTO details; } abstract final class DestinationInputMapper { static DestinationInputDTO toDTO(DestinationInput input) => switch (input) { SavedReference r => SavedInputDTO(r.id, r.executionRevision), OneTimeDestination d => OneTimeInputDTO( DestinationMapper.details(d.details), ), }; static DestinationInput fromDTO(DestinationInputDTO dto) => switch (dto) { SavedInputDTO d => SavedReference(d.id, d.executionRevision), OneTimeInputDTO d => OneTimeDestination( DestinationMapper.fromDTO(d.details), ), }; }