package docs

import (
	"bytes"
	"fmt"
	"net/http"
	"strings"

	"bookhoard/internal/database"
	"bookhoard/templates"

	"github.com/google/uuid"
	"github.com/labstack/echo/v5"
)

// HTTPHandler wraps the docs handler for Echo framework
type HTTPHandler struct {
	docs *DocsHandler
}

// NewHTTPHandler creates a new docs HTTP handler
func NewHTTPHandler(docsPath string) *HTTPHandler {
	return &HTTPHandler{
		docs: NewDocsHandler(docsPath),
	}
}

// ShowDocumentation renders a documentation page
func (h *HTTPHandler) ShowDocumentation(c *echo.Context) error {
	// Get the document path from URL parameter
	docPath := c.Param("*")

	// Load the document
	doc, err := h.docs.LoadDocument(docPath)
	if err != nil {
		// Try to load as API endpoint
		if strings.HasPrefix(docPath, "api/") {
			return h.ShowAPIEndpoint(c, strings.TrimPrefix(docPath, "api/"))
		}

		// Return error page
		errorHTML := fmt.Sprintf(`<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document Not Found - Bookhoard</title>
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-900 text-gray-100 min-h-screen flex items-center justify-center">
    <div class="text-center">
        <h1 class="text-2xl font-bold mb-4">Document Not Found</h1>
        <p class="mb-4">%s</p>
        <a href="/docs" class="text-blue-400 hover:underline">Return to Documentation</a>
    </div>
</body>
</html>`, err.Error())

		return c.HTML(http.StatusNotFound, errorHTML)
	}

	// Get navigation
	nav := h.docs.BuildNavigation()

	// Check if user is authenticated via middleware
	var user templates.User
	if userID := c.Get("user"); userID != nil {
		dbUser := userID.(database.Users)
		var theme string
		if dbUser.Theme.Valid {
			theme = dbUser.Theme.String
		} else {
			theme = "tokyo-night"
		}
		user = templates.User{
			ID:       uuid.UUID(dbUser.ID.Bytes).String(),
			Username: dbUser.Username,
			Email:    dbUser.Email,
			Role:     dbUser.Role,
			Theme:    theme,
		}
	} else {
		// Create empty user for unauthenticated users
		user = templates.User{
			ID:       "",
			Username: "",
			Email:    "",
			Role:     "",
			Theme:    "tokyo-night",
		}
	}

	// Render documentation page
	var buf bytes.Buffer
	currentPath := c.Request().URL.Path
	err = templates.DocsLayout(*nav, *doc, user, currentPath).Render(c.Request().Context(), &buf)
	if err != nil {
		fmt.Printf("DOCS RENDER ERROR: %v\n", err)
		return c.HTML(http.StatusInternalServerError, "Failed to render page: "+err.Error())
	}
	fmt.Printf("DOCS: Successfully rendered %s (%d bytes)\n", docPath, buf.Len())
	return c.HTML(http.StatusOK, buf.String())
}

// ShowAPIEndpoint shows a specific API endpoint documentation
func (h *HTTPHandler) ShowAPIEndpoint(c *echo.Context, endpointPath string) error {
	// Check if user is logged in
	isLoggedIn := false
	if userID := c.Get("user_id"); userID != nil {
		isLoggedIn = true
	}

	// Get endpoint data for the explorer
	endpointInfo, err := h.docs.GetAPIEndpointData(endpointPath)
	_ = endpointInfo
	if err != nil {
		// Endpoint not found in explorer data, fall back to old behavior
		return h.showLegacyAPIEndpoint(c, endpointPath, isLoggedIn)
	}

	// Load the markdown documentation for this endpoint
	docPath := "api/" + endpointPath + ".md"
	doc, err := h.docs.LoadDocument(docPath)
	if err != nil {
		errorHTML := `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>API Endpoint Not Found - Bookhoard</title>
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-900 text-gray-100 min-h-screen flex items-center justify-center">
    <div class="text-center">
        <h1 class="text-2xl font-bold mb-4">API Endpoint Not Found</h1>
        <a href="/docs/api" class="text-blue-400 hover:underline">Return to API Documentation</a>
    </div>
</body>
</html>`

		return c.HTML(http.StatusNotFound, errorHTML)
	}

	// Get navigation
	nav := h.docs.BuildNavigation()

	// Check if user is authenticated via middleware
	var user templates.User
	if userID := c.Get("user"); userID != nil {
		dbUser := userID.(database.Users)
		var theme string
		if dbUser.Theme.Valid {
			theme = dbUser.Theme.String
		} else {
			theme = "tokyo-night"
		}
		user = templates.User{
			ID:       uuid.UUID(dbUser.ID.Bytes).String(),
			Username: dbUser.Username,
			Email:    dbUser.Email,
			Role:     dbUser.Role,
			Theme:    theme,
		}
	} else {
		// Create empty user for unauthenticated users
		user = templates.User{
			ID:       "",
			Username: "",
			Email:    "",
			Role:     "",
			Theme:    "tokyo-night",
		}
	}

	// Render API endpoint page
	var buf bytes.Buffer
	currentPath := c.Request().URL.Path
	err = templates.DocsLayout(*nav, *doc, user, currentPath).Render(c.Request().Context(), &buf)

	if err != nil {
		return c.HTML(http.StatusInternalServerError, "Failed to render page")
	}

	return c.HTML(http.StatusOK, buf.String())
}

