/*
 * SPDX-FileCopyrightText: 2023 jordi fita mas <jfita@peritasoft.com>
 * SPDX-License-Identifier: AGPL-3.0-only
 */

package amenity

import (
	"context"
	"net/http"

	"golang.org/x/text/language"

	"dev.tandem.ws/tandem/camper/pkg/auth"
	"dev.tandem.ws/tandem/camper/pkg/carousel"
	"dev.tandem.ws/tandem/camper/pkg/database"
	httplib "dev.tandem.ws/tandem/camper/pkg/http"
	"dev.tandem.ws/tandem/camper/pkg/locale"
	"dev.tandem.ws/tandem/camper/pkg/template"
)

type PublicHandler struct {
}

func NewPublicHandler() *PublicHandler {
	return &PublicHandler{}
}

func (h *PublicHandler) Handler(user *auth.User, company *auth.Company, conn *database.Conn) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		var head string
		head, r.URL.Path = httplib.ShiftPath(r.URL.Path)

		page, err := newPublicPage(r.Context(), company, conn, user.Locale, head)
		if database.ErrorIsNotFound(err) {
			http.NotFound(w, r)
			return
		} else if err != nil {
			panic(err)
		}

		head, r.URL.Path = httplib.ShiftPath(r.URL.Path)
		switch head {
		case "":
			switch r.Method {
			case http.MethodGet:
				page.MustRender(w, r, user, company, conn)
			default:
				httplib.MethodNotAllowed(w, r, http.MethodGet)
			}
		default:
			http.NotFound(w, r)
		}
	})
}

type publicPage struct {
	*template.PublicPage
	Name     string
	Label    string
	Carousel []*carousel.Slide
	Features []*feature
	Info     []string
}

func newPublicPage(ctx context.Context, company *auth.Company, conn *database.Conn, loc *locale.Locale, label string) (*publicPage, error) {
	page := &publicPage{
		PublicPage: template.NewPublicPage(),
		Label:      label,
		Carousel:   mustCollectSlides(ctx, conn, company, loc, label),
	}
	row := conn.QueryRow(ctx, `
		select coalesce(i18n.name, amenity.name) as l10n_name
		     , array[coalesce(i18n.info1, amenity.info1)::text, coalesce(i18n.info2, amenity.info2)::text] as info
		from amenity
		    left join amenity_i18n i18n on amenity.amenity_id = i18n.amenity_id and i18n.lang_tag = $1
		where amenity.company_id = $2
		  and label = $3
		  and amenity.active
	`, loc.Language, company.ID, label)
	if err := row.Scan(&page.Name, &page.Info); err != nil {
		return nil, err
	}
	var err error
	page.Features, err = collectFeatures(ctx, conn, company, loc.Language, label)
	if err != nil {
		return nil, err
	}

	return page, nil
}

func (p *publicPage) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) {
	p.Setup(r, user, company, conn)
	template.MustRenderPublic(w, r, user, company, "amenity.gohtml", p)
}

type feature struct {
	Icon string
	Name string
}

func collectFeatures(ctx context.Context, conn *database.Conn, company *auth.Company, language language.Tag, label string) ([]*feature, error) {
	rows, err := conn.Query(ctx, `
		select feature.icon_name
		     , coalesce(i18n.name, feature.name) as l10n_name
        from amenity_feature as feature
            join amenity using (amenity_id)
		    left join amenity_feature_i18n as i18n on feature.amenity_feature_id = i18n.amenity_feature_id and i18n.lang_tag = $1
		where amenity.label = $2
		  and amenity.company_id = $3
		order by feature.position
    `, language, label, company.ID)
	if err != nil {
		return nil, err
	}

	var features []*feature
	for rows.Next() {
		f := &feature{}
		if err = rows.Scan(&f.Icon, &f.Name); err != nil {
			return nil, err
		}
		features = append(features, f)
	}
	return features, nil
}
