// Copyright 2026 Moko Consulting <hello@mokoconsulting.tech>
// SPDX-License-Identifier: GPL-3.0-or-later

package setting

import (
	"net/http"

	security_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/security"
	"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/templates"
	"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/context"
	security_service "code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/security"
)

const tplSettingsSecurity templates.TplName = "repo/settings/security"

// SecuritySettings displays the repo security scanning settings and alerts.
func SecuritySettings(ctx *context.Context) {
	ctx.Data["Title"] = ctx.Tr("repo.settings.security")
	ctx.Data["PageIsSettingsSecurity"] = true

	repoID := ctx.Repo.Repository.ID

	cfg, err := security_model.GetScannerConfig(ctx, repoID)
	if err != nil {
		ctx.ServerError("GetScannerConfig", err)
		return
	}
	ctx.Data["ScannerConfig"] = cfg

	alerts, err := security_model.GetAllAlerts(ctx, repoID)
	if err != nil {
		ctx.ServerError("GetAllAlerts", err)
		return
	}
	ctx.Data["SecurityAlerts"] = alerts

	counts, err := security_model.GetAlertCountsByRepo(ctx, repoID)
	if err != nil {
		ctx.ServerError("GetAlertCountsByRepo", err)
		return
	}
	ctx.Data["AlertCounts"] = counts

	ctx.HTML(http.StatusOK, tplSettingsSecurity)
}

// SecuritySettingsPost saves security scanner configuration.
func SecuritySettingsPost(ctx *context.Context) {
	cfg := &security_model.SecurityScannerConfig{
		RepoID:        ctx.Repo.Repository.ID,
		Enabled:       ctx.FormString("enabled") == "on",
		BlockOnPush:   ctx.FormString("block_on_push") == "on",
		SecretScanner: ctx.FormString("secret_scanner") == "on",
		DependScanner: ctx.FormString("depend_scanner") == "on",
		CodeScanner:   ctx.FormString("code_scanner") == "on",
		ConfigScanner: ctx.FormString("config_scanner") == "on",
		LicenseScanner: ctx.FormString("license_scanner") == "on",
	}

	if err := security_model.SaveScannerConfig(ctx, cfg); err != nil {
		ctx.ServerError("SaveScannerConfig", err)
		return
	}

	ctx.Flash.Success(ctx.Tr("repo.settings.security_saved"))
	ctx.Redirect(ctx.Repo.RepoLink + "/settings/security")
}

// SecurityScanNow triggers an immediate scan of the repository.
func SecurityScanNow(ctx *context.Context) {
	commit := ctx.Repo.Commit
	if commit == nil {
		ctx.Flash.Error("No commits found in repository")
		ctx.Redirect(ctx.Repo.RepoLink + "/settings/security")
		return
	}

	security_service.ScanOnPush(ctx, ctx.Repo.Repository, commit)

	ctx.Flash.Success(ctx.Tr("repo.settings.security_scan_complete"))
	ctx.Redirect(ctx.Repo.RepoLink + "/settings/security")
}

// SecurityAlertUpdate changes the status of a security alert.
func SecurityAlertUpdate(ctx *context.Context) {
	id := ctx.PathParamInt64("id")
	status := security_model.AlertStatus(ctx.FormString("status"))

	if status != security_model.AlertStatusResolved && status != security_model.AlertStatusDismissed {
		status = security_model.AlertStatusDismissed
	}

	alert, err := security_model.GetAlertByID(ctx, id)
	if err != nil {
		ctx.ServerError("GetAlertByID", err)
		return
	}
	if alert.RepoID != ctx.Repo.Repository.ID {
		ctx.NotFound(nil)
		return
	}

	if err := security_model.UpdateAlertStatus(ctx, id, status, ctx.Doer.ID); err != nil {
		ctx.ServerError("UpdateAlertStatus", err)
		return
	}

	ctx.Flash.Success("Alert updated")
	ctx.Redirect(ctx.Repo.RepoLink + "/settings/security")
}
