import Foundation
import ComplyCubeMobileSDK

public final class ProofOfAddressStageParser: StageParser {
    private let countryExtractor: CountryExtractor
    public init(countryExtractor: CountryExtractor) { self.countryExtractor = countryExtractor }

    public func canParse(_ input: Any) -> Bool {
        (input as? [String: Any]).map { $0["name"] as? String == "poaCapture" } ?? false
    }

    // Router will append AddressStage after this capture stage (see StageRouting.swift)
    public func parse(_ input: Any) throws -> ComplyCubeMobileSDKStage? {
        guard let map = input as? [String: Any] else { return nil }
        let tmap = map["documentTypes"] as? [String: Any] ?? [:]

        return ProofOfAddressStageBuilder()
            .setEnableMLAssistant(enable: map["useMLAssistance"] as? Bool ?? true)
            .setShowGuidance(enable: map["showGuidance"] as? Bool ?? true)
            .setRetryLimit(count: map["retryLimit"] as? Int ?? 3)
            .useLiveCaptureOnly(enable: map["useLiveCaptureOnly"] as? Bool ?? true)
            .setEnableAddressCapture(enable: map["isAddressCaptureEnabled"] as? Bool ?? false)
            .setAllowedDocumentTypes(types: parseProofOfAddressTypes(tmap))
            .build()
    }
    
    public func parseProofOfAddressTypes(_ documentTypes: [String: Any]) -> [DocumentTypes] {
        if documentTypes.isEmpty {
            return [
                .bankStatement(),
                .utilityBill()
            ]
        }

        var out: [DocumentTypes] = []

        func enable(_ value: Any, push: () -> Void) {
            switch value {
            case let b as Bool where b:
                push()
            case let arr as [Any]:
                let codes = arr.compactMap { $0 as? String }
                guard !codes.isEmpty else { return }
                _ = countryExtractor.extractCountries(codes)
                push()
            default:
                break
            }
        }

        for (key, value) in documentTypes {
            switch key {
            case "utility_bill":
                enable(value) { out.append(.utilityBill()) }
            case "bank_statement":
                enable(value) { out.append(.bankStatement()) }
            default:
                break
            }
        }

        return out
    }
}
