package api

import "git.threesix.ai/jordan/persona-community-5/pkg/openapi"

// NewServiceSpec builds the OpenAPI specification for the persona-api service.
func NewServiceSpec() *openapi.OpenAPISpec {
	spec := openapi.NewOpenAPISpec("persona-api API", "1.0.0").
		WithDescription("REST API for the persona-api service").
		WithBearerSecurity("bearer", "JWT authentication token").
		WithTag("Health", "Service health endpoints").
		WithTag("Examples", "Example CRUD endpoints").
		WithTag("Personas", "AI persona generation and management")

	// Define reusable schemas
	spec.WithSchema("Example", openapi.Object(map[string]openapi.Schema{
		"id":          openapi.UUID().WithDescription("Unique identifier"),
		"name":        openapi.String().WithDescription("Name of the example").WithExample("My Example"),
		"description": openapi.String().WithDescription("Optional description").WithExample("A description"),
		"created_at":  openapi.DateTime().WithDescription("Creation timestamp"),
		"updated_at":  openapi.DateTime().WithDescription("Last update timestamp"),
	}, "id", "name"))

	spec.WithSchema("CreateExampleRequest", openapi.Object(map[string]openapi.Schema{
		"name":        openapi.StringWithMinMax(1, 100).WithDescription("Name of the example"),
		"description": openapi.StringWithMinMax(0, 500).WithDescription("Optional description"),
	}, "name"))

	spec.WithSchema("UpdateExampleRequest", openapi.Object(map[string]openapi.Schema{
		"name":        openapi.StringWithMinMax(1, 100).WithDescription("Updated name"),
		"description": openapi.StringWithMinMax(0, 500).WithDescription("Updated description"),
	}))

	// Health
	spec.AddPath("/api/persona-api/health", "get", map[string]any{
		"summary": "Health check",
		"tags":    []string{"Health"},
		"responses": map[string]any{
			"200": openapi.OpResponse("Service is healthy", openapi.Object(map[string]openapi.Schema{
				"service": openapi.String(),
				"status":  openapi.String(),
			})),
		},
	})

	// List examples
	spec.AddPath("/api/persona-api/examples", "get", map[string]any{
		"summary":     "List examples",
		"description": "Returns a paginated list of examples.",
		"tags":        []string{"Examples"},
		"parameters":  []any{openapi.PageParam(), openapi.PerPageParam()},
		"responses": map[string]any{
			"200": openapi.OpResponse("Success", openapi.ResponseSchema(openapi.RefArray("Example"))),
		},
	})

	// Get example
	spec.AddPath("/api/persona-api/examples/{id}", "get", map[string]any{
		"summary":    "Get example by ID",
		"tags":       []string{"Examples"},
		"parameters": []any{openapi.IDParam()},
		"responses": map[string]any{
			"200": openapi.OpResponse("Success", openapi.ResponseSchema(openapi.Ref("Example"))),
			"404": openapi.OpResponse("Not found", openapi.ErrorResponseSchema()),
		},
	})

	// Create example
	spec.AddPath("/api/persona-api/examples", "post", map[string]any{
		"summary":     "Create example",
		"description": "Creates a new example. Requires authentication.",
		"tags":        []string{"Examples"},
		"security":    []map[string][]string{{"bearer": {}}},
		"requestBody": openapi.RequestBody(openapi.Ref("CreateExampleRequest"), true),
		"responses": map[string]any{
			"201": openapi.OpResponse("Created", openapi.ResponseSchema(openapi.Ref("Example"))),
			"400": openapi.OpResponse("Bad request", openapi.ErrorResponseSchema()),
			"401": openapi.OpResponse("Unauthorized", openapi.ErrorResponseSchema()),
			"422": openapi.OpResponse("Validation error", openapi.ErrorResponseSchema()),
		},
	})

	// Update example
	spec.AddPath("/api/persona-api/examples/{id}", "put", map[string]any{
		"summary":     "Update example",
		"description": "Updates an existing example. Requires authentication.",
		"tags":        []string{"Examples"},
		"security":    []map[string][]string{{"bearer": {}}},
		"parameters":  []any{openapi.IDParam()},
		"requestBody": openapi.RequestBody(openapi.Ref("UpdateExampleRequest"), true),
		"responses": map[string]any{
			"200": openapi.OpResponse("Updated", openapi.ResponseSchema(openapi.Ref("Example"))),
			"400": openapi.OpResponse("Bad request", openapi.ErrorResponseSchema()),
			"401": openapi.OpResponse("Unauthorized", openapi.ErrorResponseSchema()),
			"404": openapi.OpResponse("Not found", openapi.ErrorResponseSchema()),
		},
	})

	// Delete example
	spec.AddPath("/api/persona-api/examples/{id}", "delete", map[string]any{
		"summary":     "Delete example",
		"description": "Deletes an example by ID. Requires authentication.",
		"tags":        []string{"Examples"},
		"security":    []map[string][]string{{"bearer": {}}},
		"parameters":  []any{openapi.IDParam()},
		"responses": map[string]any{
			"204": openapi.OpResponseNoContent(),
			"401": openapi.OpResponse("Unauthorized", openapi.ErrorResponseSchema()),
			"404": openapi.OpResponse("Not found", openapi.ErrorResponseSchema()),
		},
	})

	// ----- Persona schemas -----

	spec.WithSchema("Persona", openapi.Object(map[string]openapi.Schema{
		"id":          openapi.UUID().WithDescription("Unique identifier"),
		"name":        openapi.String().WithDescription("Persona display name"),
		"handle":      openapi.String().WithDescription("Unique URL-safe handle"),
		"gender":      openapi.String().WithDescription("Gender identity"),
		"description": openapi.String().WithDescription("Natural-language persona concept"),
		"tags":        openapi.Array(openapi.String()).WithDescription("Tags"),
		"spec_json":   openapi.Object(map[string]openapi.Schema{}, "").WithDescription("Generated persona specification"),
		"anchor_url":  openapi.String().WithDescription("Anchor image URL"),
		"avatar_url":  openapi.String().WithDescription("Avatar image URL"),
		"banner_url":  openapi.String().WithDescription("Banner image URL"),
		"image_urls":  openapi.Array(openapi.String()).WithDescription("Gallery image URLs"),
		"video_urls":  openapi.Array(openapi.String()).WithDescription("Video URLs"),
		"status":      openapi.String().WithDescription("Generation status: pending, generating, complete, failed"),
		"created_at":  openapi.DateTime().WithDescription("Creation timestamp"),
	}, "id", "name", "handle", "gender", "description", "status"))

	spec.WithSchema("CreatePersonaRequest", openapi.Object(map[string]openapi.Schema{
		"description": openapi.StringWithMinMax(3, 1000).WithDescription("Natural-language persona concept"),
		"gender":      openapi.String().WithDescription("Gender identity: woman, man, or non_binary"),
		"custom_name": openapi.String().WithDescription("Optional custom name override"),
	}, "description", "gender"))

	// ----- Persona endpoints -----

	spec.AddPath("/api/persona-api/personas", "post", map[string]any{
		"summary":     "Create persona",
		"description": "Creates a new persona and enqueues a generate_spec job. Returns 202 Accepted.",
		"tags":        []string{"Personas"},
		"security":    []map[string][]string{{"bearer": {}}},
		"requestBody": openapi.RequestBody(openapi.Ref("CreatePersonaRequest"), true),
		"responses": map[string]any{
			"202": openapi.OpResponse("Accepted", openapi.ResponseSchema(openapi.Ref("Persona"))),
			"400": openapi.OpResponse("Bad request", openapi.ErrorResponseSchema()),
			"401": openapi.OpResponse("Unauthorized", openapi.ErrorResponseSchema()),
			"422": openapi.OpResponse("Validation error", openapi.ErrorResponseSchema()),
		},
	})

	spec.AddPath("/api/persona-api/personas", "get", map[string]any{
		"summary":     "List personas",
		"description": "Returns a paginated list of personas ordered by creation date (newest first).",
		"tags":        []string{"Personas"},
		"security":    []map[string][]string{{"bearer": {}}},
		"parameters": []any{
			openapi.QueryParam("limit", "Maximum number of results (default 20, max 100)", false),
			openapi.QueryParam("offset", "Number of results to skip (default 0)", false),
		},
		"responses": map[string]any{
			"200": openapi.OpResponse("Success", openapi.ResponseSchema(openapi.RefArray("Persona"))),
			"401": openapi.OpResponse("Unauthorized", openapi.ErrorResponseSchema()),
		},
	})

	spec.AddPath("/api/persona-api/personas/{id}", "get", map[string]any{
		"summary":    "Get persona by ID",
		"tags":       []string{"Personas"},
		"security":   []map[string][]string{{"bearer": {}}},
		"parameters": []any{openapi.IDParam()},
		"responses": map[string]any{
			"200": openapi.OpResponse("Success", openapi.ResponseSchema(openapi.Ref("Persona"))),
			"401": openapi.OpResponse("Unauthorized", openapi.ErrorResponseSchema()),
			"404": openapi.OpResponse("Not found", openapi.ErrorResponseSchema()),
		},
	})

	return spec
}
