package readapi

import (
	"encoding/json"
	"fmt"
	"net/http"
	"sort"
	"strings"

	"github.com/gofiber/fiber/v2"
	"gitlab.com/mbugroup/lti-api.git/internal/config"
	"gopkg.in/yaml.v3"
)

type Artifacts struct {
	OpenAPIJSON            []byte
	OpenAPIYAML            []byte
	PostmanCollectionJSON  []byte
	PostmanEnvironmentJSON []byte
}

type normalizedRoute struct {
	Method string
	Path   string
	Params []string
}

type securityMode string

const (
	securityNone        securityMode = "none"
	securityBearer      securityMode = "bearer"
	securityAPIOrBearer securityMode = "api_or_bearer"
)

type parameterMeta struct {
	Name           string
	In             string
	Description    string
	Required       bool
	Example        any
	PostmanValue   string
	IncludePostman bool
}

type routeMeta struct {
	Group       string
	Tag         string
	Summary     string
	Description string
	Security    securityMode
	ListStyle   bool
	QueryParams []parameterMeta
	Exclude     bool
}

func RegisterRoutes(router fiber.Router) {
	router.Get("/openapi/read.json", serveOpenAPIJSON)
	router.Get("/openapi/read.yaml", serveOpenAPIYAML)
}

func PrimeBuildConfig() {
	if strings.TrimSpace(config.S3Bucket) == "" {
		config.S3Bucket = "read-api-artifacts"
	}
	if strings.TrimSpace(config.S3Region) == "" {
		config.S3Region = "us-east-1"
	}
	if strings.TrimSpace(config.S3AccessKey) == "" {
		config.S3AccessKey = "local-access-key"
	}
	if strings.TrimSpace(config.S3SecretKey) == "" {
		config.S3SecretKey = "local-secret-key"
	}
	if strings.TrimSpace(config.S3Endpoint) == "" {
		config.S3Endpoint = "http://localhost:9000"
	}
	if strings.TrimSpace(config.S3PublicBaseURL) == "" {
		config.S3PublicBaseURL = "http://localhost:9000/read-api-artifacts"
	}
}

func BuildArtifactsFromApp(app *fiber.App) (Artifacts, error) {
	if app == nil {
		return Artifacts{}, fmt.Errorf("app is required")
	}

	routes := normalizeRoutes(app.GetRoutes(true))
	return buildArtifactsFromNormalized(routes)
}

func BuildArtifacts(routes []fiber.Route) (Artifacts, error) {
	normalized := normalizeRoutes(routes)
	return buildArtifactsFromNormalized(normalized)
}

func buildArtifactsFromNormalized(normalized []normalizedRoute) (Artifacts, error) {
	specDoc := buildOpenAPIDocument(normalized)
	collectionDoc := buildPostmanCollection(normalized)
	environmentDoc := buildPostmanEnvironment(normalized)

	openAPIJSON, err := json.MarshalIndent(specDoc, "", "  ")
	if err != nil {
		return Artifacts{}, err
	}

	openAPIYAML, err := yaml.Marshal(specDoc)
	if err != nil {
		return Artifacts{}, err
	}

	postmanCollectionJSON, err := json.MarshalIndent(collectionDoc, "", "  ")
	if err != nil {
		return Artifacts{}, err
	}

	postmanEnvironmentJSON, err := json.MarshalIndent(environmentDoc, "", "  ")
	if err != nil {
		return Artifacts{}, err
	}

	return Artifacts{
		OpenAPIJSON:            openAPIJSON,
		OpenAPIYAML:            openAPIYAML,
		PostmanCollectionJSON:  postmanCollectionJSON,
		PostmanEnvironmentJSON: postmanEnvironmentJSON,
	}, nil
}

func serveOpenAPIJSON(c *fiber.Ctx) error {
	artifacts, err := BuildArtifactsFromApp(c.App())
	if err != nil {
		return err
	}
	return c.Status(fiber.StatusOK).Type("json").Send(artifacts.OpenAPIJSON)
}

func serveOpenAPIYAML(c *fiber.Ctx) error {
	artifacts, err := BuildArtifactsFromApp(c.App())
	if err != nil {
		return err
	}
	c.Set(fiber.HeaderContentType, "application/yaml")
	return c.Status(fiber.StatusOK).Send(artifacts.OpenAPIYAML)
}

func normalizeRoutes(routes []fiber.Route) []normalizedRoute {
	seen := make(map[string]struct{}, len(routes))
	normalized := make([]normalizedRoute, 0, len(routes))
	for _, route := range routes {
		if route.Method != http.MethodGet {
			continue
		}
		if route.Path == "" || strings.HasPrefix(route.Path, "/api/openapi/") {
			continue
		}

		key := route.Method + " " + route.Path
		if _, ok := seen[key]; ok {
			continue
		}
		seen[key] = struct{}{}

		normalized = append(normalized, normalizedRoute{
			Method: route.Method,
			Path:   route.Path,
			Params: append([]string(nil), route.Params...),
		})
	}

	sort.Slice(normalized, func(i, j int) bool {
		if normalized[i].Path == normalized[j].Path {
			return normalized[i].Method < normalized[j].Method
		}
		return normalized[i].Path < normalized[j].Path
	})

	return normalized
}

