//
//  SectionEditorView.swift
//  Yattee
//
//  View for editing buttons in a player controls section (top or bottom).
//

import SwiftUI

/// View for editing buttons in a specific section of the player controls.
struct SectionEditorView: View {
    let sectionType: LayoutSectionType
    @Bindable var viewModel: PlayerControlsSettingsViewModel

    // Local state for immediate UI updates
    @State private var buttons: [ControlButtonConfiguration] = []
    @State private var availableTypes: [ControlButtonType] = []
    @State private var controlBarTheme: ControlsTheme = .system

    var body: some View {
        List {
            // Section preview
            SectionPreviewView(
                sectionType: sectionType,
                section: LayoutSection(buttons: buttons),
                isLandscape: viewModel.isPreviewingLandscape,
                fontStyle: viewModel.currentLayout.globalSettings.fontStyle,
                buttonBackground: viewModel.currentLayout.globalSettings.buttonBackground,
                theme: viewModel.currentLayout.globalSettings.theme
            )
            .listRowInsets(EdgeInsets())
            .listRowBackground(Color.clear)

            // Orientation toggle; macOS has no portrait/landscape distinction
            #if os(iOS)
            Picker(
                String(localized: "settings.playerControls.previewOrientation"),
                selection: $viewModel.isPreviewingLandscape
            ) {
                Text(String(localized: "settings.playerControls.portrait"))
                    .tag(false)
                Text(String(localized: "settings.playerControls.landscape"))
                    .tag(true)
            }
            .pickerStyle(.segmented)
            .listRowBackground(Color.clear)
            #endif

            // The macOS bar draws a glass capsule whose appearance can be forced.
            #if os(macOS)
            if sectionType == .bottom {
                Section {
                    Picker(
                        String(localized: "settings.playerControls.glassBackground", defaultValue: "Glass Background"),
                        selection: $controlBarTheme
                    ) {
                        ForEach(ControlsTheme.allCases, id: \.self) { theme in
                            Text(glassBackgroundLabel(for: theme)).tag(theme)
                        }
                    }
                    .disabled(!viewModel.canEditActivePreset)
                    .onChange(of: controlBarTheme) { _, newTheme in
                        guard newTheme != viewModel.currentLayout.globalSettings.controlBarTheme else { return }
                        viewModel.updateGlobalSettingsSync { $0.controlBarTheme = newTheme }
                    }
                } header: {
                    Text(String(localized: "settings.playerControls.appearance"))
                }
            }
            #endif

            // Added buttons
            Section {
                ForEach(buttons) { button in
                    NavigationLink {
                        ButtonConfigurationView(
                            buttonID: button.id,
                            sectionType: sectionType,
                            viewModel: viewModel
                        )
                    } label: {
                        ButtonRow(configuration: button)
                    }
                    .contextMenu {
                        if viewModel.canEditActivePreset {
                            Button(role: .destructive) {
                                removeButton(id: button.id)
                            } label: {
                                Label(
                                    String(localized: "settings.playerControls.delete"),
                                    systemImage: "trash"
                                )
                            }
                        }
                    }
                }
                .onMove { source, destination in
                    // Update local state immediately
                    buttons.move(fromOffsets: source, toOffset: destination)
                    // Sync to view model
                    viewModel.moveButtonSync(
                        fromOffsets: source,
                        toOffset: destination,
                        in: sectionType
                    )
                }
                .onDelete { indexSet in
                    let buttonIDs = indexSet.map { buttons[$0].id }
                    for id in buttonIDs {
                        removeButton(id: id)
                    }
                }
            } header: {
                Text(String(localized: "settings.playerControls.addedButtons"))
            }

            // Available buttons
            Section {
                ForEach(availableTypes, id: \.self) { buttonType in
                    Button {
                        addButton(buttonType)
                    } label: {
                        HStack {
                            Image(systemName: buttonType.systemImage)
                                .frame(width: 24)
                                .foregroundStyle(.tint)

                            Text(buttonType.displayName)
                                .foregroundStyle(.primary)

                            Spacer()

                            Image(systemName: "plus.circle.fill")
                                .foregroundStyle(.tint)
                        }
                    }
                    .buttonStyle(.plain)
                }
            } header: {
                Text(String(localized: "settings.playerControls.availableButtons"))
            } footer: {
                Text(String(localized: "settings.playerControls.availableButtonsFooter"))
            }
        }
        .navigationTitle(sectionTitle)
        #if os(iOS)
        .navigationBarTitleDisplayMode(.inline)
        #endif
        .opaqueSettingsFormBackground()
        .toolbar {
            #if os(iOS)
            EditButton()
            #endif
        }
        .onAppear {
            syncFromViewModel()
        }
        .onChange(of: viewModel.activePreset?.layout) { _, _ in
            syncFromViewModel()
        }
    }

