// Copyright 2026 MarketAlly. All rights reserved.
// SPDX-License-Identifier: MIT

package repo

import (
	"code.gitea.io/gitea/models/organization"
	user_model "code.gitea.io/gitea/models/user"
	"code.gitea.io/gitea/modules/log"
	"code.gitea.io/gitea/services/context"
)

// Pin handles pinning a repo to user profile or organization
func Pin(ctx *context.Context) {
	pinType := ctx.FormString("type")
	redirectTo := ctx.FormString("redirect_to")
	if redirectTo == "" {
		redirectTo = ctx.Repo.RepoLink
	}

	switch pinType {
	case "user":
		if err := user_model.PinRepoToUser(ctx, ctx.Doer.ID, ctx.Repo.Repository.ID); err != nil {
			if user_model.IsErrPinnedRepoLimit(err) {
				ctx.Flash.Error(ctx.Tr("repo.pin.error_limit"))
			} else {
				log.Error("PinRepoToUser failed: %v", err)
				ctx.Flash.Error(ctx.Tr("repo.pin.error_generic"))
			}
		} else {
			ctx.Flash.Success(ctx.Tr("repo.pin.success_profile"))
		}

	case "org":
		if !ctx.Repo.Repository.Owner.IsOrganization() {
			ctx.Flash.Error(ctx.Tr("repo.pin.error_not_org"))
			ctx.Redirect(redirectTo)
			return
		}

		// Check if user is a member of the org
		isMember, err := organization.IsOrganizationMember(ctx, ctx.Repo.Repository.OwnerID, ctx.Doer.ID)
		if err != nil {
			log.Error("IsOrganizationMember failed: %v", err)
			ctx.Flash.Error(ctx.Tr("repo.pin.error_generic"))
			ctx.Redirect(redirectTo)
			return
		}
		if !isMember {
			ctx.Flash.Error(ctx.Tr("repo.pin.error_not_member"))
			ctx.Redirect(redirectTo)
			return
		}

		// Use CreateOrgPinnedRepo
		pinnedRepo := &organization.OrgPinnedRepo{
			OrgID:  ctx.Repo.Repository.OwnerID,
			RepoID: ctx.Repo.Repository.ID,
		}
		if err := organization.CreateOrgPinnedRepo(ctx, pinnedRepo); err != nil {
			if _, ok := err.(organization.ErrOrgPinnedRepoAlreadyExist); ok {
				ctx.Flash.Info(ctx.Tr("repo.pin.already_pinned_org"))
			} else {
				log.Error("CreateOrgPinnedRepo failed: %v", err)
				ctx.Flash.Error(ctx.Tr("repo.pin.error_generic"))
			}
		} else {
			ctx.Flash.Success(ctx.Tr("repo.pin.success_org"))
		}

	default:
		ctx.Flash.Error(ctx.Tr("repo.pin.error_invalid_type"))
	}

	ctx.Redirect(redirectTo)
}

// Unpin handles unpinning a repo from user profile or organization
func Unpin(ctx *context.Context) {
	pinType := ctx.FormString("type")
	redirectTo := ctx.FormString("redirect_to")
	if redirectTo == "" {
		redirectTo = ctx.Repo.RepoLink
	}

	switch pinType {
	case "user":
		if err := user_model.UnpinRepoFromUser(ctx, ctx.Doer.ID, ctx.Repo.Repository.ID); err != nil {
			log.Error("UnpinRepoFromUser failed: %v", err)
			ctx.Flash.Error(ctx.Tr("repo.pin.error_generic"))
		} else {
			ctx.Flash.Success(ctx.Tr("repo.pin.unpin_success_profile"))
		}

	case "org":
		if !ctx.Repo.Repository.Owner.IsOrganization() {
			ctx.Flash.Error(ctx.Tr("repo.pin.error_not_org"))
			ctx.Redirect(redirectTo)
			return
		}

		// Check if user is a member of the org
		isMember, err := organization.IsOrganizationMember(ctx, ctx.Repo.Repository.OwnerID, ctx.Doer.ID)
		if err != nil {
			log.Error("IsOrganizationMember failed: %v", err)
			ctx.Flash.Error(ctx.Tr("repo.pin.error_generic"))
			ctx.Redirect(redirectTo)
			return
		}
		if !isMember {
			ctx.Flash.Error(ctx.Tr("repo.pin.error_not_member"))
			ctx.Redirect(redirectTo)
			return
		}

		if err := organization.DeleteOrgPinnedRepo(ctx, ctx.Repo.Repository.OwnerID, ctx.Repo.Repository.ID); err != nil {
			log.Error("DeleteOrgPinnedRepo failed: %v", err)
			ctx.Flash.Error(ctx.Tr("repo.pin.error_generic"))
		} else {
			ctx.Flash.Success(ctx.Tr("repo.pin.unpin_success_org"))
		}

	default:
		ctx.Flash.Error(ctx.Tr("repo.pin.error_invalid_type"))
	}

	ctx.Redirect(redirectTo)
}
