package api

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

	"github.com/go-chi/chi/v5"
)

type SourcesImpl interface {
	SearchQuery(*SourcesSearchQueryReq) (*SourcesSearchQueryResp, error)
	SearchSha(*SourcesSearchShaReq) (*SourcesSearchShaResp, error)
	SearchTags(*SourcesSearchTagsReq) (*SourcesSearchTagsResp, error)
	List(*SourcesListReq) (*SourcesListResp, error)
	ListPrefix(*SourcesListPrefixReq) (*SourcesListPrefixResp, error)

	Versions(*SourcesVersionsReq) (*SourcesVersionsResp, error)
	Navigate(*SourcesNavigateReq) (*SourcesNavigateResp, error)

	Status() *PingResp
}

type SourcesSearchQueryReq struct {
	Query string `json:"query"`
}

type SourcesSearchQueryResp struct {
	Results struct {
		Exact NamedItem   `json:"exact"`
		Other []NamedItem `json:"other"`
	} `json:"results"`
	Suite string `json:"suite"`
}
type SourcesSearchShaReq struct{}
type SourcesSearchShaResp struct{}

type SourcesSearchTagsReq struct{}
type SourcesSearchTagsResp struct{}

type SourcesListReq struct{}
type SourcesListResp struct{}

type SourcesListPrefixReq struct{}
type SourcesListPrefixResp struct{}

type SourcesVersionsReq struct{}
type SourcesVersionsResp struct{}

type SourcesNavigateReq struct{}
type SourcesNavigateResp struct{}

func (a *ApiHandler) RouteSource(r chi.Router) {
	// searching
	r.Get("/search/{query}", func(w http.ResponseWriter, r *http.Request) {
		query := chi.URLParam(r, "query")
		req := &SourcesSearchQueryReq{
			Query: query,
		}
		returnJson(w, req, a.sources.SearchQuery)
	})
	r.Get("/sha256", func(w http.ResponseWriter, r *http.Request) {
		req := &SourcesSearchShaReq{}
		returnJson(w, req, a.sources.SearchSha)
	})
	r.Get("/ctag", func(w http.ResponseWriter, r *http.Request) {
		req := &SourcesSearchTagsReq{}
		returnJson(w, req, a.sources.SearchTags)
	})
	//package lists
	r.Get("/list", func(w http.ResponseWriter, r *http.Request) {
		req := &SourcesListReq{}
		returnJson(w, req, a.sources.List)
	})
	r.Get("/prefix/{prefix}", func(w http.ResponseWriter, r *http.Request) {
		req := &SourcesListPrefixReq{}
		returnJson(w, req, a.sources.ListPrefix)
	})
	// package info
	r.Get("/src/{packagename}", func(w http.ResponseWriter, r *http.Request) {
		req := &SourcesVersionsReq{}
		returnJson(w, req, a.sources.Versions)
	})
	r.Get("/info/package/{packagename}/{version}", func(w http.ResponseWriter, r *http.Request) {
		req := &SourcesNavigateReq{}
		returnJson(w, req, a.sources.Navigate)
	})
	// navigation
	r.Get("/src/{packagename}/{version}/*", func(w http.ResponseWriter, r *http.Request) {
		req := &SourcesNavigateReq{}
		returnJson(w, req, a.sources.Navigate)
	})
	// status
	r.Get("/ping", func(w http.ResponseWriter, r *http.Request) {
		d, _ := json.Marshal(a.sources.Status())
		w.Write(d)
	})
}
