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

package repo

import (
	"encoding/json"
	"net/http"

	repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
	"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/context"
)

// apiManifest is the JSON representation of a repo manifest.
type apiManifest struct {
	Name             string `json:"name"`
	Org              string `json:"org"`
	Description      string `json:"description"`
	Version          string `json:"version"`
	LicenseSPDX      string `json:"license_spdx"`
	LicenseName      string `json:"license_name"`
	VersionPrefix    string `json:"version_prefix"`
	ElementName      string `json:"element_name"`
	Platform         string `json:"platform"`
	StandardsVersion string `json:"standards_version"`
	StandardsSource  string `json:"standards_source"`
	DisplayName      string `json:"display_name"`
	Maintainer       string `json:"maintainer"`
	MaintainerURL    string `json:"maintainer_url"`
	InfoURL          string `json:"info_url"`
	TargetVersion    string `json:"target_version"`
	PHPMinimum       string `json:"php_minimum"`
	Language         string `json:"language"`
	PackageType      string `json:"package_type"`
	EntryPoint       string `json:"entry_point"`
}

// GetRepoManifest returns the manifest settings for a repository.
func GetRepoManifest(ctx *context.APIContext) {
	// swagger:operation GET /repos/{owner}/{repo}/manifest repository repoGetManifest
	// ---
	// summary: Get repo manifest settings
	// produces:
	// - application/json
	// responses:
	//   "200":
	//     "$ref": "#/responses/Manifest"
	//   "404":
	//     "$ref": "#/responses/notFound"
	m, err := repo_model.GetRepoManifest(ctx, ctx.Repo.Repository.ID)
	if err != nil {
		ctx.APIErrorInternal(err)
		return
	}
	if m == nil {
		// Return defaults from repo metadata.
		ctx.JSON(http.StatusOK, &apiManifest{
			Name:        ctx.Repo.Repository.Name,
			Org:         ctx.Repo.Repository.OwnerName,
			Description: ctx.Repo.Repository.Description,
		})
		return
	}
	ctx.JSON(http.StatusOK, &apiManifest{
		Name:             m.Name,
		Org:              m.Org,
		Description:      m.Description,
		Version:          m.Version,
		LicenseSPDX:      m.LicenseSPDX,
		LicenseName:      m.LicenseName,
		VersionPrefix:    m.VersionPrefix,
		ElementName:      m.FullElementName(),
		Platform:         m.Platform,
		StandardsVersion: m.StandardsVersion,
		StandardsSource:  m.StandardsSource,
		DisplayName:      m.DisplayName,
		Maintainer:       m.Maintainer,
		MaintainerURL:    m.MaintainerURL,
		InfoURL:          m.InfoURL,
		TargetVersion:    m.TargetVersion,
		PHPMinimum:       m.PHPMinimum,
		Language:         m.Language,
		PackageType:      m.PackageType,
		EntryPoint:       m.EntryPoint,
	})
}

// UpdateRepoManifest updates the manifest settings for a repository.
func UpdateRepoManifest(ctx *context.APIContext) {
	// swagger:operation PUT /repos/{owner}/{repo}/manifest repository repoUpdateManifest
	// ---
	// summary: Update repo manifest settings
	// consumes:
	// - application/json
	// produces:
	// - application/json
	// responses:
	//   "200":
	//     "$ref": "#/responses/Manifest"
	var req apiManifest
	if err := json.NewDecoder(ctx.Req.Body).Decode(&req); err != nil {
		ctx.APIError(http.StatusBadRequest, err)
		return
	}

	m := &repo_model.RepoManifest{
		RepoID:           ctx.Repo.Repository.ID,
		Name:             req.Name,
		Org:              req.Org,
		Description:      req.Description,
		Version:          req.Version,
		LicenseSPDX:      req.LicenseSPDX,
		LicenseName:      req.LicenseName,
		VersionPrefix:    req.VersionPrefix,
		ElementName:      req.ElementName,
		Platform:         req.Platform,
		StandardsVersion: req.StandardsVersion,
		StandardsSource:  req.StandardsSource,
		DisplayName:      req.DisplayName,
		Maintainer:       req.Maintainer,
		MaintainerURL:    req.MaintainerURL,
		InfoURL:          req.InfoURL,
		TargetVersion:    req.TargetVersion,
		PHPMinimum:       req.PHPMinimum,
		Language:         req.Language,
		PackageType:      req.PackageType,
		EntryPoint:       req.EntryPoint,
	}

	if err := repo_model.CreateOrUpdateRepoManifest(ctx, m); err != nil {
		ctx.APIErrorInternal(err)
		return
	}

	ctx.JSON(http.StatusOK, &apiManifest{
		Name:             m.Name,
		Org:              m.Org,
		Description:      m.Description,
		Version:          m.Version,
		LicenseSPDX:      m.LicenseSPDX,
		LicenseName:      m.LicenseName,
		VersionPrefix:    m.VersionPrefix,
		ElementName:      m.FullElementName(),
		Platform:         m.Platform,
		StandardsVersion: m.StandardsVersion,
		StandardsSource:  m.StandardsSource,
		DisplayName:      m.DisplayName,
		Maintainer:       m.Maintainer,
		MaintainerURL:    m.MaintainerURL,
		InfoURL:          m.InfoURL,
		TargetVersion:    m.TargetVersion,
		PHPMinimum:       m.PHPMinimum,
		Language:         m.Language,
		PackageType:      m.PackageType,
		EntryPoint:       m.EntryPoint,
	})
}
