package ui

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

	"git.wntrmute.dev/mc/mcias/internal/audit"
	"git.wntrmute.dev/mc/mcias/internal/model"
)

func (u *UIServer) handleSSOClientsPage(w http.ResponseWriter, r *http.Request) {
	csrfToken, err := u.setCSRFCookies(w)
	if err != nil {
		u.logger.Error("sso-clients: set CSRF cookies", "error", err)
		http.Error(w, "internal error", http.StatusInternalServerError)
		return
	}

	clients, err := u.db.ListSSOClients()
	if err != nil {
		u.logger.Error("sso-clients: list clients", "error", err)
		u.renderError(w, r, http.StatusInternalServerError, "failed to load SSO clients")
		return
	}

	u.render(w, "sso_clients", SSOClientsData{
		PageData: PageData{CSRFToken: csrfToken, ActorName: u.actorName(r), IsAdmin: isAdmin(r)},
		Clients:  clients,
	})
}

func (u *UIServer) handleCreateSSOClientUI(w http.ResponseWriter, r *http.Request) {
	r.Body = http.MaxBytesReader(w, r.Body, maxFormBytes)
	if err := r.ParseForm(); err != nil {
		u.renderError(w, r, http.StatusBadRequest, "invalid form submission")
		return
	}

	clientID := strings.TrimSpace(r.FormValue("client_id"))
	redirectURI := strings.TrimSpace(r.FormValue("redirect_uri"))
	tagsStr := strings.TrimSpace(r.FormValue("tags"))

	if clientID == "" || redirectURI == "" {
		u.renderError(w, r, http.StatusBadRequest, "client_id and redirect_uri are required")
		return
	}

	var tags []string
	if tagsStr != "" {
		for _, t := range strings.Split(tagsStr, ",") {
			t = strings.TrimSpace(t)
			if t != "" {
				tags = append(tags, t)
			}
		}
	}

	claims := claimsFromContext(r.Context())
	var actorID *int64
	if claims != nil {
		if acct, err := u.db.GetAccountByUUID(claims.Subject); err == nil {
			actorID = &acct.ID
		}
	}

	c, err := u.db.CreateSSOClient(clientID, redirectURI, tags, actorID)
	if err != nil {
		u.renderError(w, r, http.StatusBadRequest, err.Error())
		return
	}

	u.writeAudit(r, model.EventSSOClientCreated, actorID, nil,
		audit.JSON("client_id", c.ClientID))

	u.render(w, "sso_client_row", c)
}

func (u *UIServer) handleToggleSSOClient(w http.ResponseWriter, r *http.Request) {
	clientID := r.PathValue("clientId")
	r.Body = http.MaxBytesReader(w, r.Body, maxFormBytes)
	if err := r.ParseForm(); err != nil {
		u.renderError(w, r, http.StatusBadRequest, "invalid form")
		return
	}

	enabled := r.FormValue("enabled") == "true"
	if err := u.db.UpdateSSOClient(clientID, nil, nil, &enabled); err != nil {
		u.renderError(w, r, http.StatusInternalServerError, "failed to update SSO client")
		return
	}

	claims := claimsFromContext(r.Context())
	var actorID *int64
	if claims != nil {
		if acct, err := u.db.GetAccountByUUID(claims.Subject); err == nil {
			actorID = &acct.ID
		}
	}
	u.writeAudit(r, model.EventSSOClientUpdated, actorID, nil,
		fmt.Sprintf(`{"client_id":%q,"enabled":%v}`, clientID, enabled))

	c, err := u.db.GetSSOClient(clientID)
	if err != nil {
		u.renderError(w, r, http.StatusInternalServerError, "failed to reload SSO client")
		return
	}
	u.render(w, "sso_client_row", c)
}

func (u *UIServer) handleDeleteSSOClientUI(w http.ResponseWriter, r *http.Request) {
	clientID := r.PathValue("clientId")

	if err := u.db.DeleteSSOClient(clientID); err != nil {
		u.renderError(w, r, http.StatusInternalServerError, "failed to delete SSO client")
		return
	}

	claims := claimsFromContext(r.Context())
	var actorID *int64
	if claims != nil {
		if acct, err := u.db.GetAccountByUUID(claims.Subject); err == nil {
			actorID = &acct.ID
		}
	}
	u.writeAudit(r, model.EventSSOClientDeleted, actorID, nil,
		audit.JSON("client_id", clientID))

	// Return empty response so HTMX removes the row.
	w.WriteHeader(http.StatusOK)
}
