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

package repo

import (
	"fmt"
	"net/http"

	issues_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/issues"
	"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
	"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/context"
	issue_service "code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/issue"
)

// UpdateIssueCustomStatus handles POST to set a custom status on an issue.
// If the chosen status has ClosesIssue=true, the issue is automatically closed.
// If the chosen status has ClosesIssue=false and the issue is closed, it is reopened.
func UpdateIssueCustomStatus(ctx *context.Context) {
	issueID := ctx.PathParamInt64("id")
	statusID := ctx.FormInt64("status_id")

	issue, err := issues_model.GetIssueByID(ctx, issueID)
	if err != nil {
		ctx.ServerError("GetIssueByID", err)
		return
	}

	// Validate the status belongs to this repo's org (or is being cleared).
	if statusID > 0 {
		statusDef, err := issues_model.GetIssueStatusDefByID(ctx, statusID)
		if err != nil {
			ctx.ServerError("GetIssueStatusDefByID", err)
			return
		}
		if statusDef.OrgID != ctx.Repo.Repository.OwnerID {
			ctx.NotFound(nil)
			return
		}

		// Handle automatic close/reopen based on the status definition.
		if statusDef.ClosesIssue && !issue.IsClosed {
			if err := issue_service.CloseIssue(ctx, issue, ctx.Doer, ""); err != nil {
				log.Error("UpdateIssueCustomStatus: CloseIssue: %v", err)
			}
		} else if !statusDef.ClosesIssue && issue.IsClosed {
			if err := issue_service.ReopenIssue(ctx, issue, ctx.Doer, ""); err != nil {
				log.Error("UpdateIssueCustomStatus: ReopenIssue: %v", err)
			}
		}
	}

	if err := issues_model.SetIssueStatusID(ctx, issueID, statusID); err != nil {
		ctx.ServerError("SetIssueStatusID", err)
		return
	}

	ctx.Redirect(fmt.Sprintf("%s/issues/%d", ctx.Repo.RepoLink, issue.Index), http.StatusSeeOther)
}