    // MARK: - Helpers

    private func syncFromViewModel() {
        guard let preset = viewModel.activePreset else { return }
        switch sectionType {
        case .top:
            buttons = preset.layout.topSection.buttons
        case .bottom:
            buttons = preset.layout.bottomSection.buttons
        }
        controlBarTheme = preset.layout.globalSettings.controlBarTheme
        syncAvailableTypes()
    }

    private func syncAvailableTypes() {
        let usedTypes = Set(buttons.map(\.buttonType))
        availableTypes = ControlButtonType.availableForHorizontalSections.filter { buttonType in
            // Spacer can be added multiple times
            buttonType == .spacer || !usedTypes.contains(buttonType)
        }
    }

    private func removeButton(id: UUID) {
        // Update local state immediately
        buttons.removeAll { $0.id == id }
        // Sync to view model
        viewModel.removeButtonSync(id, from: sectionType)
        // Update available types
        syncAvailableTypes()
    }

    private func addButton(_ buttonType: ControlButtonType) {
        // Create new config and add to local state immediately
        let config = ControlButtonConfiguration.defaultConfiguration(for: buttonType)
        buttons.append(config)
        // Update available types
        syncAvailableTypes()
        // Sync to view model
        viewModel.addButtonSync(buttonType, to: sectionType)
    }

    #if os(macOS)
    private func glassBackgroundLabel(for theme: ControlsTheme) -> String {
        switch theme {
        case .system:
            return String(localized: "controls.theme.auto", defaultValue: "Auto")
        case .light, .dark:
            return theme.displayName
        }
    }
    #endif

    private var sectionTitle: String {
        switch sectionType {
        case .top:
            return String(localized: "settings.playerControls.topButtons")
        case .bottom:
            #if os(macOS)
            return String(localized: "settings.playerControls.controlBar", defaultValue: "Control Bar")
            #else
            return String(localized: "settings.playerControls.bottomButtons")
            #endif
        }
    }
}

// MARK: - Button Row

private struct ButtonRow: View {
    let configuration: ControlButtonConfiguration

    var body: some View {
        HStack(spacing: 12) {
            Image(systemName: configuration.buttonType.systemImage)
                .frame(width: 24)
                .foregroundStyle(.secondary)

            VStack(alignment: .leading, spacing: 2) {
                Text(configuration.buttonType.displayName)

                #if os(iOS)
                if configuration.visibilityMode != .both {
                    Text(configuration.visibilityMode.displayName)
                        .font(.caption)
                        .foregroundStyle(.secondary)
                }
                #endif
            }

            Spacer()
        }
    }
}

// MARK: - Section Preview

private struct SectionPreviewView: View {
    let sectionType: LayoutSectionType
    let section: LayoutSection
    let isLandscape: Bool
    let fontStyle: ControlsFontStyle
    let buttonBackground: ButtonBackgroundStyle
    let theme: ControlsTheme

    private let buttonSize: CGFloat = 20
    private let buttonSpacing: CGFloat = 8
    private let barHeight: CGFloat = 50

    var body: some View {
        GeometryReader { geometry in
            let containerWidth = geometry.size.width

            if isLandscape {
                // Landscape: use full container width, or scroll if content is wider
                ScrollView(.horizontal, showsIndicators: false) {
                    barContent(minWidth: containerWidth, height: barHeight)
                }
                .frame(height: barHeight)
            } else {
                // Portrait: full width horizontal bar
                barContent(minWidth: containerWidth, height: barHeight)
            }
        }
        .frame(height: barHeight)
        .padding(.horizontal)
        .padding(.vertical, 8)
        .modifier(PreviewThemeModifier(theme: theme))
    }

