import SwiftUI
import SFSafeSymbols

final class InsertableFileButton: ObservableObject {

    @Published
    var label: ContentLabel = .init(icon: .buttonDownload, value: "Text")

    @Published
    var file: FileResource?

    @Published
    var downloadedFileName: String? = nil

    var command: String? {
        guard let file else {
            return nil
        }
        let result =
            """
            icon: \(label.icon.rawValue)
            text: \(label.value)
            file: \(file.identifier)
            """
        guard let downloadedFileName else {
            return result
        }
        return result + "\n" + "name: \(downloadedFileName)"
    }
}

final class InsertableUrlButton: ObservableObject {

    @Published
    var label: ContentLabel = .init(icon: .buttonDownload, value: "Text")

    @Published
    var url: String = "Url"

    var command: String? {
        """
        icon: \(label.icon.rawValue)
        text: \(label.value)
        url: \(url)
        """
    }
}

final class InsertableEventButton: ObservableObject {

    @Published
    var label: ContentLabel = .init(icon: .buttonDownload, value: "Text")

    @Published
    var event: String = "Javascript"

    var command: String? {
        """
        icon: \(label.icon.rawValue)
        text: \(label.value)
        event: \(event)
        """
    }
}

struct InsertableButtons: View, InsertableCommandView {

    final class Model: ObservableObject, InsertableCommandModel {

        enum AnyButton: Identifiable {
            case file(InsertableFileButton)
            case url(InsertableUrlButton)
            case event(InsertableEventButton)

            var command: String? {
                switch self {
                case .file(let file):
                    return file.command
                case .url(let url):
                    return url.command
                case .event(let event):
                    return event.command
                }
            }

            var id: String {
                switch self {
                case .file(let file):
                    return "file-\(file.file?.identifier ?? "none")"
                case .url(let url):
                    return "url-\(url.url)"
                case .event(let event):
                    return "event-\(event.event)"
                }
            }
        }

        @Published
        var buttons: [AnyButton] = []

        var isReady: Bool {
            !buttons.isEmpty
        }

        var command: String? {
            let result = buttons.compactMap { $0.command }
            guard result.count == buttons.count else {
                return nil
            }
            return result.map {
                "```buttons\n\($0)\n```"
            }.joined(separator: "\n\n")
        }
    }

    static let title = "Buttons"

    static let sheetTitle = "Insert buttons"

    static let icon: SFSymbol = .rectangleAndHandPointUpLeft

    @ObservedObject
    private var model: Model

    init(model: Model) {
        self.model = model
    }

    var body: some View {
        VStack(alignment: .leading) {
            List(model.buttons) { button in
                switch button {
                case .file(let file):
                    FileButtonView(content: file)
                case .url(let url):
                    UrlButtonView(content: url)
                case .event(let event):
                    EventButtonView(content: event)
                }
            }
            .frame(minHeight: 300)
            HStack {
                Spacer()
                Button("File", action: { model.buttons.append(.file(.init())) })
                Button("Url", action: { model.buttons.append(.url(.init())) })
                Button("Event", action: { model.buttons.append(.event(.init())) })
                Spacer()
            }
        }
    }
}

private struct FileButtonView: View {

    @ObservedObject
    var content: InsertableFileButton

    @State
    private var showFileSelectionSheet = false

    var body: some View {
        HStack {
            LabelEditingView(label: $content.label)
            Button("\(content.file?.identifier ?? "Select file")", action: { showFileSelectionSheet = true })
            OptionalTextField("", text: $content.downloadedFileName, prompt: "Downloaded file name")
                .textFieldStyle(.roundedBorder)
        }
        .sheet(isPresented: $showFileSelectionSheet) {
            FileSelectionView(selectedFile: $content.file)
        }
    }
}

private struct UrlButtonView: View {

    @ObservedObject
    var content: InsertableUrlButton

    var body: some View {
        HStack {
            LabelEditingView(label: $content.label)
            TextField("", text: $content.url, prompt: Text("URL"))
                .textFieldStyle(.roundedBorder)
        }
    }
}

private struct EventButtonView: View {

    @ObservedObject
    var content: InsertableEventButton

    var body: some View {
        HStack {
            LabelEditingView(label: $content.label)
            TextField("", text: $content.event, prompt: Text("Javascript"))
                .textFieldStyle(.roundedBorder)
        }
    }
}
