package openapi

import (
	"embed"
	"encoding/json"
	"io/fs"
	"log"
	"net/http"
	"strings"
)

//go:embed specs/*.json
var specFiles embed.FS

var mergedSpec []byte

func init() {
	spec, err := buildSpec()
	if err != nil {
		log.Fatalf("openapi: build spec: %v", err)
	}
	mergedSpec = spec
}

func buildSpec() ([]byte, error) {
	base, err := loadJSON("specs/base.json")
	if err != nil {
		return nil, err
	}

	schemas, err := loadJSON("specs/schemas.json")
	if err != nil {
		return nil, err
	}
	if comps, ok := schemas["components"]; ok {
		base["components"] = comps
	}

	allPaths := make(map[string]interface{})

	entries, err := fs.ReadDir(specFiles, "specs")
	if err != nil {
		return nil, err
	}

	for _, entry := range entries {
		name := entry.Name()
		if name == "base.json" || name == "schemas.json" || !strings.HasSuffix(name, ".json") {
			continue
		}
		partial, err := loadJSON("specs/" + name)
		if err != nil {
			return nil, err
		}
		if paths, ok := partial["paths"].(map[string]interface{}); ok {
			for path, ops := range paths {
				allPaths[path] = ops
			}
		}
	}

	base["paths"] = allPaths

	return json.MarshalIndent(base, "", "  ")
}

func loadJSON(path string) (map[string]interface{}, error) {
	data, err := specFiles.ReadFile(path)
	if err != nil {
		return nil, err
	}
	var m map[string]interface{}
	if err := json.Unmarshal(data, &m); err != nil {
		return nil, err
	}
	return m, nil
}

func SpecHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	w.Header().Set("Cache-Control", "public, max-age=3600")
	w.Write(mergedSpec)
}

const swaggerHTML = `<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Calendar & Contacts API – Docs</title>
  <link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css">
  <style>
    html { box-sizing: border-box; overflow-y: scroll; }
    *, *:before, *:after { box-sizing: inherit; }
    body { margin: 0; background: #fafafa; }
    .topbar { display: none; }
  </style>
</head>
<body>
  <div id="swagger-ui"></div>
  <script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js"></script>
  <script>
    SwaggerUIBundle({
      url: "/openapi.json",
      dom_id: "#swagger-ui",
      deepLinking: true,
      presets: [
        SwaggerUIBundle.presets.apis,
        SwaggerUIBundle.SwaggerUIStandalonePreset
      ],
      layout: "BaseLayout"
    });
  </script>
</body>
</html>`

func DocsHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	w.Write([]byte(swaggerHTML))
}
