
enum GenerationAnomaly {
    case failedToLoadContent
    case failedToParseContent
    case missingFile(file: String, markdown: String)
    case missingPage(page: String, markdown: String)
    case missingTag(tag: String, markdown: String)
    case invalidCommand(command: CommandType?, markdown: String)
    case warning(String)
}

extension GenerationAnomaly: Identifiable {

    var id: String {
        switch self {
        case .failedToLoadContent:
            return "load-failed"
        case .failedToParseContent:
            return "parse-failed"
        case .missingFile(let string, _):
            return "missing-file-\(string)"
        case .missingPage(let string, _):
            return "missing-page-\(string)"
        case .missingTag(let string, _):
            return "missing-tag-\(string)"
        case .invalidCommand(_, let markdown):
            return "invalid-command-\(markdown)"
        case .warning(let string):
            return "warning-\(string)"
        }
    }
}

extension GenerationAnomaly: Equatable {

    static func == (lhs: GenerationAnomaly, rhs: GenerationAnomaly) -> Bool {
        lhs.id == rhs.id
    }
}

extension GenerationAnomaly: Hashable {

    func hash(into hasher: inout Hasher) {
        hasher.combine(id)
    }
}

extension GenerationAnomaly {

    enum Severity: String, CaseIterable {
        case warning
        case error
    }

    var severity: Severity {
        switch self {
        case .failedToLoadContent, .failedToParseContent:
            return .error
        case .missingFile, .missingPage, .missingTag, .invalidCommand, .warning:
            return .warning
        }
    }
}

extension GenerationAnomaly: CustomStringConvertible {

    var description: String {
        switch self {
        case .failedToLoadContent:
            return "Failed to load content"
        case .failedToParseContent:
            return "Failed to parse content"
        case .missingFile(let string, _):
            return "Missing file: \(string)"
        case .missingPage(let string, _):
            return "Missing page: \(string)"
        case .missingTag(let string, _):
            return "Missing tag: \(string)"
        case .invalidCommand(_, let markdown):
            return "Invalid command: \(markdown)"
        case .warning(let string):
            return "Warning: \(string)"
        }
    }
}