func buildOpenAPIDocument(routes []normalizedRoute) map[string]any {
	paths := make(map[string]any, len(routes))
	for _, route := range routes {
		meta := describeRoute(route)
		if meta.Exclude {
			continue
		}

		openAPIPath := toOpenAPIPath(route.Path)
		operation := map[string]any{
			"summary":     meta.Summary,
			"description": meta.Description,
			"tags":        []string{meta.Tag},
			"responses": map[string]any{
				"200": map[string]any{
					"description": "Successful response",
					"content": map[string]any{
						"application/json": map[string]any{
							"schema": successSchema(meta),
						},
					},
				},
				"401": map[string]any{
					"description": "Unauthorized",
					"content": map[string]any{
						"application/json": map[string]any{
							"schema": map[string]any{"$ref": "#/components/schemas/ErrorEnvelope"},
						},
					},
				},
				"403": map[string]any{
					"description": "Forbidden",
					"content": map[string]any{
						"application/json": map[string]any{
							"schema": map[string]any{"$ref": "#/components/schemas/ErrorEnvelope"},
						},
					},
				},
			},
		}

		params := buildParameters(route, meta)
		if len(params) > 0 {
			operation["parameters"] = params
		}

		switch meta.Security {
		case securityBearer:
			operation["security"] = []map[string][]string{{"BearerAuth": {}}}
		case securityAPIOrBearer:
			operation["security"] = []map[string][]string{
				{"ApiKeyAuth": {}},
				{"BearerAuth": {}},
			}
		}

		paths[openAPIPath] = map[string]any{
			"get": operation,
		}
	}

	return map[string]any{
		"openapi": "3.1.0",
		"info": map[string]any{
			"title":       "LTI ERP Read API",
			"version":     "v1",
			"description": "Read-only OpenAPI surface for dashboard integrations and GET endpoint exploration.",
		},
		"servers": []map[string]any{
			{"url": "http://localhost:8081"},
		},
		"paths": paths,
		"components": map[string]any{
			"securitySchemes": map[string]any{
				"ApiKeyAuth": map[string]any{
					"type": "apiKey",
					"in":   "header",
					"name": "X-API-Key",
				},
				"BearerAuth": map[string]any{
					"type":   "http",
					"scheme": "bearer",
				},
			},
			"schemas": map[string]any{
				"SuccessEnvelope": map[string]any{
					"type": "object",
					"properties": map[string]any{
						"code":    map[string]any{"type": "integer", "example": 200},
						"status":  map[string]any{"type": "string", "example": "success"},
						"message": map[string]any{"type": "string", "example": "Request completed successfully"},
						"data":    map[string]any{"type": "object", "additionalProperties": true},
					},
				},
				"PaginatedEnvelope": map[string]any{
					"type": "object",
					"properties": map[string]any{
						"code":    map[string]any{"type": "integer", "example": 200},
						"status":  map[string]any{"type": "string", "example": "success"},
						"message": map[string]any{"type": "string", "example": "Request completed successfully"},
						"meta": map[string]any{
							"type": "object",
							"properties": map[string]any{
								"page":          map[string]any{"type": "integer", "example": 1},
								"limit":         map[string]any{"type": "integer", "example": 10},
								"total_pages":   map[string]any{"type": "integer", "example": 1},
								"total_results": map[string]any{"type": "integer", "example": 0},
							},
						},
						"data": map[string]any{
							"type":  "array",
							"items": map[string]any{"type": "object", "additionalProperties": true},
						},
					},
				},
				"ErrorEnvelope": map[string]any{
					"type": "object",
					"properties": map[string]any{
						"code":    map[string]any{"type": "integer", "example": 401},
						"status":  map[string]any{"type": "string", "example": "error"},
						"message": map[string]any{"type": "string", "example": "Please authenticate"},
						"errors":  map[string]any{"type": "object", "additionalProperties": true},
					},
				},
			},
		},
	}
}

func buildParameters(route normalizedRoute, meta routeMeta) []map[string]any {
	params := make([]map[string]any, 0, len(route.Params)+len(meta.QueryParams))
	for _, param := range route.Params {
		params = append(params, map[string]any{
			"name":        param,
			"in":          "path",
			"required":    true,
			"description": fmt.Sprintf("Path parameter `%s`.", param),
			"schema": map[string]any{
				"type":    "string",
				"example": defaultExampleForVariable(inferPostmanPathVariable(route.Path, param)),
			},
		})
	}
	for _, query := range meta.QueryParams {
		parameter := map[string]any{
			"name":        query.Name,
			"in":          query.In,
			"required":    query.Required,
			"description": query.Description,
			"schema":      inferSchema(query.Example),
		}
		if query.Example != nil {
			parameter["example"] = query.Example
		}
		params = append(params, parameter)
	}
	return params
}

func successSchema(meta routeMeta) map[string]any {
	if meta.ListStyle {
		return map[string]any{"$ref": "#/components/schemas/PaginatedEnvelope"}
	}
	return map[string]any{"$ref": "#/components/schemas/SuccessEnvelope"}
}

func buildPostmanCollection(routes []normalizedRoute) map[string]any {
	type folder struct {
		name  string
		items []any
	}

	folders := map[string]map[string]*folder{
		"Public":                   {},
		"Dashboard API Key":        {},
		"Internal/OAuth Reference": {},
	}

	for _, route := range routes {
		meta := describeRoute(route)
		if meta.Exclude {
			continue
		}

		tagFolder := folders[meta.Group]
		group, ok := tagFolder[meta.Tag]
		if !ok {
			group = &folder{name: meta.Tag}
			tagFolder[meta.Tag] = group
		}
		group.items = append(group.items, buildPostmanRequest(route, meta))
	}

	rootItems := make([]any, 0, len(folders))
	for _, groupName := range []string{"Public", "Dashboard API Key", "Internal/OAuth Reference"} {
		tagFolder := folders[groupName]
		tagNames := make([]string, 0, len(tagFolder))
		for tagName := range tagFolder {
			tagNames = append(tagNames, tagName)
		}
		sort.Strings(tagNames)

		groupItems := make([]any, 0, len(tagNames))
		for _, tagName := range tagNames {
			groupItems = append(groupItems, map[string]any{
				"name": tagName,
				"item": tagFolder[tagName].items,
			})
		}

		folder := map[string]any{
			"name": groupName,
			"item": groupItems,
		}
		if events := postmanFolderEvents(groupName); len(events) > 0 {
			folder["event"] = events
		}
		rootItems = append(rootItems, folder)
	}

	return map[string]any{
		"info": map[string]any{
			"name":   "LTI ERP Read API",
			"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
		},
		"item": rootItems,
	}
}

