package api

import (
	"encoding/json"
	"fmt"
	"git.lumeweb.com/LumeWeb/gitea-github-proxy/config"
	"git.lumeweb.com/LumeWeb/gitea-github-proxy/db/model"
	"github.com/gorilla/mux"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"net/http"
)

type manifests struct {
	config *config.Config
	db     *gorm.DB
	logger *zap.Logger
}

type createdApp struct {
	Id            uint   `json:"id"`
	PEM           string `json:"pem"`
	WebhookSecret string `json:"webhook_secret"`
	ClientId      string `json:"client_id"`
	ClientSecret  string `json:"client_secret"`
	HTMLUrl       string `json:"html_url"`
}

func newManifests(config *config.Config, db *gorm.DB, logger *zap.Logger) *manifests {
	return &manifests{
		config: config,
		db:     db,
		logger: logger,
	}
}

func (m *manifests) handlerConversion(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)

	code := vars["code"]

	if len(code) == 0 {
		http.Error(w, "No code provided", http.StatusBadRequest)
		return
	}

	appRecord := &model.Apps{Code: code}

	if err := m.db.First(appRecord).Error; err != nil {
		m.logger.Error("App not found", zap.Error(err))
		http.Error(w, "App not found", http.StatusNotFound)
		return
	}

	app := createdApp{
		Id:            appRecord.ID,
		PEM:           appRecord.PrivateKey,
		ClientId:      "",
		ClientSecret:  "",
		WebhookSecret: appRecord.WebhookSecret,
		HTMLUrl:       fmt.Sprintf("https://%s/apps/%s", m.config.Domain, appRecord.Name),
	}

	appRecord.Code = generateTempCode()
	tx := m.db.Save(appRecord)
	if tx.Error != nil {
		m.logger.Error("Error updating app", zap.Error(tx.Error))
		http.Error(w, "Error updating app", http.StatusInternalServerError)
		return
	}

	appData, err := json.Marshal(app)
	if err != nil {
		m.logger.Error("Error marshalling app", zap.Error(err))
		http.Error(w, "Error marshalling app", http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusCreated)
	w.Write(appData)
}

func setupManifestsRoutes(params RouteParams) {
	r := params.R

	manifestApi := newManifests(params.Config, params.Db, params.Logger)
	manifestsRouter := r.PathPrefix("/api/v3/app-manifests").Subrouter()

	manifestsRouter.HandleFunc("/{code}/conversions", manifestApi.handlerConversion).Methods("POST")
}