//
//  ProfileSpaceView.swift
//  suixinkan
//
//  Created by Codex on 2026/6/29.
//

import PhotosUI
import SwiftUI
import UIKit

/// 个人空间配置页面，承接首页“空间设置”入口。
struct ProfileSpaceView: View {
    @EnvironmentObject private var accountContext: AccountContext
    @EnvironmentObject private var router: RouterPath
    @EnvironmentObject private var toastCenter: ToastCenter
    @Environment(\.profileAPI) private var profileAPI
    @Environment(\.scheduleAPI) private var scheduleAPI
    @Environment(\.ossUploadService) private var ossUploadService
    @Environment(\.accountSnapshotStore) private var snapshotStore
    @Environment(\.globalLoading) private var globalLoading
    @Environment(\.openURL) private var openURL

    @StateObject private var viewModel = ProfileSpaceViewModel()
    @State private var pickedAvatarItem: PhotosPickerItem?
    @State private var attrInput = ""
    @State private var shootInput = ""
    @State private var deviceInput = ""
    @State private var selectedDate = Date()
    @State private var deleteTarget: ProfileSpaceDeleteTarget?
    @State private var appearedOnce = false

    private var scenicId: Int? {
        accountContext.currentScenic?.id
    }

    private var selectedDateKey: String {
        selectedDate.scheduleDayText
    }

    private var selectedSchedules: [ScheduleItem] {
        viewModel.scheduleMap[selectedDateKey] ?? []
    }

    var body: some View {
        Group {
            if scenicId == nil {
                AppContentUnavailableView("缺少景区", systemImage: "person.crop.circle.badge.exclamationmark", description: Text("请选择景区后再配置个人空间。"))
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    .background(Color(hex: 0xF5F7FA).ignoresSafeArea())
            } else {
                ScrollView {
                    VStack(spacing: AppMetrics.Spacing.medium) {
                        profileCard
                        labelCard
                        businessTimeCard
                        deviceCard
                        orderStatusCard
                        scheduleCard
                    }
                    .padding(AppMetrics.Spacing.medium)
                    .padding(.bottom, 78)
                }
                .background(Color(hex: 0xF5F7FA).ignoresSafeArea())
                .refreshable { await reload(showLoading: false) }
                .safeAreaInset(edge: .bottom) {
                    saveBar
                }
            }
        }
        .navigationTitle("个人空间配置")
        .navigationBarTitleDisplayMode(.inline)
        .task(id: scenicId) {
            await reload(showLoading: true)
        }
        .onAppear {
            guard appearedOnce else {
                appearedOnce = true
                return
            }
            Task { await reload(showLoading: false) }
        }
        .onChange(of: pickedAvatarItem) { item in
            Task { await prepareAvatarImage(from: item) }
        }
        .alert(item: $deleteTarget) { target in
            Alert(
                title: Text(target.title),
                message: Text(target.message),
                primaryButton: .destructive(Text("删除")) {
                    delete(target)
                },
                secondaryButton: .cancel(Text("取消"))
            )
        }
    }

