package middleware

import (
	"baron-sso-backend/internal/service"
	"log/slog"
	"net/url"
	"os"
	"strings"

	"github.com/gofiber/fiber/v2"
)

// TenantContextConfig defines the configuration for Tenant context middleware
type TenantContextConfig struct {
	TenantService service.TenantService
}

// TenantContextMiddleware identifies the tenant based on the Host header (subdomain or custom domain)
func TenantContextMiddleware(config TenantContextConfig) fiber.Handler {
	userfrontURL := os.Getenv("USERFRONT_URL")
	baseDomain := ""
	if userfrontURL != "" {
		if u, err := url.Parse(userfrontURL); err == nil {
			baseDomain = u.Hostname()
		}
	}

	return func(c *fiber.Ctx) error {
		hostname := c.Hostname()
		if hostname == "" {
			hostname = string(c.Request().Header.Host())
		}

		if hostname == "" {
			return c.Next()
		}

		// 1. If it's the exact base domain or localhost, no specific tenant context from host
		if hostname == baseDomain || hostname == "localhost" || hostname == "127.0.0.1" {
			return c.Next()
		}

		// 2. Try to find by registered custom domain
		tenant, err := config.TenantService.GetTenantByDomain(c.Context(), hostname)
		if err == nil && tenant != nil {
			slog.Debug("Tenant identified by custom domain", "hostname", hostname, "tenantID", tenant.ID)
			c.Locals("tenant_id", tenant.ID)
			c.Locals("tenant_slug", tenant.Slug)
			return c.Next()
		}

		// 3. Try to find by subdomain (slug.baseDomain)
		if baseDomain != "" && strings.HasSuffix(hostname, "."+baseDomain) {
			slug := strings.TrimSuffix(hostname, "."+baseDomain)
			// Handle cases like "www.sso.hmac.kr" if baseDomain is "sso.hmac.kr"
			if slug != "" && slug != "www" {
				tenant, err := config.TenantService.GetTenantBySlug(c.Context(), slug)
				if err == nil && tenant != nil {
					slog.Debug("Tenant identified by subdomain slug", "slug", slug, "tenantID", tenant.ID)
					c.Locals("tenant_id", tenant.ID)
					c.Locals("tenant_slug", tenant.Slug)
					return c.Next()
				}
			}
		}

		return c.Next()
	}
}
