package api

import (
	"embed"
	"html/template"
	"io/fs"
	"log"
	"net/http"

	"github.com/go-chi/chi/v5"
	"github.com/johanj/vault1984/lib"
)

// NewRouter creates the main router with all routes registered.
func NewRouter(cfg *lib.Config, webFS embed.FS, templateFS embed.FS) *chi.Mux {
	// Parse all website templates (nil if no templates embedded, e.g. tests)
	tmpl, _ := template.ParseFS(templateFS, "templates/*.html")

	// Helper: render a marketing page
	renderPage := func(w http.ResponseWriter, page, title, desc, activeNav string) {
		if tmpl == nil {
			http.Error(w, "templates not available", 500)
			return
		}
		w.Header().Set("Content-Type", "text/html; charset=utf-8")
		if err := tmpl.ExecuteTemplate(w, "base.html", map[string]string{
			"Page": page, "Title": title, "Desc": desc, "ActiveNav": activeNav,
		}); err != nil {
			log.Printf("template error: %v", err)
			http.Error(w, "Internal Server Error", 500)
		}
	}

	r := chi.NewRouter()
	h := NewHandlers(cfg)

	// Global middleware
	r.Use(LoggingMiddleware)
	r.Use(CORSMiddleware)
	r.Use(SecurityHeadersMiddleware)
	r.Use(RateLimitMiddleware(120))       // 120 req/min per IP
	r.Use(L1Middleware(cfg.DataDir))      // stateless: extract L1 from Bearer, open DB, forget

	// Health check (unauthenticated — no Bearer needed)
	r.Get("/health", h.Health)

	// Auth endpoints (unauthenticated — no Bearer, DB found by glob)
	r.Get("/api/auth/status", h.AuthStatus)
	r.Post("/api/auth/register/begin", h.AuthRegisterBegin)
	r.Post("/api/auth/register/complete", h.AuthRegisterComplete)
	r.Post("/api/auth/login/begin", h.AuthLoginBegin)
	r.Post("/api/auth/login/complete", h.AuthLoginComplete)

	// Legacy setup (only works when no credentials exist — for tests)
	r.Post("/api/auth/setup", h.Setup)

	// API routes (authenticated — L1 in Bearer, already validated by L1Middleware)
	r.Route("/api", func(r chi.Router) {
		mountAPIRoutes(r, h)
	})

	r.Get("/geo", h.GeoLookup)

	// --- Vault App UI at /app/* ---
	// Vault UI files (index.html, security.html, tokens.html) live in web/
	appRoot, err := fs.Sub(webFS, "web")
	if err == nil {
		appServer := http.FileServer(http.FS(appRoot))
		// /app → /app/
		r.Get("/app", func(w http.ResponseWriter, r *http.Request) {
			http.Redirect(w, r, "/app/", http.StatusMovedPermanently)
		})
		// /app/* → strip /app prefix and serve from web/
		r.Handle("/app/*", http.StripPrefix("/app", appServer))
	}

	// --- Website static assets at root ---
	serveEmbedded := func(path, contentType string) http.HandlerFunc {
		return func(w http.ResponseWriter, r *http.Request) {
			data, err := fs.ReadFile(webFS, "web/"+path)
			if err != nil {
				http.NotFound(w, r)
				return
			}
			w.Header().Set("Content-Type", contentType)
			w.Write(data)
		}
	}
	r.Get("/vault1984.css", serveEmbedded("vault1984.css", "text/css; charset=utf-8"))
	r.Get("/worldmap.svg", serveEmbedded("worldmap.svg", "image/svg+xml"))
	r.Get("/favicon.svg", serveEmbedded("favicon.svg", "image/svg+xml"))

	// --- Marketing Site ---
	// Server-rendered Go templates — agent-friendly, no JS required.
	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		renderPage(w, "landing",
			"Vault1984 — Password manager for humans with AI assistants",
			"Password manager built for humans with AI assistants. Two-tier encryption keeps agents useful and secrets safe.", "")
	})
	r.Get("/hosted", func(w http.ResponseWriter, r *http.Request) {
		renderPage(w, "hosted", "Hosted — Vault1984",
			"Your vault needs to work everywhere. 22 regions. $12/yr.", "hosted")
	})
	r.Get("/pricing", func(w http.ResponseWriter, r *http.Request) {
		renderPage(w, "pricing", "Pricing — Vault1984",
			"No tiers. No per-seat. No surprises. Self-host free or hosted $12/yr.", "pricing")
	})
	r.Get("/install", func(w http.ResponseWriter, r *http.Request) {
		renderPage(w, "install", "Install — Vault1984",
			"Self-host vault1984. One binary. No Docker. No Postgres.", "install")
	})
	r.Get("/privacy", func(w http.ResponseWriter, r *http.Request) {
		renderPage(w, "privacy", "Privacy Policy — Vault1984",
			"No analytics. No tracking. No data sales.", "")
	})
	r.Get("/terms", func(w http.ResponseWriter, r *http.Request) {
		renderPage(w, "terms", "Terms of Service — Vault1984", "", "")
	})
	r.Get("/sources", func(w http.ResponseWriter, r *http.Request) {
		renderPage(w, "sources", "Sources — Vault1984",
			"Real users. Real quotes. All verified.", "")
	})
	// Integration guides (SEO pages)
	r.Get("/integrations/claude-code", func(w http.ResponseWriter, r *http.Request) {
		renderPage(w, "claude-code",
			"Vault1984 + Claude Code — Secure MCP credential access",
			"Give Claude Code secure access to credentials and TOTP via MCP. Two-tier encryption keeps personal data sealed.", "integrations")
	})
	r.Get("/integrations/codex", func(w http.ResponseWriter, r *http.Request) {
		renderPage(w, "codex",
			"Vault1984 + OpenAI Codex — REST API and MCP integration",
			"Connect Codex to your vault via REST API or MCP. Scoped tokens, TOTP generation, field-level encryption.", "integrations")
	})
	r.Get("/integrations/openclaw", func(w http.ResponseWriter, r *http.Request) {
		renderPage(w, "openclaw",
			"Vault1984 + OpenClaw — Multi-agent credential management",
			"Give your OpenClaw agents scoped access to credentials. Two-tier encryption for autonomous agents.", "integrations")
	})
	r.Get("/integrations/openclaw/cn", func(w http.ResponseWriter, r *http.Request) {
		renderPage(w, "openclaw-cn",
			"Vault1984 + OpenClaw — AI 智能体凭据管理",
			"为 OpenClaw 智能体提供安全凭据访问。两层加密，共享字段 AI 可读，个人字段仅生物识别解锁。", "integrations")
	})

	r.Get("/homepage2", func(w http.ResponseWriter, r *http.Request) {
		renderPage(w, "landing",
			"Vault1984 — Password manager for humans with AI assistants",
			"Password manager built for humans with AI assistants. Two-tier encryption keeps agents useful and secrets safe.", "")
	})

	// SEO
	r.Get("/robots.txt", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/plain")
		w.Write([]byte("User-agent: *\nAllow: /\nSitemap: https://vault1984.com/sitemap.xml\n"))
	})
	r.Get("/sitemap.xml", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/xml")
		pages := []string{
			"/", "/hosted", "/pricing", "/install", "/privacy", "/terms",
			"/integrations/claude-code", "/integrations/codex",
			"/integrations/openclaw", "/integrations/openclaw/cn",
		}
		xml := `<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">`
		for _, p := range pages {
			xml += `<url><loc>https://vault1984.com` + p + `</loc></url>`
		}
		xml += `</urlset>`
		w.Write([]byte(xml))
	})

	return r
}

