import 'package:flutter/material.dart'; import '../../../services/clubs/club_models.dart'; /// Semantic state representing the viewer's relationship to a Club. enum ClubMembershipPresentationState { unauthenticated, outsiderOpen, outsiderRequest, outsiderInviteOnly, invited, requested, activeMember, activeAdmin, activeOwner, archived, unavailable, } /// Action intent triggered by the rider on a Club. enum ClubMembershipAction { joinOpen, requestToJoin, withdrawRequest, acceptInvite, declineInvite, leaveClub, signIn, } /// Badge color categorization for automotive UI styling. enum PresentationBadgeType { cyan, green, amber, neutral, } /// Pure presentation model mapping Club metadata, membership state, and auth context /// into authoritative, unambiguous UX components. @immutable class ClubMembershipPresentation { final ClubMembershipPresentationState state; final String statusBadge; final PresentationBadgeType badgeType; final String statusHeadline; final String statusDescription; final ClubMembershipAction? primaryAction; final String? primaryActionLabel; final IconData? primaryActionIcon; final bool isPrimaryDestructive; final ClubMembershipAction? secondaryAction; final String? secondaryActionLabel; final IconData? secondaryActionIcon; final bool isSecondaryDestructive; final bool canLeave; final bool isActionable; const ClubMembershipPresentation({ required this.state, required this.statusBadge, required this.badgeType, required this.statusHeadline, required this.statusDescription, this.primaryAction, this.primaryActionLabel, this.primaryActionIcon, this.isPrimaryDestructive = false, this.secondaryAction, this.secondaryActionLabel, this.secondaryActionIcon, this.isSecondaryDestructive = false, this.canLeave = false, this.isActionable = false, }); /// Resolves the pure presentation state from domain models and auth context. static ClubMembershipPresentation resolve({ required Club? club, required ClubMember? member, required String? currentUserId, required bool isAuthenticated, }) { if (club == null) { return const ClubMembershipPresentation( state: ClubMembershipPresentationState.unavailable, statusBadge: 'UNAVAILABLE', badgeType: PresentationBadgeType.neutral, statusHeadline: 'Club Not Found', statusDescription: 'This club could not be loaded or does not exist.', isActionable: false, ); } if (club.isArchived) { return const ClubMembershipPresentation( state: ClubMembershipPresentationState.archived, statusBadge: 'ARCHIVED', badgeType: PresentationBadgeType.amber, statusHeadline: 'Club Archived', statusDescription: 'This club has been archived by leadership and is no longer accepting members.', canLeave: false, isActionable: false, ); } if (!isAuthenticated || currentUserId == null || currentUserId.isEmpty) { return const ClubMembershipPresentation( state: ClubMembershipPresentationState.unauthenticated, statusBadge: 'GUEST', badgeType: PresentationBadgeType.neutral, statusHeadline: 'Sign in to Join', statusDescription: 'Sign in with a registered account to join this club and ride with members.', primaryAction: ClubMembershipAction.signIn, primaryActionLabel: 'Sign In / Register', primaryActionIcon: Icons.login, isActionable: true, ); } // Root ownership remains authoritative when the member record is missing or stale. if (club.ownerUid == currentUserId || member?.isActive == true) { final isOwner = member?.role == ClubRole.owner || club.ownerUid == currentUserId; if (isOwner) { return const ClubMembershipPresentation( state: ClubMembershipPresentationState.activeOwner, statusBadge: 'OWNER', badgeType: PresentationBadgeType.green, statusHeadline: 'Club Owner', statusDescription: 'You are the owner of this club. Ownership must be transferred before leaving.', canLeave: false, isActionable: false, ); } if (member?.role == ClubRole.admin) { return const ClubMembershipPresentation( state: ClubMembershipPresentationState.activeAdmin, statusBadge: 'ADMIN', badgeType: PresentationBadgeType.cyan, statusHeadline: 'Club Administrator', statusDescription: 'You are an active administrator of this club.', primaryAction: ClubMembershipAction.leaveClub, primaryActionLabel: 'Leave Club', primaryActionIcon: Icons.logout, isPrimaryDestructive: true, canLeave: true, isActionable: true, ); } return const ClubMembershipPresentation( state: ClubMembershipPresentationState.activeMember, statusBadge: 'MEMBER', badgeType: PresentationBadgeType.cyan, statusHeadline: 'Active Member', statusDescription: 'You are an active member of this club.', primaryAction: ClubMembershipAction.leaveClub, primaryActionLabel: 'Leave Club', primaryActionIcon: Icons.logout, isPrimaryDestructive: true, canLeave: true, isActionable: true, ); } // Authenticated user with an incoming invitation if (member != null && member.status == ClubMemberStatus.invited) { return const ClubMembershipPresentation( state: ClubMembershipPresentationState.invited, statusBadge: 'INVITED', badgeType: PresentationBadgeType.green, statusHeadline: 'You Are Invited', statusDescription: 'You have been invited to join this club by club leadership.', primaryAction: ClubMembershipAction.acceptInvite, primaryActionLabel: 'Accept Invitation', primaryActionIcon: Icons.check_circle_outline, secondaryAction: ClubMembershipAction.declineInvite, secondaryActionLabel: 'Decline', secondaryActionIcon: Icons.close, isSecondaryDestructive: true, isActionable: true, ); } // Authenticated user with a pending join request if (member != null && member.status == ClubMemberStatus.requested) { return const ClubMembershipPresentation( state: ClubMembershipPresentationState.requested, statusBadge: 'REQUEST PENDING', badgeType: PresentationBadgeType.amber, statusHeadline: 'Membership Requested', statusDescription: 'Your request to join is awaiting approval from club leadership.', primaryAction: ClubMembershipAction.withdrawRequest, primaryActionLabel: 'Withdraw Request', primaryActionIcon: Icons.cancel_outlined, isPrimaryDestructive: true, isActionable: true, ); } // Outsider (no member doc or historical doc: left, declined, removed) switch (club.admissionPolicy) { case ClubAdmissionPolicy.open: return const ClubMembershipPresentation( state: ClubMembershipPresentationState.outsiderOpen, statusBadge: 'OPEN ADMISSION', badgeType: PresentationBadgeType.cyan, statusHeadline: 'Open Membership', statusDescription: 'This club is open to all riders. Join now to participate in club rides.', primaryAction: ClubMembershipAction.joinOpen, primaryActionLabel: 'Join Club', primaryActionIcon: Icons.group_add, isActionable: true, ); case ClubAdmissionPolicy.request: return const ClubMembershipPresentation( state: ClubMembershipPresentationState.outsiderRequest, statusBadge: 'REQUEST REQUIRED', badgeType: PresentationBadgeType.cyan, statusHeadline: 'Request Admission', statusDescription: 'Membership requires review and approval from club leadership.', primaryAction: ClubMembershipAction.requestToJoin, primaryActionLabel: 'Request to Join', primaryActionIcon: Icons.send_outlined, isActionable: true, ); case ClubAdmissionPolicy.inviteOnly: return const ClubMembershipPresentation( state: ClubMembershipPresentationState.outsiderInviteOnly, statusBadge: 'INVITE ONLY', badgeType: PresentationBadgeType.neutral, statusHeadline: 'Invite-Only Club', statusDescription: 'This club is invite-only. You must receive an invitation from leadership to join.', isActionable: false, ); } } }