func postmanFolderEvents(groupName string) []map[string]any {
	switch groupName {
	case "Dashboard API Key":
		return []map[string]any{
			{
				"listen": "prerequest",
				"script": map[string]any{
					"type": "text/javascript",
					"exec": []string{
						"const apiKey = pm.environment.get('api_key');",
						"const bearerToken = pm.environment.get('bearer_token');",
						"if (apiKey) {",
						"  pm.request.headers.upsert({ key: 'X-API-Key', value: apiKey });",
						"  pm.request.headers.remove('Authorization');",
						"} else if (bearerToken) {",
						"  pm.request.headers.upsert({ key: 'Authorization', value: 'Bearer ' + bearerToken });",
						"  pm.request.headers.remove('X-API-Key');",
						"} else {",
						"  pm.request.headers.remove('Authorization');",
						"  pm.request.headers.remove('X-API-Key');",
						"}",
					},
				},
			},
		}
	case "Internal/OAuth Reference":
		return []map[string]any{
			{
				"listen": "prerequest",
				"script": map[string]any{
					"type": "text/javascript",
					"exec": []string{
						"const bearerToken = pm.environment.get('bearer_token');",
						"pm.request.headers.remove('X-API-Key');",
						"if (bearerToken) {",
						"  pm.request.headers.upsert({ key: 'Authorization', value: 'Bearer ' + bearerToken });",
						"} else {",
						"  pm.request.headers.remove('Authorization');",
						"}",
					},
				},
			},
		}
	default:
		return nil
	}
}

func buildPostmanRequest(route normalizedRoute, meta routeMeta) map[string]any {
	return map[string]any{
		"name": meta.Summary,
		"request": map[string]any{
			"method": http.MethodGet,
			"header": []map[string]any{
				{"key": "Accept", "value": "application/json"},
			},
			"url": buildPostmanURL(route, meta),
		},
	}
}

func buildPostmanURL(route normalizedRoute, meta routeMeta) string {
	path := route.Path
	for _, param := range route.Params {
		path = strings.ReplaceAll(path, ":"+param, "{{"+inferPostmanPathVariable(route.Path, param)+"}}")
	}

	query := make([]string, 0, len(meta.QueryParams))
	for _, param := range meta.QueryParams {
		value := strings.TrimSpace(param.PostmanValue)
		if value == "" && param.Example != nil {
			value = fmt.Sprintf("%v", param.Example)
		}
		query = append(query, fmt.Sprintf("%s=%v", param.Name, value))
	}

	if len(query) == 0 {
		return "{{base_url}}" + path
	}

	return "{{base_url}}" + path + "?" + strings.Join(query, "&")
}

func buildPostmanEnvironment(routes []normalizedRoute) map[string]any {
	values := map[string]string{
		"base_url":                 "http://localhost:8081",
		"api_key":                  "",
		"bearer_token":             "",
		"id":                       "1",
		"bank_id":                  "1",
		"customer_id":              "1",
		"expense_id":               "1",
		"location_id":              "1",
		"project_flock_id":         "1",
		"project_flock_kandang_id": "1",
		"supplier_id":              "1",
	}

	for _, route := range routes {
		meta := describeRoute(route)
		if meta.Exclude {
			continue
		}

		for _, param := range route.Params {
			name := inferPostmanPathVariable(route.Path, param)
			if _, ok := values[name]; !ok {
				values[name] = defaultExampleForVariable(name)
			}
		}
		for _, query := range meta.QueryParams {
			if query.IncludePostman && strings.HasPrefix(query.PostmanValue, "{{") && strings.HasSuffix(query.PostmanValue, "}}") {
				name := strings.TrimSuffix(strings.TrimPrefix(query.PostmanValue, "{{"), "}}")
				if _, ok := values[name]; !ok {
					values[name] = defaultExampleForVariable(name)
				}
			}
		}
	}

	keys := make([]string, 0, len(values))
	for key := range values {
		keys = append(keys, key)
	}
	sort.Strings(keys)

	items := make([]map[string]any, 0, len(keys))
	for _, key := range keys {
		items = append(items, map[string]any{
			"key":     key,
			"value":   values[key],
			"enabled": true,
		})
	}

	return map[string]any{
		"id":                      "lti-read-api-local",
		"name":                    "LTI ERP Read API.local",
		"values":                  items,
		"_postman_variable_scope": "environment",
		"_postman_exported_at":    "2026-04-14T00:00:00Z",
		"_postman_exported_using": "Codex",
	}
}

