package ui

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"git.threefold.info/herocode/heroagent/pkg/servers/ui/routes" // Import the routes package
	"github.com/gofiber/fiber/v2"
	jetadapter "github.com/gofiber/template/jet/v2" // Aliased for clarity
)

// AppConfig holds the configuration for the UI application.
type AppConfig struct {
	// Any specific configurations can be added here later
}

// NewApp creates and configures a new Fiber application for the UI.
func NewApp(config AppConfig) *fiber.App {
	// Initialize Jet template engine
	// Using OSFileSystemLoader to load templates from the filesystem.
	// The path is relative to where the application is run.
	// Get current working directory and construct absolute path to views
	cwd, err := os.Getwd()
	if err != nil {
		panic("Failed to get current working directory: " + err.Error())
	}
	viewsPath := filepath.Join(cwd, "pkg", "servers", "ui", "views")

	// Validate that the views directory and key template files exist
	if _, err := os.Stat(viewsPath); os.IsNotExist(err) {
		panic("Views directory does not exist: " + viewsPath)
	}

	// Check for key template files
	baseLayoutPath := filepath.Join(viewsPath, "layouts", "base.jet")
	dashboardPath := filepath.Join(viewsPath, "pages", "dashboard.jet")
	navbarPath := filepath.Join(viewsPath, "components", "navbar.jet")
	sidebarPath := filepath.Join(viewsPath, "components", "sidebar.jet")

	requiredFiles := []string{baseLayoutPath, dashboardPath, navbarPath, sidebarPath}
	for _, filePath := range requiredFiles {
		if _, err := os.Stat(filePath); os.IsNotExist(err) {
			panic("Required template file does not exist: " + filePath)
		}
	}

	// Log the views path for debugging
	println("Views directory found at:", viewsPath)
	println("All required template files exist")

	// Create Fiber Jet adapter
	engine := jetadapter.New(viewsPath, ".jet")

	// Enable template reloading for development
	engine.Reload(true)

	// No custom functions for now

	// Create a new Fiber app with the configured Jet engine and enhanced error handling
	app := fiber.New(fiber.Config{
		Views: engine,
		ErrorHandler: func(c *fiber.Ctx, err error) error {
			// Log the detailed error
			log.Printf("ERROR: %v", err)

			// Check if it's a template rendering error
			if err.Error() != "" && (c.Route().Path != "" && c.Method() == "GET") {
				// Extract template name and line number from error message
				errorMsg := err.Error()
				templateInfo := "Unknown template"
				lineInfo := "Unknown line"
				variableInfo := "Unknown variable"

				// Try to extract template name and line number
				if strings.Contains(errorMsg, "Jet Runtime Error") {
					// Extract template and line number
					templateLineRegex := regexp.MustCompile(`"([^"]+)":(\d+)`)
					templateMatches := templateLineRegex.FindStringSubmatch(errorMsg)
					if len(templateMatches) >= 3 {
						templateInfo = templateMatches[1]
						lineInfo = templateMatches[2]
					}

					// Extract variable name
					varRegex := regexp.MustCompile(`there is no field or method '([^']+)'`)
					varMatches := varRegex.FindStringSubmatch(errorMsg)
					if len(varMatches) >= 2 {
						variableInfo = varMatches[1]
					}

					// Log more detailed information
					log.Printf("Template Error Details - Template: %s, Line: %s, Variable: %s",
						templateInfo, lineInfo, variableInfo)
				}

				// Create a more detailed error page
				errorHTML := fmt.Sprintf(`
					<html>
					<head>
						<title>Template Error</title>
						<style>
							body { font-family: Arial, sans-serif; margin: 20px; }
							.error-box { background-color: #f8d7da; border: 1px solid #f5c6cb; padding: 15px; border-radius: 5px; }
							.error-details { background-color: #f8f9fa; border: 1px solid #dee2e6; padding: 15px; border-radius: 5px; margin-top: 20px; }
							.code-context { background-color: #f0f0f0; padding: 10px; border-radius: 5px; font-family: monospace; }
							pre { white-space: pre-wrap; }
							.highlight { background-color: #ffeb3b; font-weight: bold; }
						</style>
					</head>
					<body>
						<h1>Template Error</h1>
						<div class="error-box">
							<h3>Error Details:</h3>
							<p><strong>Template:</strong> %s</p>
							<p><strong>Line:</strong> %s</p>
							<p><strong>Missing Variable:</strong> <span class="highlight">%s</span></p>
							<pre>%s</pre>
						</div>
						<div class="error-details">
							<h3>Debugging Tips:</h3>
							<p>1. Check if the variable <span class="highlight">%s</span> is passed to the template</p>
							<p>2. Visit <a href="/debug">/debug</a> to see available template variables</p>
							<p>3. Check for typos in variable names</p>
							<p>4. Ensure the variable is of the expected type</p>
							<p>5. Check the controller that renders this template to ensure all required data is provided</p>
						</div>
					</body>
					</html>
				`, templateInfo, lineInfo, variableInfo, errorMsg, variableInfo)

				return c.Status(fiber.StatusInternalServerError).Type("html").SendString(errorHTML)
			}

			// For other errors, use the default error handler
			return fiber.DefaultErrorHandler(c, err)
		},
	})

	// Setup static file serving
	// Files in ./pkg/servers/ui/static will be accessible via /static URL path
	app.Static("/static", "./pkg/servers/ui/static")

	// Setup routes
	routes.SetupRoutes(app)

	return app
}