// showLegacyAPIEndpoint shows API endpoint documentation without explorer data
func (h *HTTPHandler) showLegacyAPIEndpoint(c *echo.Context, endpointPath string, isLoggedIn bool) error {
	endpoints := h.docs.GetAPIEndpoints()

	// Find the endpoint
	var foundEndpoint *APIEndpoint
	for _, ep := range endpoints {
		if strings.HasSuffix(endpointPath, strings.TrimPrefix(ep.Path, "/api/")) {
			foundEndpoint = &ep
			break
		}
	}

	if foundEndpoint == nil {
		errorHTML := `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>API Endpoint Not Found - Bookhoard</title>
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-900 text-gray-100 min-h-screen flex items-center justify-center">
    <div class="text-center">
        <h1 class="text-2xl font-bold mb-4">API Endpoint Not Found</h1>
        <a href="/docs/api" class="text-blue-400 hover:underline">Return to API Documentation</a>
    </div>
</body>
</html>`

		return c.HTML(http.StatusNotFound, errorHTML)
	}

	// Get navigation
	nav := h.docs.BuildNavigation()

	// Check if user is authenticated via middleware
	var user templates.User
	currentPath := c.Request().URL.Path
	if userID := c.Get("user"); userID != nil {
		dbUser := userID.(database.Users)
		var theme string
		if dbUser.Theme.Valid {
			theme = dbUser.Theme.String
		} else {
			theme = "tokyo-night"
		}
		user = templates.User{
			ID:       uuid.UUID(dbUser.ID.Bytes).String(),
			Username: dbUser.Username,
			Email:    dbUser.Email,
			Role:     dbUser.Role,
			Theme:    theme,
		}
	} else {
		// Create empty user for unauthenticated users
		user = templates.User{
			ID:       "",
			Username: "",
			Email:    "",
			Role:     "",
			Theme:    "tokyo-night",
		}
	}

	// Render API endpoint page
	var buf bytes.Buffer
	err := templates.DocsLayout(*nav, templates.Document{
		Title:   foundEndpoint.Title,
		Content: fmt.Sprintf("<p>Documentation for <code>%s %s</code></p>", foundEndpoint.Method, foundEndpoint.Path),
		TOC:     []templates.TOCItem{},
		Breadcrumb: []templates.BreadcrumbItem{
			{Title: "Docs", URL: "/docs"},
			{Title: "API Reference", URL: "/docs/api"},
			{Title: foundEndpoint.Category, URL: "/docs/api"},
			{Title: foundEndpoint.Title, URL: ""},
		},
		Category:   "API Reference",
		SourceFile: "api",
	}, user, currentPath).Render(c.Request().Context(), &buf)

	if err != nil {
		return c.HTML(http.StatusInternalServerError, "Failed to render page")
	}

	return c.HTML(http.StatusOK, buf.String())
}

// DocsHome redirects to the documentation index
func (h *HTTPHandler) DocsHome(c *echo.Context) error {
	return c.Redirect(http.StatusFound, "/docs/index.md")
}