func describeRoute(route normalizedRoute) routeMeta {
	routePath := route.Path
	if len(routePath) > 1 {
		routePath = strings.TrimSuffix(routePath, "/")
	}

	meta := routeMeta{
		Group:       "Dashboard API Key",
		Tag:         inferTag(routePath),
		Summary:     defaultSummary(routePath),
		Description: fmt.Sprintf("Read access to `%s`.", routePath),
		Security:    securityAPIOrBearer,
		ListStyle:   !strings.Contains(routePath, ":"),
	}

	switch {
	case routePath == "/healthz" || routePath == "/readyz" || routePath == "/api/constants":
		meta.Group = "Public"
		meta.Security = securityNone
		meta.ListStyle = false
	case strings.HasPrefix(routePath, "/api/sso/"):
		meta.Group = "Internal/OAuth Reference"
		meta.ListStyle = false
		if routePath == "/api/sso/userinfo" {
			meta.Security = securityBearer
		} else {
			meta.Security = securityNone
		}
	}

	switch routePath {
	case "/api/approvals":
		meta.QueryParams = []parameterMeta{
			{Name: "module_name", In: "query", Description: "Approval workflow module name.", Required: true, Example: "EXPENSES", PostmanValue: "EXPENSES"},
			{Name: "module_id", In: "query", Description: "Optional approvable module id.", Example: 1},
			{Name: "group_step_number", In: "query", Description: "Group approval records by step number.", Example: false},
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "approval"},
			{Name: "order_by_date", In: "query", Description: "Sort direction by date.", Example: "DESC"},
		}
	case "/api/daily-checklists":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "kebersihan"},
			{Name: "date_from", In: "query", Description: "Start date filter (YYYY-MM-DD).", Example: "2026-01-01"},
			{Name: "date_to", In: "query", Description: "End date filter (YYYY-MM-DD).", Example: "2026-01-31"},
			{Name: "status", In: "query", Description: "Checklist status filter.", Example: "done"},
			{Name: "kandang_id", In: "query", Description: "Kandang id filter.", Example: 1, PostmanValue: "{{idProjectFlockKandang}}"},
		}
	case "/api/daily-checklists/report":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Required: true, Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Required: true, Example: 10},
			{Name: "bulan", In: "query", Description: "Month number (1-12).", Required: true, Example: 1},
			{Name: "tahun", In: "query", Description: "Year.", Required: true, Example: 2026},
			{Name: "area_id", In: "query", Description: "Area id filter.", Example: 1, PostmanValue: "{{area_id}}"},
			{Name: "location_id", In: "query", Description: "Location id filter.", Example: 1, PostmanValue: "{{location_id}}"},
			{Name: "kandang_id", In: "query", Description: "Kandang id filter.", Example: 1, PostmanValue: "{{idProjectFlockKandang}}"},
			{Name: "employee_id", In: "query", Description: "Employee id filter.", Example: 1, PostmanValue: "{{employee_id}}"},
			{Name: "phase_id", In: "query", Description: "Phase id filter.", Example: 1, PostmanValue: "{{id}}"},
		}
	case "/api/daily-checklists/summary":
		meta.QueryParams = []parameterMeta{
			{Name: "date_from", In: "query", Description: "Start date filter (YYYY-MM-DD).", Required: true, Example: "2026-01-01"},
			{Name: "date_to", In: "query", Description: "End date filter (YYYY-MM-DD).", Required: true, Example: "2026-01-31"},
			{Name: "category", In: "query", Description: "Checklist category filter.", Example: "cleaning"},
			{Name: "kandang_id", In: "query", Description: "Kandang id filter.", Example: 1, PostmanValue: "{{idProjectFlockKandang}}"},
		}
	case "/api/daily-checklists/tasks":
		meta.QueryParams = []parameterMeta{
			{Name: "checklist_id", In: "query", Description: "Daily checklist id.", Required: true, Example: 1, PostmanValue: "{{idDailyChecklist}}"},
		}
	case "/api/closings":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "kandang"},
			{Name: "project_status", In: "query", Description: "Project status filter (1 or 2).", Example: 1},
			{Name: "location_id", In: "query", Description: "Location id filter.", Example: 1, PostmanValue: "{{location_id}}"},
		}
	case "/api/closings/:projectFlockId":
		meta.ListStyle = false
		meta.QueryParams = []parameterMeta{
			{Name: "kandang_id", In: "query", Description: "Optional kandang id filter.", Example: 1, PostmanValue: "{{project_flock_kandang_id}}"},
		}
	case "/api/closings/:project_flock_id/perhitungan_sapronak", "/api/closings/:project_flock_id/:project_flock_kandang_id/perhitungan_sapronak":
		meta.ListStyle = false
		meta.QueryParams = []parameterMeta{
			{Name: "flag", In: "query", Description: "Product category flag filter (DOC/OVK/PAKAN/PULLET).", Example: "DOC"},
		}
	case "/api/expenses":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "operasional"},
		}
	case "/api/dashboards":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "farm"},
			{Name: "start_date", In: "query", Description: "Period start date (YYYY-MM-DD).", Example: "2026-01-01"},
			{Name: "end_date", In: "query", Description: "Period end date (YYYY-MM-DD).", Example: "2026-01-31"},
			{Name: "analysis_mode", In: "query", Description: "Dashboard analysis mode.", Example: "OVERVIEW"},
			{Name: "comparison_type", In: "query", Description: "Required when analysis_mode is COMPARISON.", Example: "PREVIOUS_PERIOD"},
			{Name: "metric", In: "query", Description: "Metric to compare.", Example: "egg_mass"},
			{Name: "location_ids", In: "query", Description: "Comma separated location ids.", Example: "1,2"},
			{Name: "flock_ids", In: "query", Description: "Comma separated flock ids.", Example: "1,2"},
			{Name: "kandang_ids", In: "query", Description: "Comma separated kandang ids.", Example: "1,2"},
			{Name: "include", In: "query", Description: "Comma separated dashboard sections to include.", Example: "performance,summary"},
		}
	case "/api/closings/:projectFlockId/sapronak":
		meta.ListStyle = true
		meta.QueryParams = []parameterMeta{
			{Name: "type", In: "query", Description: "Required sapronak direction.", Required: true, Example: "incoming", PostmanValue: "incoming"},
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "pakan"},
			{Name: "kandang_id", In: "query", Description: "Optional kandang id filter.", Example: 1, PostmanValue: "{{project_flock_kandang_id}}"},
		}
	case "/api/closings/:projectFlockId/sapronak/summary":
		meta.ListStyle = false
		meta.QueryParams = []parameterMeta{
			{Name: "type", In: "query", Description: "Required sapronak direction.", Required: true, Example: "incoming", PostmanValue: "incoming"},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "pakan"},
			{Name: "kandang_id", In: "query", Description: "Optional kandang id filter.", Example: 1, PostmanValue: "{{project_flock_kandang_id}}"},
		}
	case "/api/closings/:projectFlockId/production-data", "/api/closings/:projectFlockId/keuangan":
		meta.ListStyle = false
		meta.QueryParams = []parameterMeta{
			{Name: "kandang_id", In: "query", Description: "Optional kandang id filter.", Example: 1, PostmanValue: "{{project_flock_kandang_id}}"},
		}
	case "/api/closings/:project_flock_id/expedition-hpp":
		meta.ListStyle = false
		meta.QueryParams = []parameterMeta{
			{Name: "project_flock_kandang_id", In: "query", Description: "Optional project flock kandang id filter.", Example: 1, PostmanValue: "{{project_flock_kandang_id}}"},
		}
	case "/api/inventory/adjustments":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "product_id", In: "query", Description: "Product id filter.", Example: 1, PostmanValue: "{{product_id}}"},
			{Name: "warehouse_id", In: "query", Description: "Warehouse id filter.", Example: 1, PostmanValue: "{{warehouse_id}}"},
			{Name: "transaction_type", In: "query", Description: "Transaction type filter.", Example: "IN"},
			{Name: "transaction_subtype", In: "query", Description: "Transaction subtype filter.", Example: "ADJUSTMENT"},
			{Name: "function_code", In: "query", Description: "Function code filter.", Example: "MANUAL_ADJUSTMENT"},
		}
	case "/api/inventory/product-stocks":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "pakan"},
		}
	case "/api/inventory/product-warehouses":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "gudang"},
			{Name: "product_id", In: "query", Description: "Product id filter.", Example: 1, PostmanValue: "{{product_id}}"},
			{Name: "warehouse_id", In: "query", Description: "Warehouse id filter.", Example: 1, PostmanValue: "{{warehouse_id}}"},
			{Name: "location_id", In: "query", Description: "Location id filter.", Example: 1, PostmanValue: "{{location_id}}"},
			{Name: "flags", In: "query", Description: "Stock flags filter.", Example: "DOC"},
			{Name: "kandang_id", In: "query", Description: "Kandang id filter.", Example: 1, PostmanValue: "{{project_flock_kandang_id}}"},
			{Name: "available_only", In: "query", Description: "Show available stock only.", Example: true},
			{Name: "transfer_context", In: "query", Description: "Transfer context filter.", Example: "inventory_transfer"},
			{Name: "stock_mode", In: "query", Description: "Stock mode filter.", Example: "exclude_chickin"},
			{Name: "type", In: "query", Description: "Warehouse stock type filter.", Example: "incoming"},
		}
	case "/api/inventory/transfers":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "TRF"},
		}
	case "/api/marketing":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "delivery"},
			{Name: "product_ids", In: "query", Description: "Comma separated product ids.", Example: "1,2"},
			{Name: "status", In: "query", Description: "Delivery status filter.", Example: "DRAFT"},
			{Name: "customer_id", In: "query", Description: "Customer id filter.", Example: 1, PostmanValue: "{{customer_id}}"},
			{Name: "marketing_id", In: "query", Description: "Marketing id filter.", Example: 1},
		}
	case "/api/master-data/areas":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "bandung"},
		}
	case "/api/master-data/banks":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "bca"},
		}
	case "/api/master-data/config-checklists":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "harian"},
		}
	case "/api/master-data/customers":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "pt"},
			{Name: "has_marketing", In: "query", Description: "Filter customer by marketing relation.", Example: true},
		}
	case "/api/master-data/employees":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "andi"},
			{Name: "kandang_id", In: "query", Description: "Kandang id filter.", Example: 1, PostmanValue: "{{project_flock_kandang_id}}"},
			{Name: "is_active", In: "query", Description: "Active status filter.", Example: true},
		}
	case "/api/master-data/fcrs":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "fcr"},
		}
	case "/api/master-data/flocks":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "layer"},
		}
	case "/api/master-data/kandang-groups":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "blok"},
			{Name: "location_id", In: "query", Description: "Location id filter.", Example: 1, PostmanValue: "{{location_id}}"},
			{Name: "pic_id", In: "query", Description: "Person in charge id filter.", Example: 1, PostmanValue: "{{employee_id}}"},
		}
	case "/api/master-data/kandangs":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "kandang"},
			{Name: "location_id", In: "query", Description: "Location id filter.", Example: 1, PostmanValue: "{{location_id}}"},
			{Name: "pic_id", In: "query", Description: "Person in charge id filter.", Example: 1, PostmanValue: "{{employee_id}}"},
		}
	case "/api/master-data/locations":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "farm"},
			{Name: "area_id", In: "query", Description: "Area id filter.", Example: 1, PostmanValue: "{{area_id}}"},
			{Name: "has_laying", In: "query", Description: "Filter laying locations only.", Example: false},
		}
	case "/api/master-data/nonstocks":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "vitamin"},
			{Name: "supplier_id", In: "query", Description: "Supplier id filter.", Example: 1, PostmanValue: "{{supplier_id}}"},
		}
	case "/api/master-data/phase-activities":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "cek pakan"},
			{Name: "phase_ids", In: "query", Description: "Comma separated phase ids.", Example: "1,2"},
		}
	case "/api/master-data/phases":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "starter"},
			{Name: "category", In: "query", Description: "Phase category filter.", Example: "Growing"},
		}
	case "/api/master-data/product-categories":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "pakan"},
		}
	case "/api/master-data/production-standards":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "standar"},
			{Name: "project_category", In: "query", Description: "Project category filter.", Example: "GROWING"},
		}
	case "/api/master-data/products":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "jagung"},
			{Name: "product_category_id", In: "query", Description: "Product category id filter.", Example: 1, PostmanValue: "{{product_category_id}}"},
			{Name: "is_depletion", In: "query", Description: "Filter depletion products.", Example: false},
			{Name: "include_all", In: "query", Description: "Include all products regardless of status.", Example: false},
		}
	case "/api/master-data/suppliers":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "supplier"},
			{Name: "flag", In: "query", Description: "Supplier type flag filter.", Example: "ACTIVE"},
			{Name: "category", In: "query", Description: "Supplier category filter.", Example: "PAKAN"},
		}
	case "/api/master-data/uoms":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "kg"},
		}
	case "/api/master-data/warehouses":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "gudang"},
			{Name: "area_id", In: "query", Description: "Area id filter.", Example: 1, PostmanValue: "{{area_id}}"},
			{Name: "location_id", In: "query", Description: "Location id filter.", Example: 1, PostmanValue: "{{location_id}}"},
			{Name: "active_project_flock", In: "query", Description: "Filter only active project flock warehouses.", Example: false},
			{Name: "transfer_context", In: "query", Description: "Transfer context filter.", Example: "inventory_transfer"},
		}
	case "/api/production/project-flock-kandangs":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "kandang"},
			{Name: "name_with_periode", In: "query", Description: "Return name-with-period projection.", Example: false},
			{Name: "project_flock_id", In: "query", Description: "Project flock id filter.", Example: 1, PostmanValue: "{{project_flock_id}}"},
			{Name: "kandang_id", In: "query", Description: "Kandang id filter.", Example: 1, PostmanValue: "{{project_flock_kandang_id}}"},
			{Name: "category", In: "query", Description: "Project category filter.", Example: "Growing"},
			{Name: "area_id", In: "query", Description: "Area id filter.", Example: 1, PostmanValue: "{{area_id}}"},
			{Name: "location_id", In: "query", Description: "Location id filter.", Example: 1, PostmanValue: "{{location_id}}"},
			{Name: "sort_by", In: "query", Description: "Sort field.", Example: "created_at"},
			{Name: "sort_order", In: "query", Description: "Sort order.", Example: "ASC"},
			{Name: "step_name", In: "query", Description: "Approval step name filter.", Example: "Pengajuan"},
		}
	case "/api/production/project-flocks":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "flock"},
			{Name: "sort_by", In: "query", Description: "Sort field.", Example: "created_at"},
			{Name: "sort_order", In: "query", Description: "Sort order.", Example: "asc"},
			{Name: "area_id", In: "query", Description: "Area id filter.", Example: 1, PostmanValue: "{{area_id}}"},
			{Name: "location_id", In: "query", Description: "Location id filter.", Example: 1, PostmanValue: "{{location_id}}"},
			{Name: "period", In: "query", Description: "Project period filter.", Example: 1},
			{Name: "category", In: "query", Description: "Project category filter.", Example: "Growing"},
			{Name: "status", In: "query", Description: "Project status filter.", Example: "Aktif"},
			{Name: "kandang_id", In: "query", Description: "Comma separated kandang ids.", Example: "1,2"},
			{Name: "transfer_context", In: "query", Description: "Transfer context filter.", Example: "transfer_to_laying"},
		}
	case "/api/production/project-flocks/kandangs/lookup":
		meta.ListStyle = false
		meta.QueryParams = []parameterMeta{
			{Name: "project_flock_id", In: "query", Description: "Project flock id.", Required: true, Example: 1, PostmanValue: "{{project_flock_id}}"},
			{Name: "kandang_id", In: "query", Description: "Kandang id.", Required: true, Example: 1, PostmanValue: "{{project_flock_kandang_id}}"},
			{Name: "withpopulation", In: "query", Description: "Include population value in response.", Example: false},
			{Name: "record_date", In: "query", Description: "Reference date (YYYY-MM-DD).", Example: "2026-01-01"},
		}
	case "/api/production/recordings":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "project_flock_kandang_id", In: "query", Description: "Project flock kandang id filter.", Example: 1, PostmanValue: "{{project_flock_kandang_id}}"},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "record"},
			{Name: "export", In: "query", Description: "Export mode.", Example: "excel"},
		}
	case "/api/production/recordings/next-day":
		meta.ListStyle = false
		meta.QueryParams = []parameterMeta{
			{Name: "project_flock_kandang_id", In: "query", Description: "Project flock kandang id.", Required: true, Example: 1, PostmanValue: "{{project_flock_kandang_id}}"},
			{Name: "record_date", In: "query", Description: "Recording date (YYYY-MM-DD).", Required: true, Example: "2026-01-01"},
		}
	case "/api/production/transfer_layings":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "transfer"},
			{Name: "start_date", In: "query", Description: "Start date (YYYY-MM-DD).", Example: "2026-01-01"},
			{Name: "end_date", In: "query", Description: "End date (YYYY-MM-DD).", Example: "2026-01-31"},
			{Name: "flock_source", In: "query", Description: "Comma separated source flock ids.", Example: "1,2"},
			{Name: "flock_destination", In: "query", Description: "Comma separated destination flock ids.", Example: "3,4"},
			{Name: "status", In: "query", Description: "Comma separated status values.", Example: "DRAFT,APPROVED"},
		}
	case "/api/production/uniformities":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "project_flock_kandang_id", In: "query", Description: "Project flock kandang id filter.", Example: 1, PostmanValue: "{{project_flock_kandang_id}}"},
			{Name: "week", In: "query", Description: "Week number filter.", Example: 1},
			{Name: "start_date", In: "query", Description: "Start date (YYYY-MM-DD).", Example: "2026-01-01"},
			{Name: "end_date", In: "query", Description: "End date (YYYY-MM-DD).", Example: "2026-01-31"},
			{Name: "with_chart", In: "query", Description: "Include chart payload.", Example: false},
		}
	case "/api/purchases":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "supplier_id", In: "query", Description: "Supplier id filter.", Example: 1, PostmanValue: "{{supplier_id}}"},
			{Name: "area_id", In: "query", Description: "Area id filter.", Example: 1, PostmanValue: "{{area_id}}"},
			{Name: "location_id", In: "query", Description: "Location id filter.", Example: 1, PostmanValue: "{{location_id}}"},
			{Name: "product_category_id", In: "query", Description: "Product category id filter.", Example: "1"},
			{Name: "approval_status", In: "query", Description: "Approval status filter.", Example: "PENDING"},
			{Name: "po_date", In: "query", Description: "PO date (YYYY-MM-DD).", Example: "2026-01-01"},
			{Name: "po_date_from", In: "query", Description: "PO date start (YYYY-MM-DD).", Example: "2026-01-01"},
			{Name: "po_date_to", In: "query", Description: "PO date end (YYYY-MM-DD).", Example: "2026-01-31"},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "PO-"},
			{Name: "created_from", In: "query", Description: "Created date start (YYYY-MM-DD).", Example: "2026-01-01"},
			{Name: "created_to", In: "query", Description: "Created date end (YYYY-MM-DD).", Example: "2026-01-31"},
		}
	case "/api/users":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "admin"},
		}
	case "/api/reports/expense":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "operasional"},
			{Name: "category", In: "query", Description: "Expense category filter.", Example: "BOP"},
			{Name: "supplier_id", In: "query", Description: "Supplier id filter.", Example: 1},
			{Name: "kandang_id", In: "query", Description: "Kandang id filter.", Example: 1},
			{Name: "project_flock_kandang_id", In: "query", Description: "Project flock kandang id filter.", Example: 1},
			{Name: "nonstock_id", In: "query", Description: "Nonstock id filter.", Example: 1},
			{Name: "location_id", In: "query", Description: "Location id filter.", Example: 1},
			{Name: "area_id", In: "query", Description: "Area id filter.", Example: 1},
			{Name: "realization_date", In: "query", Description: "Realization date filter (YYYY-MM-DD).", Example: "2026-01-15"},
		}
	case "/api/reports/expense/depreciation":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "period", In: "query", Description: "Daily period filter (YYYY-MM-DD).", Required: true, Example: "2026-01-01"},
			{Name: "project_flock_id", In: "query", Description: "Comma separated project flock ids.", Example: "1,2"},
			{Name: "area_id", In: "query", Description: "Comma separated area ids.", Example: "1,2"},
			{Name: "location_id", In: "query", Description: "Comma separated location ids.", Example: "1,2"},
		}
	case "/api/reports/expense/depreciation/manual-inputs":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "project_flock_id", In: "query", Description: "Comma separated project flock ids.", Example: "1,2"},
			{Name: "area_id", In: "query", Description: "Comma separated area ids.", Example: "1,2"},
			{Name: "location_id", In: "query", Description: "Comma separated location ids.", Example: "1,2"},
		}
	case "/api/reports/marketing":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "SO-"},
			{Name: "customer_id", In: "query", Description: "Customer id filter.", Example: 1},
			{Name: "product_id", In: "query", Description: "Product id filter.", Example: 1},
			{Name: "warehouse_id", In: "query", Description: "Warehouse id filter.", Example: 1},
			{Name: "sales_person_id", In: "query", Description: "Sales person id filter.", Example: 1},
			{Name: "area_id", In: "query", Description: "Area id filter.", Example: 1},
			{Name: "location_id", In: "query", Description: "Location id filter.", Example: 1},
			{Name: "marketing_type", In: "query", Description: "Marketing type filter.", Example: "ayam"},
			{Name: "filter_by", In: "query", Description: "Date field filter.", Example: "so_date"},
			{Name: "start_date", In: "query", Description: "Period start date (YYYY-MM-DD).", Example: "2026-01-01"},
			{Name: "end_date", In: "query", Description: "Period end date (YYYY-MM-DD).", Example: "2026-01-31"},
			{Name: "sort_by", In: "query", Description: "Sort field.", Example: "so_date"},
			{Name: "sort_order", In: "query", Description: "Sort order.", Example: "asc"},
		}
	case "/api/reports/purchase-supplier":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "area_id", In: "query", Description: "Comma separated area ids.", Example: "1,2"},
			{Name: "supplier_id", In: "query", Description: "Comma separated supplier ids.", Example: "1,2"},
			{Name: "product_id", In: "query", Description: "Comma separated product ids.", Example: "1,2"},
			{Name: "product_category_id", In: "query", Description: "Comma separated product category ids.", Example: "1,2"},
			{Name: "start_date", In: "query", Description: "Period start date (YYYY-MM-DD).", Example: "2026-01-01"},
			{Name: "end_date", In: "query", Description: "Period end date (YYYY-MM-DD).", Example: "2026-01-31"},
			{Name: "sort_by", In: "query", Description: "Sort field.", Example: "created_at"},
			{Name: "filter_by", In: "query", Description: "Filter field.", Example: "received_date"},
		}
	case "/api/reports/debt-supplier":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "start_date", In: "query", Description: "Period start date (YYYY-MM-DD).", Example: "2026-01-01"},
			{Name: "end_date", In: "query", Description: "Period end date (YYYY-MM-DD).", Example: "2026-01-31"},
			{Name: "supplier_ids", In: "query", Description: "Comma separated supplier ids.", Example: "1,2", PostmanValue: "{{supplier_id}}"},
			{Name: "filter_by", In: "query", Description: "Date field filter.", Example: "received_date"},
			{Name: "sort_order", In: "query", Description: "Sort order.", Example: "asc"},
		}
	case "/api/reports/customer-payment":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "start_date", In: "query", Description: "Period start date (YYYY-MM-DD).", Example: "2026-01-01"},
			{Name: "end_date", In: "query", Description: "Period end date (YYYY-MM-DD).", Example: "2026-01-31"},
			{Name: "customer_ids", In: "query", Description: "Comma separated customer ids.", Example: "1,2", PostmanValue: "{{customer_id}}"},
			{Name: "filter_by", In: "query", Description: "Date field filter.", Example: "TRANS_DATE"},
		}
	case "/api/reports/hpp-per-kandang":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "period", In: "query", Description: "Daily period filter (YYYY-MM-DD).", Example: "2026-01-01"},
			{Name: "show_unrecorded", In: "query", Description: "Include unrecorded data.", Example: false},
			{Name: "area_id", In: "query", Description: "Comma separated area ids.", Example: "1,2"},
			{Name: "location_id", In: "query", Description: "Comma separated location ids.", Example: "1,2"},
			{Name: "kandang_id", In: "query", Description: "Comma separated kandang ids.", Example: "1,2"},
			{Name: "weight_min", In: "query", Description: "Minimum body weight filter.", Example: "1.2"},
			{Name: "weight_max", In: "query", Description: "Maximum body weight filter.", Example: "1.8"},
		}
	case "/api/reports/production-result/:idProjectFlockKandang":
		meta.ListStyle = false
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
		}
	case "/api/finance/transactions":
		meta.QueryParams = []parameterMeta{
			{Name: "page", In: "query", Description: "Page number.", Example: 1},
			{Name: "limit", In: "query", Description: "Page size.", Example: 10},
			{Name: "search", In: "query", Description: "Search keyword.", Example: "invoice"},
			{Name: "bank_ids", In: "query", Description: "Comma separated bank ids.", Example: "1,2", PostmanValue: "{{bank_id}}"},
			{Name: "customer_ids", In: "query", Description: "Comma separated customer ids.", Example: "1,2"},
			{Name: "supplier_ids", In: "query", Description: "Comma separated supplier ids.", Example: "1,2"},
			{Name: "transaction_types", In: "query", Description: "Comma separated transaction types.", Example: "payment,initial_balance"},
			{Name: "sort_date", In: "query", Description: "Sort date basis.", Example: "created_at"},
			{Name: "start_date", In: "query", Description: "Start date (YYYY-MM-DD).", Example: "2026-01-01"},
			{Name: "end_date", In: "query", Description: "End date (YYYY-MM-DD).", Example: "2026-01-31"},
		}
	}

	if routePath == "/healthz" {
		meta.Summary = "Health check"
		meta.Description = "Simple liveness probe."
	} else if routePath == "/readyz" {
		meta.Summary = "Readiness check"
		meta.Description = "Readiness probe for database and Redis."
	}

	return meta
}