    private var profileCard: some View {
        sectionCard {
            HStack(alignment: .top, spacing: AppMetrics.Spacing.medium) {
                avatarPicker
                VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
                    Text("姓名: \(viewModel.realName.isEmpty ? "--" : viewModel.realName)")
                        .font(.system(size: AppMetrics.FontSize.subheadline))
                        .foregroundStyle(AppDesign.textSecondary)
                    TextField("请输入昵称", text: $viewModel.nickname)
                        .font(.system(size: AppMetrics.FontSize.body, weight: .semibold))
                        .appInputFieldStyle(cornerRadius: 8, minHeight: 42)
                    TextField("请输入简介", text: $viewModel.introduction, axis: .vertical)
                        .lineLimit(2...5)
                        .font(.system(size: AppMetrics.FontSize.subheadline))
                        .appInputFieldStyle(cornerRadius: 8, minHeight: 78)
                    certificationTags
                }
            }
        }
    }

    private var avatarPicker: some View {
        PhotosPicker(selection: $pickedAvatarItem, matching: .images) {
            avatarPreview
                .frame(width: 92, height: 92)
                .clipShape(Circle())
                .overlay {
                    Circle().stroke(.white, lineWidth: 3)
                }
                .overlay(alignment: .bottomTrailing) {
                    Image(systemName: "camera.fill")
                        .font(.system(size: 12, weight: .semibold))
                        .foregroundStyle(.white)
                        .frame(width: 26, height: 26)
                        .background(AppDesign.primary, in: Circle())
                        .overlay { Circle().stroke(.white, lineWidth: 2) }
                }
                .overlay {
                    if let progress = viewModel.avatarUploadProgress {
                        ZStack {
                            Circle().fill(.black.opacity(0.34))
                            Text("\(progress)%")
                                .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                                .foregroundStyle(.white)
                        }
                    }
                }
        }
        .buttonStyle(.plain)
        .accessibilityLabel("头像")
    }

    @ViewBuilder
    private var avatarPreview: some View {
        if let data = viewModel.pendingAvatarData, let image = UIImage(data: data) {
            Image(uiImage: image)
                .resizable()
                .scaledToFill()
        } else {
            RemoteAvatarImage(urlString: viewModel.avatarURL)
        }
    }

    @ViewBuilder
    private var certificationTags: some View {
        if !viewModel.scenicCertification.isEmpty {
            FlowLayout(spacing: 6, lineSpacing: 6) {
                ForEach(viewModel.scenicCertification, id: \.self) { tag in
                    Text(tag)
                        .font(.system(size: AppMetrics.FontSize.caption))
                        .foregroundStyle(AppDesign.warning)
                        .padding(.horizontal, 6)
                        .padding(.vertical, 3)
                        .background(Color(hex: 0xFFF0E2), in: RoundedRectangle(cornerRadius: 4))
                }
            }
        }
    }

    private var labelCard: some View {
        sectionCard {
            VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
                Text("标签")
                    .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                    .foregroundStyle(AppDesign.textPrimary)
                chipEditor(labels: viewModel.attrLabels, input: $attrInput, placeholder: "添加标签") { value in
                    try viewModel.addAttrLabel(value)
                } remove: { value in
                    deleteTarget = .attrLabel(value)
                }

                Text("拍摄说明")
                    .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                    .foregroundStyle(AppDesign.textPrimary)
                    .padding(.top, AppMetrics.Spacing.xSmall)
                chipEditor(labels: viewModel.shootLabels, input: $shootInput, placeholder: "添加拍摄说明") { value in
                    try viewModel.addShootLabel(value)
                } remove: { value in
                    deleteTarget = .shootLabel(value)
                }

                Text("每个标签最多20个字符,最多8个标签")
                    .font(.system(size: AppMetrics.FontSize.caption))
                    .foregroundStyle(AppDesign.placeholder)
            }
        }
    }

    private var businessTimeCard: some View {
        sectionCard {
            VStack(alignment: .leading, spacing: AppMetrics.Spacing.medium) {
                sectionTitle("营业时间")
                timeRow(title: "工作日营业时间", start: $viewModel.businessStartTime, end: $viewModel.businessEndTime)
                timeRow(title: "法定节假日营业时间", start: $viewModel.holidayStartTime, end: $viewModel.holidayEndTime)
            }
        }
    }

    private var deviceCard: some View {
        sectionCard {
            VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
                sectionTitle("相机设备")
                FlowLayout(spacing: 8, lineSpacing: 8) {
                    ForEach(viewModel.cameraDevices, id: \.self) { device in
                        removableChip(title: device, tint: AppDesign.textSecondary) {
                            deleteTarget = .device(device)
                        }
                    }
                }
                HStack(spacing: AppMetrics.Spacing.small) {
                    TextField("请输入设备名", text: $deviceInput)
                        .appInputFieldStyle(cornerRadius: 8, minHeight: 42)
                    Button {
                        viewModel.addCameraDevice(deviceInput)
                        deviceInput = ""
                    } label: {
                        Image(systemName: "plus")
                            .font(.system(size: AppMetrics.FontSize.body, weight: .semibold))
                            .frame(width: 44, height: 42)
                    }
                    .buttonStyle(.borderedProminent)
                    .disabled(deviceInput.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
                }
            }
        }
    }

    private var orderStatusCard: some View {
        sectionCard {
            VStack(alignment: .leading, spacing: AppMetrics.Spacing.medium) {
                sectionTitle("接单状态")
                LazyVGrid(columns: Array(repeating: GridItem(.flexible(), spacing: AppMetrics.Spacing.small), count: 2), spacing: AppMetrics.Spacing.small) {
                    ForEach(ProfileSpaceOrderStatus.allCases) { status in
                        Button {
                            viewModel.acceptOrderStatus = status.rawValue
                        } label: {
                            Text(status.title)
                                .font(.system(size: AppMetrics.FontSize.subheadline, weight: .medium))
                                .foregroundStyle(viewModel.acceptOrderStatus == status.rawValue ? .white : AppDesign.textSecondary)
                                .frame(maxWidth: .infinity)
                                .frame(height: 48)
                                .background(
                                    viewModel.acceptOrderStatus == status.rawValue ? AppDesign.primary : Color.white,
                                    in: RoundedRectangle(cornerRadius: 8)
                                )
                                .overlay {
                                    RoundedRectangle(cornerRadius: 8)
                                        .stroke(viewModel.acceptOrderStatus == status.rawValue ? AppDesign.primary : Color(hex: 0xD7DEE8), lineWidth: 1)
                                }
                        }
                        .buttonStyle(.plain)
                    }
                }
            }
        }
    }

    private var scheduleCard: some View {
        sectionCard {
            VStack(alignment: .leading, spacing: AppMetrics.Spacing.medium) {
                HStack {
                    sectionTitle("日程安排")
                    Spacer()
                    NavigationLink(value: AppRoute.home(.scheduleAdd)) {
                        Label("添加日程", systemImage: "plus")
                            .font(.system(size: AppMetrics.FontSize.subheadline, weight: .medium))
                    }
                }
                weekSelector
                HStack {
                    Text(selectedDate.scheduleDayText)
                        .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                        .foregroundStyle(AppDesign.textPrimary)
                    Spacer()
                }
                if selectedSchedules.isEmpty {
                    AppContentUnavailableView("该日无日程", systemImage: "calendar")
                        .frame(minHeight: 120)
                } else {
                    VStack(spacing: AppMetrics.Spacing.small) {
                        ForEach(selectedSchedules) { item in
                            scheduleItemCard(item)
                        }
                    }
                }
            }
        }
    }

    private var weekSelector: some View {
        HStack(spacing: 0) {
            ForEach(nextSevenDays, id: \.scheduleDayText) { date in
                Button {
                    selectedDate = date
                } label: {
                    VStack(spacing: AppMetrics.Spacing.xSmall) {
                        Text(weekdayText(for: date))
                            .font(.system(size: AppMetrics.FontSize.caption))
                        Text(dayText(for: date))
                            .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                            .frame(width: 34, height: 34)
                            .background(isSelected(date) ? AppDesign.primary : Color(hex: 0xF3F5F8), in: RoundedRectangle(cornerRadius: 8))
                            .foregroundStyle(isSelected(date) ? .white : AppDesign.textSecondary)
                    }
                    .frame(maxWidth: .infinity)
                }
                .buttonStyle(.plain)
            }
        }
    }

    private var saveBar: some View {
        VStack(spacing: 0) {
            if let error = viewModel.errorMessage {
                Text(error)
                    .font(.system(size: AppMetrics.FontSize.caption))
                    .foregroundStyle(Color(hex: 0xE5484D))
                    .frame(maxWidth: .infinity, alignment: .leading)
                    .padding(.horizontal, AppMetrics.Spacing.medium)
                    .padding(.top, AppMetrics.Spacing.small)
            }
            Button {
                Task { await save() }
            } label: {
                HStack {
                    if viewModel.saving {
                        ProgressView()
                            .tint(.white)
                    }
                    Text(viewModel.saving ? "保存中..." : "保存")
                        .font(.system(size: AppMetrics.FontSize.body, weight: .semibold))
                }
                .foregroundStyle(.white)
                .frame(maxWidth: .infinity)
                .frame(height: AppMetrics.ControlSize.primaryButtonHeight)
                .background(viewModel.hasChanges && !viewModel.saving ? AppDesign.primary : Color(hex: 0xB6BECA), in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.button))
            }
            .buttonStyle(.plain)
            .disabled(!viewModel.hasChanges || viewModel.saving)
            .padding(AppMetrics.Spacing.medium)
        }
        .background(.white)
        .overlay(alignment: .top) {
            Rectangle()
                .fill(Color(hex: 0xE5E7EB))
                .frame(height: 0.5)
        }
    }

    /// 构造通用白色分组卡片。
    private func sectionCard<Content: View>(@ViewBuilder content: () -> Content) -> some View {
        VStack(alignment: .leading, spacing: 0) {
            content()
        }
        .padding(AppMetrics.Spacing.medium)
        .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
    }

    /// 构造分组标题。
    private func sectionTitle(_ title: String) -> some View {
        Text(title)
            .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
            .foregroundStyle(AppDesign.textPrimary)
    }

    /// 构造标签编辑器。
    private func chipEditor(
        labels: [String],
        input: Binding<String>,
        placeholder: String,
        add: @escaping (String) throws -> Void,
        remove: @escaping (String) -> Void
    ) -> some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
            FlowLayout(spacing: 8, lineSpacing: 8) {
                ForEach(labels, id: \.self) { label in
                    removableChip(title: label, tint: AppDesign.primary) {
                        remove(label)
                    }
                }
            }
            HStack(spacing: AppMetrics.Spacing.small) {
                TextField(placeholder, text: input)
                    .appInputFieldStyle(cornerRadius: 8, minHeight: 42)
                Button {
                    do {
                        try add(input.wrappedValue)
                        input.wrappedValue = ""
                    } catch {
                        viewModel.errorMessage = error.localizedDescription
                    }
                } label: {
                    Text("添加")
                        .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                        .frame(width: 56, height: 42)
                }
                .buttonStyle(.borderedProminent)
                .disabled(input.wrappedValue.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
            }
        }
    }

    /// 构造可删除标签。
    private func removableChip(title: String, tint: Color, onRemove: @escaping () -> Void) -> some View {
        HStack(spacing: 4) {
            Text(title)
                .font(.system(size: AppMetrics.FontSize.caption))
            Button(action: onRemove) {
                Image(systemName: "xmark")
                    .font(.system(size: 10, weight: .bold))
            }
            .buttonStyle(.plain)
        }
        .foregroundStyle(tint)
        .padding(.horizontal, 8)
        .padding(.vertical, 5)
        .background(tint.opacity(0.1), in: RoundedRectangle(cornerRadius: 5))
    }

    /// 构造营业时间行。
    private func timeRow(title: String, start: Binding<Date?>, end: Binding<Date?>) -> some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.xSmall) {
            Text(title)
                .font(.system(size: AppMetrics.FontSize.subheadline))
                .foregroundStyle(AppDesign.textSecondary)
            HStack(spacing: AppMetrics.Spacing.small) {
                optionalTimePicker("开始", selection: start)
                Text("至")
                    .font(.system(size: AppMetrics.FontSize.subheadline))
                    .foregroundStyle(AppDesign.textSecondary)
                optionalTimePicker("结束", selection: end)
            }
        }
    }

    /// 构造可为空的时间选择器。
    private func optionalTimePicker(_ title: String, selection: Binding<Date?>) -> some View {
        VStack(alignment: .leading, spacing: 4) {
            DatePicker(
                title,
                selection: Binding(
                    get: { selection.wrappedValue ?? defaultTime },
                    set: { selection.wrappedValue = $0 }
                ),
                displayedComponents: .hourAndMinute
            )
            .labelsHidden()
            .frame(maxWidth: .infinity, alignment: .leading)
            Text(selection.wrappedValue?.profileSpaceHourMinuteText ?? "未设置")
                .font(.system(size: AppMetrics.FontSize.caption))
                .foregroundStyle(selection.wrappedValue == nil ? Color(hex: 0xE5484D) : AppDesign.textSecondary)
        }
    }

    /// 构造日程卡片。
    private func scheduleItemCard(_ item: ScheduleItem) -> some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.xSmall) {
            HStack(spacing: AppMetrics.Spacing.small) {
                Text("\(item.startTime) - \(item.endTime) \(item.name)")
                    .font(.system(size: AppMetrics.FontSize.subheadline, weight: .medium))
                    .foregroundStyle(AppDesign.textPrimary)
                    .lineLimit(1)
                Spacer()
                Button(role: .destructive) {
                    deleteTarget = .schedule(item)
                } label: {
                    Text("删除")
                        .font(.system(size: AppMetrics.FontSize.subheadline))
                }
            }
            if let orderNumber = item.orderNumber, !orderNumber.isEmpty {
                scheduleText("订单号: \(orderNumber)")
            }
            if let phone = item.userPhone, !phone.isEmpty {
                HStack(spacing: AppMetrics.Spacing.medium) {
                    scheduleText("客户手机号: \(maskedPhone(phone))")
                    Button("拨打") {
                        if let url = URL(string: "tel:\(phone)") {
                            openURL(url)
                        }
                    }
                    .font(.system(size: AppMetrics.FontSize.subheadline))
                }
            }
            if !item.remark.isEmpty {
                scheduleText("备注信息: \(item.remark)")
            }
        }
        .padding(AppMetrics.Spacing.small)
        .background(Color(hex: 0xF8FAFC), in: RoundedRectangle(cornerRadius: 8))
    }

    /// 构造日程辅助文本。
    private func scheduleText(_ text: String) -> some View {
        Text(text)
            .font(.system(size: AppMetrics.FontSize.subheadline))
            .foregroundStyle(AppDesign.textSecondary)
            .lineLimit(2)
    }

    /// 重新加载页面数据。
    private func reload(showLoading: Bool) async {
        await globalLoading.withOptionalLoading(showLoading && scenicId != nil) {
            await viewModel.load(api: profileAPI, scenicId: scenicId)
        }
    }

    /// 读取 PhotosPicker 选中的头像图片。
    private func prepareAvatarImage(from item: PhotosPickerItem?) async {
        guard let item else { return }
        do {
            guard let data = try await item.loadTransferable(type: Data.self) else { return }
            try viewModel.prepareAvatarImage(data: data)
        } catch {
            viewModel.errorMessage = error.localizedDescription
        }
    }

    /// 保存当前空间配置。
    private func save() async {
        do {
            try await globalLoading.withLoading {
                try await viewModel.save(api: profileAPI, uploader: ossUploadService, scenicId: scenicId)
            }
            if let profile = viewModel.accountProfileFallback(accountContext.profile) {
                accountContext.replaceProfile(profile)
                saveSnapshotProfile(profile)
            }
            toastCenter.show("保存成功")
        } catch {
            viewModel.errorMessage = error.localizedDescription
            toastCenter.show(error.localizedDescription)
        }
    }

    /// 执行删除确认目标。
    private func delete(_ target: ProfileSpaceDeleteTarget) {
        switch target {
        case .attrLabel(let label):
            viewModel.removeAttrLabel(label)
        case .shootLabel(let label):
            viewModel.removeShootLabel(label)
        case .device(let device):
            viewModel.removeCameraDevice(device)
        case .schedule(let item):
            Task {
                await globalLoading.withLoading {
                    await viewModel.deleteSchedule(item: item, profileAPI: profileAPI, scheduleAPI: scheduleAPI, scenicId: scenicId)
                }
            }
        }
    }

    /// 更新账号快照里的展示资料。
    private func saveSnapshotProfile(_ profile: AccountProfile) {
        let existing = snapshotStore.load()
        snapshotStore.save(
            AccountSnapshot(
                profile: profile,
                accountType: accountContext.accountType ?? existing?.accountType,
                businessUserId: existing?.businessUserId,
                currentAccountDisplayTitle: accountContext.currentAccountDisplayTitle ?? existing?.currentAccountDisplayTitle,
                currentRoleCode: existing?.currentRoleCode,
                scenicScopes: accountContext.scenicScopes,
                storeScopes: accountContext.storeScopes,
                currentScenicId: accountContext.currentScenic?.id,
                currentStoreId: accountContext.currentStore?.id
            )
        )
    }

    private var defaultTime: Date {
        Calendar.current.date(from: DateComponents(hour: 9, minute: 0)) ?? Date()
    }

    private var nextSevenDays: [Date] {
        (0..<7).compactMap { Calendar.current.date(byAdding: .day, value: $0, to: Date()) }
    }

    private func isSelected(_ date: Date) -> Bool {
        date.scheduleDayText == selectedDate.scheduleDayText
    }

    private func weekdayText(for date: Date) -> String {
        let symbols = ["日", "一", "二", "三", "四", "五", "六"]
        let index = Calendar.current.component(.weekday, from: date) - 1
        return symbols[max(0, min(index, symbols.count - 1))]
    }

    private func dayText(for date: Date) -> String {
        "\(Calendar.current.component(.day, from: date))"
    }

    private func maskedPhone(_ phone: String) -> String {
        guard phone.count >= 11 else { return phone }
        let prefix = phone.prefix(3)
        let suffix = phone.suffix(4)
        return "\(prefix)****\(suffix)"
    }
}

