package main

import (
	"fmt"
	"log"
	"net/http"
	"time"

	"git.coopgo.io/coopgo-apps/parcoursmob/handlers/api"
	"git.coopgo.io/coopgo-apps/parcoursmob/handlers/application"
	"git.coopgo.io/coopgo-apps/parcoursmob/handlers/auth"
	"git.coopgo.io/coopgo-apps/parcoursmob/handlers/exports"
	"git.coopgo.io/coopgo-apps/parcoursmob/renderer"
	"git.coopgo.io/coopgo-apps/parcoursmob/services"
	"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
	cache "git.coopgo.io/coopgo-apps/parcoursmob/utils/storage"
	"github.com/gorilla/mux"
)

func main() {
	cfg, err := ReadConfig()

	if err != nil {
		panic(err)
	}

	var (
		//address              = cfg.GetString("server.listen")
		service_name         = cfg.GetString("service_name")
		templates_public_dir = cfg.GetString("templates.public_dir")
		dev_env              = cfg.GetBool("dev_env")
	)
	svc, err := services.NewServicesHandler(cfg)
	if err != nil {
		panic(err)
	}
	fmt.Println(cfg)
	kv, err := cache.NewKVHandler(cfg)
	if err != nil {
		panic(err)
	}
	filestorage, err := cache.NewFileStorage(cfg)

	idp, err := identification.NewIdentificationProvider(cfg, svc, kv)
	if err != nil {
		panic(err)
	}

	emailing, err := renderer.NewEmailingHandler(cfg)
	if err != nil {
		panic(err)
	}

	apiHandler, _ := api.NewAPIHandler(cfg, idp, svc, kv)
	applicationHandler, _ := application.NewApplicationHandler(cfg, svc, kv, filestorage, emailing)
	exportsHandler, _ := exports.NewExportsHandler(cfg, svc, emailing)
	authHandler, _ := auth.NewAuthHandler(cfg, idp, svc, kv, emailing)

	fmt.Println("Running", service_name, ":")
	if dev_env {
		fmt.Printf("\033]0;%s\007", service_name)
	}

	r := mux.NewRouter()

	r.PathPrefix("/public/").Handler(http.StripPrefix("/public/", http.FileServer(http.Dir(templates_public_dir))))

	r.HandleFunc("/auth/onboarding", authHandler.Onboarding)
	r.HandleFunc("/auth/disconnect", authHandler.Disconnect)
	r.HandleFunc("/auth/lost-password", authHandler.LostPasswordInit)
	r.HandleFunc("/auth/lost-password/recover", authHandler.LostPasswordRecover)
	r.HandleFunc("/auth/groups/", authHandler.Groups)
	r.HandleFunc("/auth/groups/switch", authHandler.GroupSwitch)
	r.HandleFunc("/", redirectApp)

	api_router := r.PathPrefix("/api").Subrouter()
	api_router.HandleFunc("/", apiHandler.NotFound)
	api_router.HandleFunc("/geo/autocomplete", apiHandler.GeoAutocomplete)
	api_router.HandleFunc("/cache/{cacheid}", apiHandler.GetCache)
	api_router.HandleFunc("/cache/{cacheid}/export", apiHandler.CacheExport)
	api_router.HandleFunc("/oauth2/callback", apiHandler.OAuth2Callback)

	application := r.PathPrefix("/app").Subrouter()
	application.HandleFunc("/", applicationHandler.Dashboard)
	application.HandleFunc("/beneficiaries/", applicationHandler.BeneficiariesList)
	application.HandleFunc("/beneficiaries/create", applicationHandler.BeneficiaryCreate)
	application.HandleFunc("/beneficiaries/{beneficiaryid}", applicationHandler.BeneficiaryDisplay)
	application.HandleFunc("/beneficiaries/{beneficiaryid}/update", applicationHandler.BeneficiaryUpdate)
	application.HandleFunc("/beneficiaries/{beneficiaryid}/documents", applicationHandler.BeneficiaryDocuments)
	application.HandleFunc("/beneficiaries/{beneficiaryid}/documents/{document}", applicationHandler.BeneficiaryDocumentDownload)
	application.HandleFunc("/beneficiaries/{beneficiaryid}/picture", applicationHandler.BeneficiaryPicture)
	application.HandleFunc("/members/{beneficiaryid}/picture", applicationHandler.BeneficiaryPicture)
	application.HandleFunc("/members/{adminid}", applicationHandler.MemberDisplay)
	application.HandleFunc("/members/{adminid}/update", applicationHandler.MemberUpdate)
	application.HandleFunc("/members/", applicationHandler.MembersList)
	application.HandleFunc("/journeys/", applicationHandler.JourneysSearch)
	application.HandleFunc("/vehicles/", applicationHandler.VehiclesSearch)
	application.HandleFunc("/vehicles/bookings/", applicationHandler.VehiclesBookingsList)
	application.HandleFunc("/vehicles/bookings/{bookingid}", applicationHandler.VehicleBookingDisplay)
	application.HandleFunc("/vehicles/v/{vehicleid}/b/{beneficiaryid}", applicationHandler.Book)
	application.HandleFunc("/vehicles/bookings/{bookingid}/documents/{document}", applicationHandler.BookingDocumentDownload)
	application.HandleFunc("/vehicles-management/", applicationHandler.VehiclesManagementOverview)
	application.HandleFunc("/vehicles-management/fleet/add", applicationHandler.VehiclesFleetAdd)
	application.HandleFunc("/vehicles-management/fleet/{vehicleid}", applicationHandler.VehiclesFleetDisplay)
	application.HandleFunc("/vehicles-management/fleet/{vehicleid}/unavailability", applicationHandler.VehiclesFleetMakeUnavailable)
	application.HandleFunc("/vehicles-management/fleet/{vehicleid}/update", applicationHandler.VehiclesFleetUpdate)
	application.HandleFunc("/vehicles-management/bookings/", applicationHandler.VehiclesManagementBookingsList)
	application.HandleFunc("/vehicles-management/bookings/{bookingid}", applicationHandler.VehicleManagementBookingDisplay)
	application.HandleFunc("/vehicles-management/bookings/{bookingid}/change-vehicle", applicationHandler.VehicleManagementBookingChangeVehicle)
	/////////////////////////////////////Remove booking vehicle/////////////////////////////////////////
	application.HandleFunc("/vehicles-management/bookings/{bookingid}/delete", applicationHandler.UnbookingVehicle)
	////////////////////////////////////////////////////////////////////////////////////////////////////
	application.HandleFunc("/vehicles-management/bookings/{bookingid}/documents/{document}", applicationHandler.BookingDocumentDownload)
	application.HandleFunc("/agenda/", applicationHandler.AgendaHome)
	application.HandleFunc("/agenda/history", applicationHandler.AgendaHistory)
	application.HandleFunc("/agenda/create-event", applicationHandler.AgendaCreateEvent)
	application.HandleFunc("/agenda/{eventid}", applicationHandler.AgendaDisplayEvent)
	///////////////////////////////Code to modify event///////////////////////
	application.HandleFunc("/agenda/{eventid}/update", applicationHandler.AgendaUpdateEvent)
	application.HandleFunc("/agenda/{eventid}/delete", applicationHandler.AgendaDeleteEvent)

	/////////////////////////////////////////////////////
	application.HandleFunc("/agenda/{eventid}/subscribe", applicationHandler.AgendaSubscribeEvent)
	application.HandleFunc("/directory/", applicationHandler.DirectoryHome)

	application.HandleFunc("/group/settings", applicationHandler.GroupSettingsDisplay)
	application.HandleFunc("/group/settings/invite-member", applicationHandler.GroupSettingsInviteMember)

	/****************************Groupe Déplacement ************************************/
	application.HandleFunc("/journeys/groups_covoiturage", applicationHandler.GroupsGestion)
	application.HandleFunc("/journeys/groups_covoiturage/create", applicationHandler.CreateGroup)
	application.HandleFunc("/journeys/groups_covoiturage/create/{groupid}", applicationHandler.DisplayGroupCovoiturage)
	application.HandleFunc("/journeys/groups_covoiturage/create/{id}/{groupid}/{memberid}", applicationHandler.UpdateGroupCovoiturage)
	/****************************************************************/

	/********************Code Supprt Emailing************************/
	application.HandleFunc("/support/", applicationHandler.SupportSend)
	/*********************** CODE GROUP **************************/

	//=================================silvermobi====================================
	application.HandleFunc("/solidarity_service/", applicationHandler.SolidarityService)
	application.HandleFunc("/solidarity_service/create/{id}", applicationHandler.DriversJourney)
	application.HandleFunc("/solidarity_service/driver/create", applicationHandler.CreateDriver)


	appGroup := application.PathPrefix("/group_module").Subrouter()
	appGroup.HandleFunc("/", applicationHandler.Groups)
	appGroup.HandleFunc("/groups", applicationHandler.CreateGroupModule)
	appGroup.HandleFunc("/groups/{groupid}", applicationHandler.DisplayGroupModule)

	//TODO Subrouters with middlewares checking security for each module ?
	application.Use(idp.Middleware)
	application.Use(idp.GroupsMiddleware)

	appAdmin := application.PathPrefix("/administration").Subrouter()
	appAdmin.HandleFunc("/", applicationHandler.Administration)
	appAdmin.HandleFunc("/groups/", applicationHandler.AdministrationCreateGroup)
	appAdmin.HandleFunc("/groups/{groupid}", applicationHandler.AdministrationGroupDisplay)
	appAdmin.HandleFunc("/groups/{groupid}/invite-admin", applicationHandler.AdministrationGroupInviteAdmin)
	appAdmin.HandleFunc("/groups/{groupid}/invite-member", applicationHandler.AdministrationGroupInviteMember)
	//add statistiques
	appAdmin.HandleFunc("/stats/vehicles", applicationHandler.AdminStatVehicles)
	appAdmin.HandleFunc("/stats/bookings", applicationHandler.AdminStatBookings)
	appAdmin.HandleFunc("/stats/beneficaires", applicationHandler.AdminStatBeneficaires)
	appAdmin.HandleFunc("/stats/events", applicationHandler.AdminStatEvents)

	/////////////////////////////////////Delete subscriber///////////////////////////////////////////////
	application.HandleFunc("/agenda/{eventid}/{subscribeid}/delete", applicationHandler.AgendaDeleteSubscribeEvent)
	application.HandleFunc("/agenda/{eventid}/history", applicationHandler.AgendaHistoryEvent)
	/////////////////////////////////////////////////////////////////////////////////////////////////////

	export := r.PathPrefix("/exports").Subrouter()
	export.HandleFunc("/fleets/bookings", exportsHandler.Bookings)
	export.HandleFunc("/fleets/bookings/{groupid}", exportsHandler.Bookings)
	export.HandleFunc("/agenda/subscriptions", exportsHandler.Agenda("allEvents"))
	export.HandleFunc("/agenda/{eventid}", exportsHandler.Agenda("oneEvent"))
	export.Use(idp.Middleware)
	export.Use(idp.GroupsMiddleware)

	srv := &http.Server{
		Handler:      r,
		Addr:         "0.0.0.0:9000",
		WriteTimeout: 15 * time.Second,
		ReadTimeout:  15 * time.Second,
	}

	log.Fatal(srv.ListenAndServe())

}

func redirectApp(w http.ResponseWriter, r *http.Request) {
	http.Redirect(w, r, "/app/", http.StatusFound)
}