func inferTag(path string) string {
	switch {
	case path == "/healthz" || path == "/readyz":
		return "System"
	case strings.HasPrefix(path, "/api/master-data/"):
		return "Master Data"
	case strings.HasPrefix(path, "/api/finance/"):
		return "Finance"
	case strings.HasPrefix(path, "/api/inventory/"):
		return "Inventory"
	case strings.HasPrefix(path, "/api/production/"):
		return "Production"
	case strings.HasPrefix(path, "/api/reports/"):
		return "Reports"
	case strings.HasPrefix(path, "/api/closings/"):
		return "Closings"
	case strings.HasPrefix(path, "/api/expenses"):
		return "Expenses"
	case strings.HasPrefix(path, "/api/dashboards"):
		return "Dashboards"
	case strings.HasPrefix(path, "/api/purchases"):
		return "Purchases"
	case strings.HasPrefix(path, "/api/marketing"):
		return "Marketing"
	case strings.HasPrefix(path, "/api/users"):
		return "Users"
	case strings.HasPrefix(path, "/api/daily-checklists"):
		return "Daily Checklists"
	case strings.HasPrefix(path, "/api/sso"):
		return "SSO"
	default:
		return "API"
	}
}

func defaultSummary(path string) string {
	switch path {
	case "/healthz":
		return "Health check"
	case "/readyz":
		return "Readiness check"
	}

	trimmed := strings.Trim(path, "/")
	if trimmed == "" {
		return "List root"
	}
	parts := strings.Split(trimmed, "/")
	for i, part := range parts {
		parts[i] = strings.ReplaceAll(part, "-", " ")
	}
	return "GET " + strings.Join(parts, " / ")
}

