/*
 * Copyright (c) 2024 Huawei Technologies Co., Ltd.
 * openFuyao is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

// Package v1 provides the HTTP request handling and interaction logic for
// a logging server designed to work within Kubernetes environments. This package
// encapsulates functionalities for making and processing HTTP requests
// to Loki, a horizontally-scalable, highly-available, multi-tenant log aggregation
// system. It aims to facilitate logging data retrieval and analysis by
// providing structured access to logs stored in Loki.
//
// The package defines the APIServer and Handler types that manage the HTTP server
// and request routing respectively. The APIServer serves as the entry point for
// incoming HTTP requests, whereas Handler implements the logic for processing
// these requests, including querying Loki for log data based on various
// parameters such as filename, time range, and log level.
//
// Key Components:
//
//   - HTTPRequest: A struct that encapsulates details of an HTTP request, including
//     URL, method, headers, and body. It serves as a foundational element for
//     constructing requests to Loki.
//
//   - Handler: The core struct that handles incoming requests, routes them to
//     appropriate processing functions, and interacts with Loki to fetch or
//     manipulate log data. It maintains a map of predefined Loki query configurations
//     and a dictionary mapping human-readable time units to their respective
//     durations for flexible time range queries.
//
//   - LogData: A struct designed to unmarshal JSON responses from Loki, specifically
//     targeting the data structure returned by Loki's series and query_range APIs.
//
// Functionalities:
//
//   - Dynamic Loki Query Construction: Allows building and executing complex Loki
//     queries based on request parameters, enabling clients to perform detailed log
//     searches and analysis.
//
//   - Time Range Calculation: Offers utilities to calculate start and end times for
//     queries based on either specific timestamps or relative time units (e.g., "last 5 minutes").
//
//   - API Endpoints: Defines RESTful endpoints for interacting with the logging server,
//     including endpoints for listing available log sources and querying logs based
//     on various filters.
//
// Usage:
// To use this package, create an instance of the Handler struct via the New function,
// then call its methods to handle incoming requests or interact with Loki. The
// package's functionality is encapsulated in the Handler type, making it the primary
// interface for clients.
//
// Note:
// This package assumes that Loki is accessible via HTTP and that clients have
// necessary permissions to query Loki. It also relies on external packages such
// as "github.com/emicklei/go-restful/v3" for RESTful routing and
// "k8s.io/apimachinery/pkg/util/runtime" for Kubernetes-related utilities.
//
// The package is designed with extensibility in mind, allowing for future
// enhancements such as additional Loki query types, improved error handling,
// and richer response parsing.
package v1

const (
	// ContentTypeJSON specifies the MIME type for JSON, used in content type headers.
	ContentTypeJSON = "application/json"
	// ContentType is a header field name used to specify the MIME type of the content being sent.
	ContentType = "Content-Type"
)

// logLevelRegex contains regular expressions for matching log messages by severity levels.
// It maps each log level to a regex pattern that identifies strings commonly associated
// with each log level in log files or streams. This allows for filtering and categorization
// of log messages based on their indicated severity level in various log formats.
//
// Patterns:
// "error"    - Matches strings that denote an error log level. The pattern captures various
// formats commonly used to indicate errors, such as tags or prefixes in logs.
// "warning"  - Matches strings that denote a warning log level. It includes common indicators
// of warnings in log messages.
// "info"     - Matches strings representing an informational log level. This is typically used
// for regular messages that provide runtime information without indicating errors.
// "debug"    - Matches debug-level messages, which are usually intended for development and
// debugging purposes, providing detailed contextual information.
// "critical" - Matches strings that indicate a critical severity level, often used for logs
// that describe severe conditions that may require immediate attention.
var logLevelRegex = map[string]string{
	"error":    errorRegex,
	"warning":  warningRegex,
	"info":     infoRegex,
	"debug":    debugRegex,
	"critical": criticalRegex,
}

var errorRegex = `(` +
	`\\[ERROR\\]|` +
	`\\bERROR\\b|` +
	`\\bERR\\b|` +
	`\\<Error\\>|` +
	`ERROR\\:|` +
	`Error\\:|` +
	`error\\:|` +
	`level=Error|` +
	`level=error|` +
	`level=ERROR|` +
	`\\x22level\\x22:\\x22error\\x22|` +
	`\\x22level\\x22:\\x22Error\\x22|` +
	`\\x22level\\x22:\\x22ERROR\\x22|` +
	`\\bErr:\\b|` +
	`\\bERR:\\b)`

var warningRegex = `(` +
	`\\[WARNING\\]|` +
	`\\bWARN\\b|` +
	`\\bWRN\\b|` +
	`\\<Warning\\>|` +
	`WARN\\:|` +
	`WARNING\\:|` +
	`Warning\\:|` +
	`warning:|` +
	`Warn\\:|` +
	`warn\\:|` +
	`level=Warn|` +
	`level=warning|` +
	`level=warn|` +
	`level=WARNING|` +
	`\\x22level\\x22:\\x22warn\\x22|` +
	`\\x22level\\x22:\\x22Warn\\x22|` +
	`\\x22level\\x22:\\x22warning\\x22|` +
	`\\x22level\\x22:\\x22Warning\\x22|` +
	`\\x22level\\x22:\\x22WARNING\\x22|` +
	`\\bWrn\\b|` +
	`\\bWRN:\\b)`

var infoRegex = `(` +
	`\\[INFO\\]|` +
	`\\bINFO\\b|` +
	`\\<Info\\>|` +
	`INFO\\:|` +
	`Info\\:|` +
	`info\\:|` +
	`level=Info|` +
	`level=info|` +
	`level=INFO|` +
	`\\x22level\\x22:\\x22info\\x22|` +
	`\\x22level\\x22:\\x22Info\\x22|` +
	`\\x22level\\x22:\\x22INFO\\x22)`

var debugRegex = `(` +
	`\\[DEBUG\\]|` +
	`\\bDEBUG\\b|` +
	`\\bDBG\\b|` +
	`\\<Debug\\>|` +
	`DEBUG\\:|` +
	`Debug\\:|` +
	`Debugging\\:|` +
	`level=Debug|` +
	`level=debug|` +
	`level=DEBUG|` +
	`\\x22level\\x22:\\x22debug\\x22|` +
	`\\x22level\\x22:\\x22Debug\\x22|` +
	`\\x22level\\x22:\\x22DEBUG\\x22|` +
	`\\bDbg\\b|` +
	`\\bDBG:\\b)`

var criticalRegex = `(` +
	`\\[CRITICAL\\]|` +
	`\\bCRITICAL\\b|` +
	`\\bCRIT\\b|` +
	`\\<Critical\\>|` +
	`CRITICAL\\:|` +
	`Critical\\:|` +
	`level=critical|` +
	`level=Critical|` +
	`level=CRITICAL|` +
	`\\x22level\\x22:\\x22critical\\x22|` +
	`\\x22level\\x22:\\x22Critical\\x22|` +
	`\\x22level\\x22:\\x22CRITICAL\\x22|` +
	`\\bCRIT:\\b)`