// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package v2

import (
	"net/http"

	"code.gitea.io/gitea/modules/setting"
	"code.gitea.io/gitea/services/context"
)

// scalarTemplate is the HTML template for Scalar API documentation
// Scalar is a modern, AI-friendly API documentation tool
const scalarTemplate = `<!DOCTYPE html>
<html>
<head>
    <title>{{.AppName}} API v2 Reference</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style>
        /* Custom theme to match Gitea */
        :root {
            --scalar-color-1: #4a90d9;
            --scalar-color-accent: #4a90d9;
            --scalar-background-1: #ffffff;
            --scalar-background-2: #f8f9fa;
            --scalar-background-3: #e9ecef;
        }
        @media (prefers-color-scheme: dark) {
            :root {
                --scalar-background-1: #1a1a1a;
                --scalar-background-2: #252525;
                --scalar-background-3: #333333;
            }
        }
    </style>
</head>
<body>
    <script
        id="api-reference"
        data-url="{{.SpecURL}}"
        data-configuration='{
            "theme": "default",
            "layout": "modern",
            "showSidebar": true,
            "hideModels": false,
            "hideDownloadButton": false,
            "hiddenClients": [],
            "defaultHttpClient": {
                "targetKey": "shell",
                "clientKey": "curl"
            }
        }'>
    </script>
    <script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
</body>
</html>`

// DocsScalar serves the Scalar API documentation UI for v2
func DocsScalar(ctx *context.APIContext) {
	data := map[string]string{
		"AppName": setting.AppName,
		"SpecURL": setting.AppSubURL + "/api/v2/swagger.json",
	}

	ctx.Resp.Header().Set("Content-Type", "text/html; charset=utf-8")
	ctx.Resp.WriteHeader(http.StatusOK)

	// Simple template rendering
	html := scalarTemplate
	for key, value := range data {
		html = replaceTemplateVar(html, key, value)
	}
	_, _ = ctx.Resp.Write([]byte(html))
}

func replaceTemplateVar(template, key, value string) string {
	placeholder := "{{." + key + "}}"
	result := template
	for range 10 { // Replace up to 10 occurrences
		newResult := ""
		idx := 0
		for {
			pos := indexOf(result[idx:], placeholder)
			if pos == -1 {
				newResult += result[idx:]
				break
			}
			newResult += result[idx : idx+pos]
			newResult += value
			idx = idx + pos + len(placeholder)
		}
		if newResult == result {
			break
		}
		result = newResult
	}
	return result
}

func indexOf(s, substr string) int {
	for i := 0; i <= len(s)-len(substr); i++ {
		if s[i:i+len(substr)] == substr {
			return i
		}
	}
	return -1
}

// SwaggerJSON serves the OpenAPI/Swagger JSON specification for v2
func SwaggerJSON(ctx *context.APIContext) {
	spec := generateOpenAPISpec()
	ctx.JSON(http.StatusOK, spec)
}

// generateOpenAPISpec creates the OpenAPI 3.0 specification for v2 API
func generateOpenAPISpec() map[string]any {
	return map[string]any{
		"openapi": "3.0.3",
		"info": map[string]any{
			"title":       setting.AppName + " API v2",
			"description": "Gitea API v2 with structured error codes, batch operations, and AI-friendly endpoints.",
			"version":     "2.0.0",
			"contact": map[string]string{
				"name": "Gitea",
				"url":  "https://gitea.com",
			},
			"license": map[string]string{
				"name": "MIT",
				"url":  "https://opensource.org/licenses/MIT",
			},
		},
		"servers": []map[string]string{
			{"url": setting.AppURL + "api/v2", "description": "Current server"},
		},
		"tags": []map[string]string{
			{"name": "miscellaneous", "description": "General API information"},
			{"name": "user", "description": "User operations"},
			{"name": "repository", "description": "Repository operations"},
			{"name": "batch", "description": "Batch operations for bulk actions"},
			{"name": "ai", "description": "AI-friendly context endpoints"},
		},
		"paths": map[string]any{
			"/version": map[string]any{
				"get": map[string]any{
					"tags":        []string{"miscellaneous"},
					"summary":     "Get API version",
					"operationId": "getVersion",
					"responses": map[string]any{
						"200": map[string]any{
							"description": "Version information",
							"content": map[string]any{
								"application/json": map[string]any{
									"schema": map[string]any{
										"$ref": "#/components/schemas/Version",
									},
								},
							},
						},
					},
				},
			},
			"/user": map[string]any{
				"get": map[string]any{
					"tags":        []string{"user"},
					"summary":     "Get authenticated user",
					"operationId": "getAuthenticatedUser",
					"security":    []map[string][]string{{"bearerAuth": {}}},
					"responses": map[string]any{
						"200": map[string]any{
							"description": "User information",
							"content": map[string]any{
								"application/json": map[string]any{
									"schema": map[string]any{
										"$ref": "#/components/schemas/User",
									},
								},
							},
						},
						"401": map[string]any{
							"description": "Authentication required",
							"content": map[string]any{
								"application/json": map[string]any{
									"schema": map[string]any{
										"$ref": "#/components/schemas/APIError",
									},
								},
							},
						},
					},
				},
			},
		},
		"components": map[string]any{
			"securitySchemes": map[string]any{
				"bearerAuth": map[string]any{
					"type":         "http",
					"scheme":       "bearer",
					"description":  "API token authentication",
					"bearerFormat": "token",
				},
				"basicAuth": map[string]any{
					"type":        "http",
					"scheme":      "basic",
					"description": "Basic authentication with username and password",
				},
			},
			"schemas": map[string]any{
				"Version": map[string]any{
					"type": "object",
					"properties": map[string]any{
						"version": map[string]string{"type": "string", "description": "Gitea version"},
						"api":     map[string]string{"type": "string", "description": "API version"},
					},
				},
				"User": map[string]any{
					"type": "object",
					"properties": map[string]any{
						"id":       map[string]string{"type": "integer", "description": "User ID"},
						"login":    map[string]string{"type": "string", "description": "Username"},
						"email":    map[string]string{"type": "string", "description": "Email address"},
						"is_admin": map[string]string{"type": "boolean", "description": "Is site admin"},
					},
				},
				"APIError": map[string]any{
					"type":        "object",
					"description": "Structured error response following RFC 7807",
					"properties": map[string]any{
						"error": map[string]any{
							"type": "object",
							"properties": map[string]any{
								"code":              map[string]string{"type": "string", "description": "Machine-readable error code"},
								"message":           map[string]string{"type": "string", "description": "Human-readable error message"},
								"status":            map[string]string{"type": "integer", "description": "HTTP status code"},
								"documentation_url": map[string]string{"type": "string", "description": "URL to error documentation"},
								"request_id":        map[string]string{"type": "string", "description": "Request ID for tracing"},
								"details":           map[string]string{"type": "object", "description": "Additional error context"},
								"suggestions":       map[string]any{"type": "array", "items": map[string]string{"type": "string"}, "description": "Suggested actions"},
							},
						},
					},
				},
			},
		},
	}
}