func toOpenAPIPath(path string) string {
	segments := strings.Split(path, "/")
	for i, segment := range segments {
		if strings.HasPrefix(segment, ":") {
			segments[i] = "{" + strings.TrimPrefix(segment, ":") + "}"
		}
	}
	return strings.Join(segments, "/")
}

func inferPostmanPathVariable(path, param string) string {
	if param != "id" {
		return param
	}

	switch {
	case strings.HasPrefix(path, "/api/expenses/"):
		return "expense_id"
	case strings.HasPrefix(path, "/api/finance/payments/"):
		return "payment_id"
	case strings.HasPrefix(path, "/api/finance/transactions/"):
		return "transaction_id"
	case strings.HasPrefix(path, "/api/finance/initial-balances/"):
		return "initial_balance_id"
	case strings.HasPrefix(path, "/api/finance/injections/"):
		return "injection_id"
	case strings.HasPrefix(path, "/api/purchases/"):
		return "purchase_id"
	case strings.HasPrefix(path, "/api/inventory/adjustments/"):
		return "adjustment_id"
	case strings.HasPrefix(path, "/api/inventory/transfers/"):
		return "transfer_id"
	case strings.HasPrefix(path, "/api/master-data/banks/"):
		return "bank_id"
	case strings.HasPrefix(path, "/api/master-data/customers/"):
		return "customer_id"
	case strings.HasPrefix(path, "/api/master-data/suppliers/"):
		return "supplier_id"
	case strings.HasPrefix(path, "/api/master-data/locations/"):
		return "location_id"
	case strings.HasPrefix(path, "/api/master-data/areas/"):
		return "area_id"
	case strings.HasPrefix(path, "/api/master-data/products/"):
		return "product_id"
	case strings.HasPrefix(path, "/api/master-data/product-categories/"):
		return "product_category_id"
	case strings.HasPrefix(path, "/api/master-data/nonstocks/"):
		return "nonstock_id"
	case strings.HasPrefix(path, "/api/master-data/employees/"):
		return "employee_id"
	case strings.HasPrefix(path, "/api/master-data/flocks/"):
		return "flock_id"
	case strings.HasPrefix(path, "/api/master-data/warehouses/"):
		return "warehouse_id"
	case strings.HasPrefix(path, "/api/master-data/uoms/"):
		return "uom_id"
	case strings.HasPrefix(path, "/api/users/"):
		return "user_id"
	case strings.HasPrefix(path, "/api/production/recordings/"):
		return "recording_id"
	case strings.HasPrefix(path, "/api/production/uniformities/"):
		return "uniformity_id"
	case strings.HasPrefix(path, "/api/production/chickins/"):
		return "chickin_id"
	default:
		return "id"
	}
}

func defaultExampleForVariable(name string) string {
	if strings.Contains(name, "date") {
		return "2026-01-01"
	}
	if strings.Contains(name, "token") || strings.Contains(name, "key") {
		return ""
	}
	return "1"
}

func inferSchema(example any) map[string]any {
	switch example.(type) {
	case int, int32, int64, uint, uint32, uint64, float64:
		return map[string]any{"type": "integer"}
	default:
		return map[string]any{"type": "string"}
	}
}
