package main

import (
	"expvar"
	"net/http"

	"github.com/julienschmidt/httprouter"
	"party.at/party/cmd/party/common"
	"party.at/party/cmd/party/api"
	"party.at/party/cmd/party/web"
)

func routes(app *common.Application) http.Handler {
	// ── API router (Bearer token auth) ──────────────────────────────────────

	api := api.Api{
		App: app,
	}

	apiRouter := httprouter.New()
	apiRouter.NotFound = http.HandlerFunc(api.NotFoundResponse)
	apiRouter.MethodNotAllowed = http.HandlerFunc(api.MethodNotAllowedResponse)

	apiRouter.HandlerFunc(http.MethodGet, "/v1/healthcheck", api.Healthcheck)

	apiRouter.HandlerFunc(http.MethodGet,    "/v1/issues",                api.RequirePermission("issues:read",  api.ListIssues))
	apiRouter.HandlerFunc(http.MethodPost,   "/v1/issues",                api.RequirePermission("issues:write", api.CreateIssue))
	apiRouter.HandlerFunc(http.MethodGet,    "/v1/issues/:id",            api.RequirePermission("issues:read",  api.ReadIssue))
	apiRouter.HandlerFunc(http.MethodPatch,  "/v1/issues/:id",            api.RequirePermission("issues:write", api.UpdateIssue))
	apiRouter.HandlerFunc(http.MethodDelete, "/v1/issues/:id",            api.RequirePermission("issues:write", api.DeleteIssue))
	apiRouter.HandlerFunc(http.MethodGet,    "/v1/issues/:id/pubkey",     api.RequirePermission("issues:read",  api.ReadIssuePubKey))
	apiRouter.HandlerFunc(http.MethodPost,   "/v1/issues/:id/blind-sign", api.RequirePermission("issues:read",  api.BlindSignIssueVote))
	apiRouter.HandlerFunc(http.MethodPost,   "/v1/votes",                 api.Vote)
	apiRouter.HandlerFunc(http.MethodPost,   "/v1/users",                 api.CreateUser)
	apiRouter.HandlerFunc(http.MethodGet,    "/v1/users",                 api.RequirePermission("users:read", api.ListUsers))
	apiRouter.HandlerFunc(http.MethodGet,    "/v1/users/:id",             api.RequireAuthenticatedUser(api.ReadUser))
	apiRouter.HandlerFunc(http.MethodDelete, "/v1/users/:id",             api.DeleteUser)
	apiRouter.HandlerFunc(http.MethodPut,    "/v1/users/activated",       api.ActivateUser)

	apiRouter.HandlerFunc(http.MethodPost,   "/v1/tokens/authentication", api.CreateAuthenticationToken)
	apiRouter.HandlerFunc(http.MethodDelete, "/v1/tokens/authentication", api.RequireAuthenticatedUser(api.DeleteAuthenticationToken))

	apiRouter.HandlerFunc(http.MethodPost,   "/v1/device-tokens", api.RequireAuthenticatedUser(api.RegisterDeviceToken))
	apiRouter.HandlerFunc(http.MethodDelete, "/v1/device-tokens", api.RequireAuthenticatedUser(api.DeleteDeviceToken))

	apiRouter.HandlerFunc(http.MethodGet, "/v1/mps",                  api.ListMPs)
	apiRouter.HandlerFunc(http.MethodGet, "/v1/parlament/votes",       api.ListParlVotes)
	apiRouter.Handler(http.MethodGet,     "/v1/parlament/votes/*path", http.HandlerFunc(api.GetParlVoteDetail))

	apiRouter.Handler(http.MethodGet, "/debug/vars", expvar.Handler())

	apiChain := app.Metrics(api.RecoverPanic(app.EnableCORS(api.RateLimit(api.Authenticate(apiRouter)))))

	// ── Web router (cookie auth) ─────────────────────────────────────────────

	web := web.Web{
		App: app,
	}

	webRouter := httprouter.New()
	webRouter.HandlerFunc(http.MethodGet,    "/",                      web.Home)
	webRouter.HandlerFunc(http.MethodGet,    "/register",              web.Register)
	webRouter.HandlerFunc(http.MethodPost,   "/register",              web.RegisterUserPage)
	webRouter.HandlerFunc(http.MethodGet,    "/issues",                web.IssuesPage)
	webRouter.HandlerFunc(http.MethodPost,   "/issues",                web.CreateIssueAction)
	webRouter.HandlerFunc(http.MethodGet,    "/issues/:id",            web.IssuePage)
	webRouter.HandlerFunc(http.MethodPatch,  "/issues/:id",            web.UpdateIssueAction)
	webRouter.HandlerFunc(http.MethodDelete, "/issues/:id",            web.DeleteIssueAction)
	webRouter.HandlerFunc(http.MethodGet,    "/issues/:id/pubkey",     web.GetIssuePubKey)
	webRouter.HandlerFunc(http.MethodPost,   "/issues/:id/blind-sign", web.BlindSignIssue)
	webRouter.HandlerFunc(http.MethodPost,   "/votes",                 web.VoteAction)
	webRouter.HandlerFunc(http.MethodGet,    "/users",                 web.UsersPage)
	webRouter.HandlerFunc(http.MethodGet,    "/users/me",              web.ProfilePage)
	webRouter.HandlerFunc(http.MethodGet,    "/users/activated",       web.ActivatePage)
	webRouter.HandlerFunc(http.MethodPost,   "/users/activated",       web.ActivateUserAction)
	webRouter.HandlerFunc(http.MethodDelete, "/users/:id",             web.DeleteUserAction)
	webRouter.HandlerFunc(http.MethodGet,    "/mps",                   web.MembersOfParliamentPage)
	webRouter.HandlerFunc(http.MethodGet,    "/parlament",             web.ParlVotesPage)
	webRouter.Handler(http.MethodGet,        "/parlament/*path",       http.HandlerFunc(web.ParlamentDispatch))
	webRouter.HandlerFunc(http.MethodPost,   "/login",                 web.Login)
	webRouter.HandlerFunc(http.MethodPost,   "/dev-login",             web.DevLogin)
	webRouter.HandlerFunc(http.MethodPost,   "/logout",                web.Logout)
	webRouter.HandlerFunc(http.MethodGet,    "/ws",                    ws)
	webRouter.ServeFiles("/static/*filepath", http.Dir("web/static"))

	webChain := app.Metrics(web.WebRecoverPanic(web.WebRateLimit(web.AuthenticateCookie(webRouter))))

	// ── Top-level mux ────────────────────────────────────────────────────────
	mux := http.NewServeMux()
	mux.Handle("/v1/", apiChain)
	mux.Handle("/debug/", apiChain)
	mux.Handle("/", webChain)

	return mux
}