/// 个人空间页面删除确认目标。
private enum ProfileSpaceDeleteTarget: Identifiable {
    case attrLabel(String)
    case shootLabel(String)
    case device(String)
    case schedule(ScheduleItem)

    var id: String {
        switch self {
        case .attrLabel(let label): "attr-\(label)"
        case .shootLabel(let label): "shoot-\(label)"
        case .device(let device): "device-\(device)"
        case .schedule(let item): "schedule-\(item.id)"
        }
    }

    var title: String {
        switch self {
        case .attrLabel: "删除标签"
        case .shootLabel: "删除拍摄说明"
        case .device: "删除设备"
        case .schedule: "删除日程"
        }
    }

    var message: String {
        switch self {
        case .attrLabel(let label):
            "您确定要删除\(label)标签吗?"
        case .shootLabel(let label):
            "您确定要删除\(label)拍摄说明吗?"
        case .device(let device):
            "您确定要删除\(device)设备吗?"
        case .schedule:
            "您确定要删除该日程吗?"
        }
    }
}

/// 简单流式布局，用于标签自动换行。
private struct FlowLayout: Layout {
    let spacing: CGFloat
    let lineSpacing: CGFloat

    /// 计算流式布局所需尺寸。
    func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
        let maxWidth = proposal.width ?? 0
        let rows = makeRows(maxWidth: maxWidth, subviews: subviews)
        let width = rows.map(\.width).max() ?? 0
        let height = rows.reduce(CGFloat.zero) { $0 + $1.height } + lineSpacing * CGFloat(max(0, rows.count - 1))
        return CGSize(width: width, height: height)
    }

    /// 摆放子视图。
    func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) {
        let rows = makeRows(maxWidth: bounds.width, subviews: subviews)
        var y = bounds.minY
        for row in rows {
            var x = bounds.minX
            for item in row.items {
                subviews[item.index].place(
                    at: CGPoint(x: x, y: y),
                    proposal: ProposedViewSize(width: item.size.width, height: item.size.height)
                )
                x += item.size.width + spacing
            }
            y += row.height + lineSpacing
        }
    }

    /// 根据最大宽度拆分布局行。
    private func makeRows(maxWidth: CGFloat, subviews: Subviews) -> [FlowRow] {
        guard maxWidth > 0 else {
            return subviews.enumerated().map { index, subview in
                let size = subview.sizeThatFits(.unspecified)
                return FlowRow(items: [FlowItem(index: index, size: size)], width: size.width, height: size.height)
            }
        }

        var rows: [FlowRow] = []
        var currentItems: [FlowItem] = []
        var currentWidth: CGFloat = 0
        var currentHeight: CGFloat = 0

        for (index, subview) in subviews.enumerated() {
            let size = subview.sizeThatFits(.unspecified)
            let nextWidth = currentItems.isEmpty ? size.width : currentWidth + spacing + size.width
            if nextWidth > maxWidth, !currentItems.isEmpty {
                rows.append(FlowRow(items: currentItems, width: currentWidth, height: currentHeight))
                currentItems = [FlowItem(index: index, size: size)]
                currentWidth = size.width
                currentHeight = size.height
            } else {
                currentItems.append(FlowItem(index: index, size: size))
                currentWidth = nextWidth
                currentHeight = max(currentHeight, size.height)
            }
        }

        if !currentItems.isEmpty {
            rows.append(FlowRow(items: currentItems, width: currentWidth, height: currentHeight))
        }
        return rows
    }

    private struct FlowItem {
        let index: Int
        let size: CGSize
    }

    private struct FlowRow {
        let items: [FlowItem]
        let width: CGFloat
        let height: CGFloat
    }
}