    @ViewBuilder
    private func barContent(minWidth: CGFloat, height: CGFloat) -> some View {
        HStack(spacing: buttonSpacing) {
            ForEach(section.visibleButtons(isWideLayout: isLandscape)) { button in
                PreviewButtonView(
                    configuration: button,
                    size: buttonSize,
                    isLandscape: isLandscape,
                    fontStyle: fontStyle,
                    buttonBackground: buttonBackground
                )
            }
        }
        .padding(.horizontal, 12)
        .frame(minWidth: minWidth, minHeight: height)
        .background(
            Image("PlayerControlsPreviewBackground")
                .resizable()
                .scaledToFill()
                .overlay {
                    LinearGradient(
                        colors: sectionType == .top
                            ? [.black.opacity(0.7), .clear]
                            : [.clear, .black.opacity(0.7)],
                        startPoint: .top,
                        endPoint: .bottom
                    )
                }
        )
        .clipShape(RoundedRectangle(cornerRadius: 8))
    }
}

private struct PreviewButtonView: View {
    let configuration: ControlButtonConfiguration
    let size: CGFloat
    let isLandscape: Bool
    let fontStyle: ControlsFontStyle
    let buttonBackground: ButtonBackgroundStyle

    /// Whether this button should show a glass background.
    private var hasBackground: Bool { buttonBackground.glassStyle != nil }

    /// Frame size - slightly larger when backgrounds are enabled.
    private var frameSize: CGFloat { hasBackground ? size * 1.7 : size * 1.5 }

    var body: some View {
        Group {
            if configuration.buttonType == .spacer {
                if let settings = configuration.settings,
                   case .spacer(let spacerSettings) = settings,
                   spacerSettings.isFlexible {
                    Spacer()
                } else {
                    Rectangle()
                        .fill(Color.clear)
                        .frame(width: spacerWidth)
                }
            } else if configuration.buttonType == .timeDisplay {
                Text(verbatim: "0:00 / 3:45")
                    .font(fontStyle.font(size: size * 0.6, weight: .medium))
                    .foregroundStyle(.white.opacity(0.9))
            } else if configuration.buttonType == .brightness || configuration.buttonType == .volume {
                // Slider buttons - show based on behavior
                sliderPreview
            } else if configuration.buttonType == .seek {
                // Seek button - show dynamic icon based on settings
                seekButtonContent
            } else if configuration.buttonType == .titleAuthor {
                // Title/Author button - show preview matching actual layout
                titleAuthorPreview
            } else {
                // Regular button
                regularButtonContent
            }
        }
    }

    // MARK: - Seek Button Content

    @ViewBuilder
    private var seekButtonContent: some View {
        let seekSettings = configuration.seekSettings ?? SeekSettings()
        if let glassStyle = buttonBackground.glassStyle {
            Image(systemName: seekSettings.systemImage)
                .font(.system(size: size))
                .foregroundStyle(.white.opacity(0.9))
                .frame(width: frameSize, height: frameSize)
                .glassBackground(glassStyle, in: .circle, fallback: .ultraThinMaterial)
        } else {
            Image(systemName: seekSettings.systemImage)
                .font(.system(size: size))
                .foregroundStyle(.white.opacity(0.9))
                .frame(width: frameSize, height: frameSize)
        }
    }

    // MARK: - Title/Author Preview

    @ViewBuilder
    private var titleAuthorPreview: some View {
        let settings = configuration.titleAuthorSettings ?? TitleAuthorSettings()
        let avatarSize = size * 1.4

        HStack(spacing: 6) {
            // Avatar placeholder
            if settings.showSourceImage {
                Circle()
                    .fill(.white.opacity(0.3))
                    .frame(width: avatarSize, height: avatarSize)
                    .overlay {
                        Text(verbatim: "Y")
                            .font(.system(size: size * 0.7, weight: .semibold))
                            .foregroundStyle(.white.opacity(0.8))
                    }
            }

            // Title and author stack
            if settings.showTitle || settings.showSourceName {
                VStack(alignment: .leading, spacing: 1) {
                    if settings.showTitle {
                        Text(verbatim: "Video Title")
                            .font(fontStyle.font(size: size * 0.55, weight: .medium))
                            .foregroundStyle(.white.opacity(0.9))
                            .lineLimit(1)
                    }

                    if settings.showSourceName {
                        Text(verbatim: "Channel Name")
                            .font(fontStyle.font(size: size * 0.45))
                            .foregroundStyle(.white.opacity(0.6))
                            .lineLimit(1)
                    }
                }
            }
        }
        .padding(.horizontal, buttonBackground.glassStyle != nil ? 8 : 0)
        .padding(.vertical, buttonBackground.glassStyle != nil ? 4 : 0)
        .modifier(OptionalCapsuleGlassBackgroundModifier(style: buttonBackground))
    }