// APIHome shows the API documentation home page
func (h *HTTPHandler) APIHome(c *echo.Context) error {
	endpoints := h.docs.GetAPIEndpoints()
	nav := h.docs.BuildNavigation()

	// Check if user is authenticated via middleware
	var user templates.User
	currentPath := c.Request().URL.Path
	if userID := c.Get("user"); userID != nil {
		dbUser := userID.(database.Users)
		var theme string
		if dbUser.Theme.Valid {
			theme = dbUser.Theme.String
		} else {
			theme = "tokyo-night"
		}
		user = templates.User{
			ID:       uuid.UUID(dbUser.ID.Bytes).String(),
			Username: dbUser.Username,
			Email:    dbUser.Email,
			Role:     dbUser.Role,
			Theme:    theme,
		}
	} else {
		// Create empty user for unauthenticated users
		user = templates.User{
			ID:       "",
			Username: "",
			Email:    "",
			Role:     "",
			Theme:    "tokyo-night",
		}
	}

	// Build API documentation content
	content := "<h2>API Endpoints</h2><p>Complete API reference for Bookhoard v1.0.</p><ul>"
	for _, ep := range endpoints {
		content += fmt.Sprintf(`<li><a href="/docs/api%s"><strong>%s %s</strong></a> - %s</li>`,
			strings.TrimPrefix(ep.Path, "/api"),
			ep.Method,
			ep.Path,
			ep.Title,
		)
	}
	content += "</ul>"

	apiDoc := &templates.Document{
		Title:   "API Reference",
		Content: content,
		TOC:     []templates.TOCItem{},
		Breadcrumb: []templates.BreadcrumbItem{
			{Title: "Docs", URL: "/docs"},
			{Title: "Developer", URL: "/docs/developer"},
			{Title: "API Reference", URL: ""},
		},
		Category:   "API Reference",
		SourceFile: "developer/api-reference.md",
	}

	var buf bytes.Buffer
	err := templates.DocsLayout(*nav, *apiDoc, user, currentPath).Render(c.Request().Context(), &buf)

	if err != nil {
		return c.HTML(http.StatusInternalServerError, "Failed to render page")
	}

	return c.HTML(http.StatusOK, buf.String())
}

// Search searches through documentation
func (h *HTTPHandler) Search(c *echo.Context) error {
	query := c.QueryParam("q")
	if query == "" {
		return c.JSON(http.StatusBadRequest, map[string]string{
			"error": "query parameter 'q' is required",
		})
	}

	// Get all documents
	docs, err := h.docs.ListDocuments()
	if err != nil {
		return c.JSON(http.StatusInternalServerError, map[string]string{
			"error": "failed to list documents",
		})
	}

	// Simple search implementation
	var results []SearchResult
	queryLower := strings.ToLower(query)

	for _, docPath := range docs {
		doc, err := h.docs.LoadDocument(docPath)
		if err != nil {
			continue
		}

		// Check if title matches
		if strings.Contains(strings.ToLower(doc.Title), queryLower) {
			results = append(results, SearchResult{
				Title: doc.Title,
				URL:   "/docs/" + strings.TrimSuffix(doc.SourceFile, ".md"),
				Type:  "Documentation",
			})
			continue
		}

		// Check if content matches (simple substring search)
		contentLower := strings.ToLower(doc.Content)
		if strings.Contains(contentLower, queryLower) {
			results = append(results, SearchResult{
				Title: doc.Title,
				URL:   "/docs/" + strings.TrimSuffix(doc.SourceFile, ".md"),
				Type:  "Documentation",
			})
		}
	}

	return c.JSON(http.StatusOK, map[string]interface{}{
		"results": results,
		"count":   len(results),
	})
}

// SearchResult represents a search result
type SearchResult struct {
	Title string
	URL   string
	Type  string
}

// TryEndpoint executes an API endpoint (for the interactive explorer)
func (h *HTTPHandler) TryEndpoint(c *echo.Context) error {
	// This would execute the actual API request
	// For now, return a placeholder
	return c.JSON(http.StatusOK, map[string]interface{}{
		"message": "API explorer not yet implemented",
	})
}

// ServeSearchIndex serves the Lunr.js search index
func (h *HTTPHandler) ServeSearchIndex(c *echo.Context) error {
	index, err := h.docs.GenerateSearchIndex()
	if err != nil {
		return c.JSON(http.StatusInternalServerError, map[string]string{
			"error": "failed to generate search index",
		})
	}
	return c.JSON(http.StatusOK, index)
}
