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

package app

import (
	"net/http"

	"dev.tandem.ws/tandem/camper/pkg/amenity"
	"dev.tandem.ws/tandem/camper/pkg/auth"
	"dev.tandem.ws/tandem/camper/pkg/booking"
	"dev.tandem.ws/tandem/camper/pkg/campsite"
	"dev.tandem.ws/tandem/camper/pkg/company"
	"dev.tandem.ws/tandem/camper/pkg/customer"
	"dev.tandem.ws/tandem/camper/pkg/database"
	"dev.tandem.ws/tandem/camper/pkg/home"
	httplib "dev.tandem.ws/tandem/camper/pkg/http"
	"dev.tandem.ws/tandem/camper/pkg/invoice"
	"dev.tandem.ws/tandem/camper/pkg/legal"
	"dev.tandem.ws/tandem/camper/pkg/location"
	"dev.tandem.ws/tandem/camper/pkg/media"
	"dev.tandem.ws/tandem/camper/pkg/payment"
	"dev.tandem.ws/tandem/camper/pkg/season"
	"dev.tandem.ws/tandem/camper/pkg/services"
	"dev.tandem.ws/tandem/camper/pkg/surroundings"
	"dev.tandem.ws/tandem/camper/pkg/template"
	"dev.tandem.ws/tandem/camper/pkg/user"
)

type adminHandler struct {
	amenity      *amenity.AdminHandler
	booking      *booking.AdminHandler
	campsite     *campsite.AdminHandler
	company      *company.AdminHandler
	customer     *customer.AdminHandler
	home         *home.AdminHandler
	invoice      *invoice.AdminHandler
	legal        *legal.AdminHandler
	location     *location.AdminHandler
	media        *media.AdminHandler
	payment      *payment.AdminHandler
	prebooking   *booking.PrebookingHandler
	season       *season.AdminHandler
	services     *services.AdminHandler
	surroundings *surroundings.AdminHandler
	user         *user.AdminHandler
}

func newAdminHandler(mediaDir string) *adminHandler {
	return &adminHandler{
		amenity:      amenity.NewAdminHandler(),
		booking:      booking.NewAdminHandler(),
		campsite:     campsite.NewAdminHandler(),
		company:      company.NewAdminHandler(),
		customer:     customer.NewAdminHandler(),
		home:         home.NewAdminHandler(),
		invoice:      invoice.NewAdminHandler(),
		legal:        legal.NewAdminHandler(),
		location:     location.NewAdminHandler(),
		media:        media.NewAdminHandler(mediaDir),
		payment:      payment.NewAdminHandler(),
		prebooking:   booking.NewPrebookingHandler(),
		season:       season.NewAdminHandler(),
		services:     services.NewAdminHandler(),
		surroundings: surroundings.NewAdminHandler(),
		user:         user.NewAdminHandler(),
	}
}

func (h *adminHandler) Handle(user *auth.User, company *auth.Company, conn *database.Conn) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if !user.LoggedIn {
			w.WriteHeader(http.StatusUnauthorized)
			serveLoginForm(w, r, user, company, r.RequestURI)
			return
		}

		if !user.IsEmployee() {
			http.Error(w, user.Locale.Gettext("Access forbidden"), http.StatusForbidden)
			return
		}

		var head string
		head, r.URL.Path = httplib.ShiftPath(r.URL.Path)
		switch head {
		case "amenities":
			h.amenity.Handler(user, company, conn).ServeHTTP(w, r)
		case "bookings":
			h.booking.Handler(user, company, conn).ServeHTTP(w, r)
		case "campsites":
			h.campsite.Handler(user, company, conn).ServeHTTP(w, r)
		case "company":
			h.company.Handler(user, company, conn).ServeHTTP(w, r)
		case "customers":
			h.customer.Handler(user, company, conn).ServeHTTP(w, r)
		case "home":
			h.home.Handler(user, company, conn).ServeHTTP(w, r)
		case "legal":
			h.legal.Handler(user, company, conn).ServeHTTP(w, r)
		case "invoices":
			h.invoice.Handler(user, company, conn).ServeHTTP(w, r)
		case "location":
			h.location.Handler(user, company, conn).ServeHTTP(w, r)
		case "media":
			h.media.Handler(user, company, conn).ServeHTTP(w, r)
		case "payments":
			h.payment.Handler(user, company, conn).ServeHTTP(w, r)
		case "prebookings":
			h.prebooking.Handler(user, company, conn).ServeHTTP(w, r)
		case "seasons":
			h.season.Handler(user, company, conn).ServeHTTP(w, r)
		case "services":
			h.services.Handler(user, company, conn).ServeHTTP(w, r)
		case "surroundings":
			h.surroundings.Handler(user, company, conn).ServeHTTP(w, r)
		case "users":
			h.user.Handler(user, company, conn).ServeHTTP(w, r)
		case "":
			switch r.Method {
			case http.MethodGet:
				serveDashboard(w, r, user, company)
			default:
				httplib.MethodNotAllowed(w, r, http.MethodGet)
			}
		default:
			http.NotFound(w, r)
		}
	})
}

func serveDashboard(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
	template.MustRenderAdmin(w, r, user, company, "dashboard.gohtml", nil)
}