    // MARK: - Regular Button Content

    @ViewBuilder
    private var regularButtonContent: some View {
        if let glassStyle = buttonBackground.glassStyle {
            Image(systemName: configuration.buttonType.systemImage)
                .font(.system(size: size))
                .foregroundStyle(.white.opacity(0.9))
                .frame(width: frameSize, height: frameSize)
                .glassBackground(glassStyle, in: .circle, fallback: .ultraThinMaterial)
        } else {
            Image(systemName: configuration.buttonType.systemImage)
                .font(.system(size: size))
                .foregroundStyle(.white.opacity(0.9))
                .frame(width: frameSize, height: frameSize)
        }
    }

    // MARK: - Slider Preview

    @ViewBuilder
    private var sliderPreview: some View {
        let behavior = configuration.sliderSettings?.sliderBehavior ?? .expandOnTap

        // Compute effective behavior based on orientation for autoExpandInLandscape
        let effectiveBehavior: SliderBehavior = {
            if behavior == .autoExpandInLandscape {
                return isLandscape ? .alwaysVisible : .expandOnTap
            }
            return behavior
        }()

        HStack(spacing: 3) {
            // Icon with optional glass background
            sliderIconContent

            // Fake slider - show when effectively always visible
            if effectiveBehavior == .alwaysVisible {
                ZStack(alignment: .leading) {
                    // Slider track
                    RoundedRectangle(cornerRadius: 1.5)
                        .fill(.white.opacity(0.3))
                        .frame(width: size * 3, height: 3)

                    // Slider fill (showing ~60% filled)
                    RoundedRectangle(cornerRadius: 1.5)
                        .fill(.white.opacity(0.8))
                        .frame(width: size * 1.8, height: 3)
                }
            }
        }
    }

    @ViewBuilder
    private var sliderIconContent: some View {
        let iconFrameSize = hasBackground ? size * 1.4 : size * 1.2
        if let glassStyle = buttonBackground.glassStyle {
            Image(systemName: configuration.buttonType.systemImage)
                .font(.system(size: size))
                .foregroundStyle(.white.opacity(0.9))
                .frame(width: iconFrameSize, height: iconFrameSize)
                .glassBackground(glassStyle, in: .circle, fallback: .ultraThinMaterial)
        } else {
            Image(systemName: configuration.buttonType.systemImage)
                .font(.system(size: size))
                .foregroundStyle(.white.opacity(0.9))
                .frame(width: iconFrameSize, height: iconFrameSize)
        }
    }

    private var spacerWidth: CGFloat {
        guard let settings = configuration.settings,
              case .spacer(let spacerSettings) = settings else {
            return 8
        }
        return CGFloat(spacerSettings.fixedWidth) / 4
    }
}

// MARK: - Optional Capsule Glass Background Modifier

/// A view modifier that conditionally applies a capsule glass background.
private struct OptionalCapsuleGlassBackgroundModifier: ViewModifier {
    let style: ButtonBackgroundStyle

    func body(content: Content) -> some View {
        if let glassStyle = style.glassStyle {
            content.glassBackground(glassStyle, in: .capsule, fallback: .ultraThinMaterial)
        } else {
            content
        }
    }
}

// MARK: - Preview

#Preview {
    NavigationStack {
        SectionEditorView(
            sectionType: .top,
            viewModel: PlayerControlsSettingsViewModel(
                layoutService: PlayerControlsLayoutService(),
                settingsManager: SettingsManager()
            )
        )
    }
}
