import Foundation
import Combine
import Network

final class ExternalServiceMiddleware {
    private var servicesDiscoveryId = ""

    func middleware(state: ClientState, action: ClientAction) -> AnyPublisher<ClientAction, Never> {
        switch action {
        case .externalServiceAction(.startDiscoveryExternalServices):
            servicesDiscoveryId = XMLElement.randomId
            let req = XMLElement(
                name: "iq",
                xmlns: nil,
                attributes: [
                    "from": state.jid.description,
                    "id": servicesDiscoveryId,
                    "to": state.jid.domainPart,
                    "type": "get"
                ],
                content: nil,
                nodes: [
                    XMLElement(name: "services", xmlns: "urn:xmpp:extdisco:2", attributes: [:], content: nil, nodes: [])
                ]
            )
            return Just(ClientAction.streamAction(.streamSend(req)))
                .eraseToAnyPublisher()

        case .parserAction(.elementParsed(let element)):
            if element.name == "iq", element.attributes["id"] == servicesDiscoveryId {
                let services = element.nodes
                    .first(where: { $0.name == "services" })?
                    .nodes.compactMap({ ExternalService.parse($0) })
                return Just(ClientAction.externalServiceAction(.externalServicesListUpdated(services ?? [])))
                    .eraseToAnyPublisher()
            } else {
                return Empty().eraseToAnyPublisher()
            }

        default:
            return Empty().eraseToAnyPublisher()
        }
    }
}
