package api

import (
	"fmt"
	"net/http"

	"github.com/alexei/docker-watcher/internal/crypto"
	"github.com/alexei/docker-watcher/internal/webhook"
)

// settingsRequest is the expected JSON body for updating settings.
type settingsRequest struct {
	Domain           string `json:"domain"`
	ServerIP         string `json:"server_ip"`
	Network          string `json:"network"`
	SubdomainPattern string `json:"subdomain_pattern"`
	NotificationURL  string `json:"notification_url"`
	NpmURL           string `json:"npm_url"`
	NpmEmail         string `json:"npm_email"`
	NpmPassword      string `json:"npm_password"`
	PollingInterval  string `json:"polling_interval"`
}

// getSettings handles GET /api/settings.
func (s *Server) getSettings(w http.ResponseWriter, r *http.Request) {
	settings, err := s.store.GetSettings()
	if err != nil {
		respondError(w, http.StatusInternalServerError, "failed to get settings: "+err.Error())
		return
	}

	// Return settings without sensitive fields.
	respondJSON(w, http.StatusOK, map[string]any{
		"domain":            settings.Domain,
		"server_ip":         settings.ServerIP,
		"network":           settings.Network,
		"subdomain_pattern": settings.SubdomainPattern,
		"notification_url":  settings.NotificationURL,
		"npm_url":           settings.NpmURL,
		"npm_email":         settings.NpmEmail,
		"has_npm_password":  settings.NpmPassword != "",
		"polling_interval":  settings.PollingInterval,
		"updated_at":        settings.UpdatedAt,
	})
}

// updateSettings handles PUT /api/settings.
func (s *Server) updateSettings(w http.ResponseWriter, r *http.Request) {
	var req settingsRequest
	if !decodeJSON(w, r, &req) {
		return
	}

	existing, err := s.store.GetSettings()
	if err != nil {
		respondError(w, http.StatusInternalServerError, "failed to get settings: "+err.Error())
		return
	}

	updated := existing
	if req.Domain != "" {
		updated.Domain = req.Domain
	}
	if req.ServerIP != "" {
		updated.ServerIP = req.ServerIP
	}
	if req.Network != "" {
		updated.Network = req.Network
	}
	if req.SubdomainPattern != "" {
		updated.SubdomainPattern = req.SubdomainPattern
	}
	// Allow clearing notification URL.
	updated.NotificationURL = req.NotificationURL
	if req.NpmURL != "" {
		updated.NpmURL = req.NpmURL
	}
	if req.NpmEmail != "" {
		updated.NpmEmail = req.NpmEmail
	}
	if req.NpmPassword != "" {
		encPassword, err := crypto.Encrypt(s.encKey, req.NpmPassword)
		if err != nil {
			respondError(w, http.StatusInternalServerError, "failed to encrypt npm password: "+err.Error())
			return
		}
		updated.NpmPassword = encPassword
	}
	if req.PollingInterval != "" {
		updated.PollingInterval = req.PollingInterval
	}

	if err := s.store.UpdateSettings(updated); err != nil {
		respondError(w, http.StatusInternalServerError, "failed to update settings: "+err.Error())
		return
	}
	respondJSON(w, http.StatusOK, map[string]string{"status": "updated"})
}

// getWebhookURL handles GET /api/settings/webhook-url.
func (s *Server) getWebhookURL(w http.ResponseWriter, r *http.Request) {
	settings, err := s.store.GetSettings()
	if err != nil {
		respondError(w, http.StatusInternalServerError, "failed to get settings: "+err.Error())
		return
	}

	webhookURL := ""
	if settings.WebhookSecret != "" && settings.Domain != "" {
		webhookURL = fmt.Sprintf("https://%s/api/webhook/%s", settings.Domain, settings.WebhookSecret)
	}

	respondJSON(w, http.StatusOK, map[string]string{
		"webhook_url": webhookURL,
	})
}

// regenerateWebhookSecret handles POST /api/settings/regenerate.
func (s *Server) regenerateWebhookSecret(w http.ResponseWriter, r *http.Request) {
	secret, err := webhook.RegenerateWebhookSecret(s.store)
	if err != nil {
		respondError(w, http.StatusInternalServerError, "failed to regenerate webhook secret: "+err.Error())
		return
	}

	settings, err := s.store.GetSettings()
	if err != nil {
		respondError(w, http.StatusInternalServerError, "failed to get settings: "+err.Error())
		return
	}

	webhookURL := ""
	if settings.Domain != "" {
		webhookURL = fmt.Sprintf("https://%s/api/webhook/%s", settings.Domain, secret)
	}

	respondJSON(w, http.StatusOK, map[string]string{
		"webhook_url":    webhookURL,
		"webhook_secret": secret,
	})
}

