import Combine
import Foundation

// MARK: - GroupJoinViewModel

/// ViewModel for joining a group via invite string.
@MainActor
final class GroupJoinViewModel: ObservableObject {
    @Published var inviteString: String = ""
    @Published var isJoining: Bool = false
    @Published var isChecking: Bool = false
    @Published var errorMessage: String?
    @Published var joinedRoute: ChatRoute?

    /// Preview info after parsing invite.
    @Published var parsedTitle: String?
    @Published var parsedDescription: String?
    @Published var memberCount: Int?
    @Published var inviteStatus: GroupStatus?

    var hasParsedInvite: Bool { parsedTitle != nil }

    func parseInvite() {
        let trimmed = inviteString.trimmingCharacters(in: .whitespacesAndNewlines)
        guard let parsed = GroupRepository.shared.parseInviteString(trimmed) else {
            parsedTitle = nil
            parsedDescription = nil
            memberCount = nil
            inviteStatus = nil
            // Show error if user typed something but it didn't parse.
            if !trimmed.isEmpty {
                errorMessage = "Invalid invite link"
            } else {
                errorMessage = nil
            }
            return
        }
        errorMessage = nil
        parsedTitle = parsed.title
        parsedDescription = parsed.description.isEmpty ? nil : parsed.description
    }

    func checkStatus() async {
        guard let parsed = GroupRepository.shared.parseInviteString(
            inviteString.trimmingCharacters(in: .whitespacesAndNewlines)
        ) else { return }

        isChecking = true
        do {
            let result = try await GroupService.shared.checkInviteStatus(groupId: parsed.groupId)
            memberCount = result.memberCount
            inviteStatus = result.status
        } catch {
            errorMessage = error.localizedDescription
        }
        isChecking = false
    }

    func joinGroup() async {
        let trimmed = inviteString.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !trimmed.isEmpty else { return }

        isJoining = true
        errorMessage = nil

        do {
            let route = try await GroupService.shared.joinGroup(inviteString: trimmed)
            joinedRoute = route
        } catch let error as GroupService.GroupError {
            switch error {
            case .joinRejected(let status):
                switch status {
                case .banned: errorMessage = "You are banned from this group"
                case .invalid: errorMessage = "This group no longer exists"
                default: errorMessage = error.localizedDescription
                }
            default:
                errorMessage = error.localizedDescription
            }
        } catch {
            errorMessage = error.localizedDescription
        }

        isJoining = false
    }
}
