package httpserver

import (
	"encoding/json"
	"errors"
	"io"
	"net/http"
	"strings"

	apicontract "bit.admedia.com/scm/ad/adpilot-indexing-repo-sync.com/internal/contracts/api"
	"bit.admedia.com/scm/ad/adpilot-indexing-repo-sync.com/internal/service"
)

const maxImportBodyBytes = 1 << 20 // 1 MiB

// ImportAcceptor handles gateway-driven repository imports.
type ImportAcceptor interface {
	AcceptImport(r *http.Request, req apicontract.ImportRequest) (apicontract.ImportAcceptedResponse, error)
}

type importAcceptorFunc func(r *http.Request, req apicontract.ImportRequest) (apicontract.ImportAcceptedResponse, error)

func (f importAcceptorFunc) AcceptImport(r *http.Request, req apicontract.ImportRequest) (apicontract.ImportAcceptedResponse, error) {
	return f(r, req)
}

func handleRepoImport(acceptor ImportAcceptor) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			writeJSON(w, http.StatusMethodNotAllowed, errorResponse{Error: "method not allowed"})
			return
		}

		raw, err := io.ReadAll(http.MaxBytesReader(w, r.Body, maxImportBodyBytes))
		if err != nil {
			writeJSON(w, http.StatusBadRequest, errorResponse{Error: "invalid request body"})
			return
		}

		var req apicontract.ImportRequest
		if err := json.Unmarshal(raw, &req); err != nil {
			writeJSON(w, http.StatusBadRequest, errorResponse{Error: "invalid json payload"})
			return
		}

		resp, err := acceptor.AcceptImport(r, req)
		if errors.Is(err, service.ErrInvalidImportPayload) {
			writeJSON(w, http.StatusBadRequest, errorResponse{Error: err.Error()})
			return
		}
		if errors.Is(err, service.ErrDuplicateImport) {
			writeJSON(w, http.StatusConflict, resp)
			return
		}
		if err != nil {
			writeJSON(w, http.StatusInternalServerError, errorResponse{Error: "failed to accept import"})
			return
		}

		writeJSON(w, http.StatusAccepted, resp)
	}
}

func ImportAcceptorFromSync(svc *service.SyncService) ImportAcceptor {
	return importAcceptorFunc(func(r *http.Request, req apicontract.ImportRequest) (apicontract.ImportAcceptedResponse, error) {
		if orgID := strings.TrimSpace(r.Header.Get("X-Org-Id")); orgID != "" && strings.TrimSpace(req.OrgID) == "" {
			req.OrgID = orgID
		}
		return svc.AcceptImport(r.Context(), req)
	})
}

var _ ImportAcceptor = importAcceptorFunc(nil)