// mountAPIRoutes registers the authenticated API handlers on the given router.
// Used by both self-hosted (/api/*) and hosted (/{vault_id}/api/*) routes.
func mountAPIRoutes(r chi.Router, h *Handlers) {
	// Vault info (for Tokens page config snippets)
	r.Get("/vault-info", h.VaultInfo)

	// Entries CRUD
	r.Get("/entries", h.ListEntries)
	r.Post("/entries", h.CreateEntry)
	r.Get("/entries/{id}", h.GetEntry)
	r.Put("/entries/{id}", h.UpdateEntry)
	r.Delete("/entries/{id}", h.DeleteEntry)

	// Search
	r.Get("/search", h.SearchEntries)

	// Password generator
	r.Get("/generate", h.GeneratePassword)

	// Import
	r.Post("/import", h.ImportEntries)
	r.Post("/import/confirm", h.ImportConfirm)

	// Audit log
	r.Get("/audit", h.GetAuditLog)

	// Extension API
	r.Get("/ext/totp/{id}", h.GetTOTP)
	r.Get("/ext/match", h.MatchURL)
	r.Post("/ext/map", h.MapFields)

	// MCP Token management
	r.Post("/mcp-tokens", h.HandleCreateMCPToken)
	r.Get("/mcp-tokens", h.HandleListMCPTokens)
	r.Delete("/mcp-tokens/{id}", h.HandleDeleteMCPToken)

	// Backups
	r.Get("/backups", h.ListBackups)
	r.Post("/backups", h.CreateBackup)
	r.Post("/backups/restore", h.RestoreBackup)

	// Agent management
	r.Post("/agents", h.HandleCreateAgent)
	r.Get("/agents", h.HandleListAgents)
	r.Get("/agents/{id}", h.HandleGetAgent)
	r.Put("/agents/{id}/whitelist", h.HandleUpdateAgentWhitelist)
	r.Put("/agents/{id}/rate-limits", h.HandleUpdateAgentRateLimits)
	r.Post("/agents/{id}/lock", h.HandleLockAgent)
	r.Post("/agents/{id}/unlock", h.HandleUnlockAgent)
	r.Delete("/agents/{id}", h.HandleRevokeAgent)

	// Vault lock
	r.Get("/vault-lock", h.HandleVaultLockStatus)
	r.Post("/vault-unlock", h.HandleVaultUnlock)

	// WebAuthn
	r.Post("/webauthn/register/begin", h.HandleWebAuthnRegisterBegin)
	r.Post("/webauthn/register/complete", h.HandleWebAuthnRegisterComplete)
	r.Post("/webauthn/auth/begin", h.HandleWebAuthnAuthBegin)
	r.Post("/webauthn/auth/complete", h.HandleWebAuthnAuthComplete)
	r.Get("/webauthn/credentials", h.HandleListWebAuthnCredentials)
	r.Delete("/webauthn/credentials/{id}", h.HandleDeleteWebAuthnCredential)
}
