package route

import (
	"app/shelfly/internal/download"
	"app/shelfly/internal/library"
	"app/shelfly/internal/login"
	"app/shelfly/internal/models"
	"app/shelfly/internal/users"
	"app/shelfly/renders"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"

	"golang.org/x/crypto/bcrypt"

	"github.com/gorilla/mux"
	"golang.org/x/net/webdav"
	"gorm.io/gorm"
)
func PingHandler() http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		json.NewEncoder(w).Encode(map[string]string{
			"message": "pong",
			"service": "shelfy",
			"version": "1.0.0", // optionnel
		})
	}
}

func checkUserCredentials(db *gorm.DB, email string, password string) bool {
	var user models.User

	// On cherche l'utilisateur par email
	result := db.Where("email = ?", email).First(&user)
	if result.Error != nil {
		return false
	}

	// On vérifie le mot de passe via bcrypt comme dans ton LoginHandler
	err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
	return err == nil
}

type spaHandler struct {
	staticPath string
	indexPath  string
}

// Routes non protégées
func checkAuth(authHeader, username, password string) bool {
	const prefix = "Basic "
	if !strings.HasPrefix(authHeader, prefix) {
		return false
	}
	decoded, err := base64.StdEncoding.DecodeString(authHeader[len(prefix):])
	if err != nil {
		return false
	}
	pair := strings.SplitN(string(decoded), ":", 2)
	if len(pair) != 2 {
		return false
	}
	return pair[0] == username && pair[1] == password
}

func RoutesPublic(r *mux.Router, bd *gorm.DB) {
	// Fichiers statiques (CSS, JS, etc.)
	staticDir := "./templates/assets/"
	r.PathPrefix("/templates/assets/").Handler(
		http.StripPrefix("/templates/assets/", http.FileServer(http.Dir(staticDir))),
	)
	r.PathPrefix("/static/").Handler(
		http.StripPrefix("/static/", http.FileServer(http.Dir("./static"))))

	// Page de login
	r.HandleFunc("/api/ping", PingHandler()).Methods("GET")
	r.HandleFunc("/login", renders.Login)
	r.HandleFunc("/api/login", login.LoginHandler(bd)).Methods("POST")
    r.HandleFunc("/api/v2/login", login.LoginHandlerApi(bd)).Methods("POST")

	r.HandleFunc("/api/scan/{id}", library.ScanFolder(bd)).Methods("GET")
	r.HandleFunc("/api/download/stream", renders.HandleJobsStream(bd))

	// Génération playlist
	r.HandleFunc("/playlist.m3u", func(w http.ResponseWriter, r *http.Request) {
		uploadDir := "/app/upload"

		w.Header().Set("Content-Type", "audio/x-mpegurl")
		fmt.Fprintln(w, "#EXTM3U")

		err := filepath.Walk(uploadDir, func(path string, info os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			if info.IsDir() {
				return nil
			}
			relPath, _ := filepath.Rel(uploadDir, path)
			relPath = filepath.ToSlash(relPath)
			fileURL := fmt.Sprintf("https://media.canguidev.fr/upload/%s", relPath)
			fmt.Fprintln(w, fileURL)
			return nil
		})

		if err != nil {
			http.Error(w, "Erreur lors de la génération de la playlist", http.StatusInternalServerError)
		}
	})
	r.PathPrefix("/webdav/").Handler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		authHeader := req.Header.Get("Authorization")
		if authHeader == "" {
			w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
			http.Error(w, "Unauthorized", http.StatusUnauthorized)
			return
		}

		// Authentification HTTP Basic en base de données
		email, password, ok := req.BasicAuth()
		if !ok {
			w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
			http.Error(w, "Unauthorized", http.StatusUnauthorized)
			return
		}
		log.Printf("✅ email saisi: %s", email)
		log.Printf("✅ password saisi: %s", password)

		var user models.User
		result := bd.Where("email = ?", email).First(&user)
		if result.Error != nil {
			w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
			http.Error(w, "Unauthorized", http.StatusUnauthorized)
			return
		}

		err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
		if err != nil {
			w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
			http.Error(w, "Unauthorized", http.StatusUnauthorized)
			return
		}

		// ✅ Ici on autorise TOUTES les méthodes WebDAV (lecture/écriture/suppression)
		log.Printf("✅ WebDAV FULL ACCESS for user: %s", email)

		// Headers WebDAV que certains clients attendent
		w.Header().Set("DAV", "1,2")
		w.Header().Set("MS-Author-Via", "DAV")

		// Handler WebDAV complet
		webdavHandler := &webdav.Handler{
			Prefix:     "/webdav/",
			FileSystem: webdav.Dir("/app/upload"),
			LockSystem: webdav.NewMemLS(),
		}

		webdavHandler.ServeHTTP(w, req)
	}))

	// WebDAV sécurisé
	// username := "tonuser"       // ton login
	// password := "tonpassword"   // ton password

	// webdavHandler := &webdav.Handler{
	// 	Prefix:     "/webdav/",
	// 	FileSystem: webdav.Dir("/app/upload"),
	// 	LockSystem: webdav.NewMemLS(),
	// }

	// r.PathPrefix("/webdav/").Handler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
	// 	// Authentification
	// 	auth := req.Header.Get("Authorization")
	// 	if auth == "" || !checkAuth(auth, username, password) {
	// 		w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
	// 		http.Error(w, "Unauthorized", http.StatusUnauthorized)
	// 		return
	// 	}

	// 	// Protection lecture seule
	// 	if req.Method != "GET" && req.Method != "HEAD" && req.Method != "OPTIONS" && req.Method != "PROPFIND" {
	// 		http.Error(w, "Read-Only", http.StatusForbidden)
	// 		return
	// 	}
	// 	log.Printf("WebDAV request: %s %s", req.Method, req.URL.Path)

	// 	// Headers WebDAV que VLC attend
	// 	w.Header().Set("DAV", "1,2")
	// 	w.Header().Set("MS-Author-Via", "DAV")

	// 	webdavHandler.ServeHTTP(w, req)
	// }))
}

// Routes protégées
func RoutesProtected(r *mux.Router, bd *gorm.DB) {

	// Ici on place les vues et API qui doivent être protégées
	r.HandleFunc("/stream", StreamHandler)
	r.HandleFunc("/dashboard", renders.Dashboard(bd))
	r.HandleFunc("/settings", renders.Settings)
	r.HandleFunc("/library", renders.Library)
	r.HandleFunc("/menuLibary", renders.Library)
	r.HandleFunc("/godownloader/downloads", renders.GoDownload)
	r.HandleFunc("/godownloader/linkcollectors", renders.GoDownloadLinkCollectors)
	r.HandleFunc("/godownloader/settings", renders.GoDownloadSetting(bd))
	r.HandleFunc("/godownloader/poll-status", renders.PollStatusHandler(bd))
	r.HandleFunc("/godownloader/table-refresh", renders.GoDownloadPartialTable(bd))
	r.HandleFunc("/godownloader/settings/delete", renders.GoDownloadSettingDelete(bd))
	r.HandleFunc("/api/download/add", renders.HandleAddJob(bd)).Methods("POST")
	r.HandleFunc("/api/download/all", renders.HandleListJobsPartial(bd)).Methods("GET")
	r.HandleFunc("/downloads", renders.GoDownload2(bd))
	r.HandleFunc("/stream/{id}", download.HandleStreamPage()).Methods("GET")
	r.HandleFunc("/api/download/start/{id}", renders.HandleStartJob(bd)).Methods("POST")
	r.HandleFunc("/api/download/pause/{id}", renders.HandlePauseJob).Methods("POST")
	r.HandleFunc("/api/download/resume/{id}", renders.HandleResumeJob(bd)).Methods("POST")
	r.HandleFunc("/api/download/delete/{id}", renders.HandleDeleteJob(bd)).Methods("DELETE")
	r.HandleFunc("/api/download/delete-multiple", renders.HandleDeleteMultipleJobs(bd)).Methods("POST")

	// API user
	r.HandleFunc("/api/user/create", users.CreateUser(bd)).Methods("POST")
	r.HandleFunc("/api/user/update/{id}", users.UpdateUser(bd)).Methods("PUT")
	r.HandleFunc("/api/user/delete/{id}", users.DeleteUser(bd)).Methods("DELETE")
	r.HandleFunc("/api/user/all/", users.ReadAllUser(bd)).Methods("GET")
	r.HandleFunc("/api/user/{id}", users.FindUserById(bd)).Methods("GET")

	// API download
	r.HandleFunc("/api/pathDownload/create", download.CreateSavePath(bd)).Methods("POST")
	r.HandleFunc("/api/pathDownload/update/{id}", download.UpdateSavePath(bd)).Methods("PUT")
	r.HandleFunc("/api/pathDownload/delete/{id}", download.DeleteSavePath(bd)).Methods("DELETE")
	r.HandleFunc("/api/pathDownload/all/", download.ReadAllSavePath(bd)).Methods("GET")
	r.HandleFunc("/api/download/add-multiple", renders.HandleAddJobsMultiple(bd)).Methods("POST")
	//API Check path
	r.HandleFunc("/validate-path", download.PathValidationHandler)

	r.HandleFunc("/folders", renders.StreamHandler)
	r.HandleFunc("/folders/detail", renders.DetailHandler).Methods("GET")

	r.HandleFunc("/api/paths/{id:[0-9]+}/media", renders.PathMedia(bd)).Methods("GET")
	// r.HandleFunc("/stream/{partID:[0-9]+}", renders.Stream(bd)).Methods("GET")
	r.HandleFunc("/media/{partID:[0-9]+}", renders.MediaDetail(bd)).Methods("GET")
	r.HandleFunc("/hls/{partID:[0-9]+}/{file}", renders.HLSStream(bd)).Methods("GET")
	r.HandleFunc("/hls/{partID:[0-9]+}/", renders.HLSStream(bd)).Methods("GET")
	//API Scan folder



	// —————— JSON API routes apiV2 ——————
	r.HandleFunc("/api/v2/dashboard", renders.DashboardJSON(bd)).Methods("GET")
	r.HandleFunc("/api/v2/menu-library", renders.MenuLibraryJSON(bd)).Methods("GET")
	r.HandleFunc("/api/v2/settings", renders.SettingsJSON()).Methods("GET")
	r.HandleFunc("/api/v2/library", renders.LibraryJSON()).Methods("GET")

	r.HandleFunc("/api/v2/godownloader/download", renders.GoDownloadJSON()).Methods("GET")
	r.HandleFunc("/api/v2/godownloader/linkcollectors", renders.GoDownloadLinkCollectorsJSON()).Methods("GET")
	r.HandleFunc("/api/v2/godownloader/settings/delete", renders.GoDownloadSettingDeleteJSON(bd)).Methods("POST")
	r.HandleFunc("/api/v2/godownloader/settings/toggle", renders.GoDownloadSettingToggleActiveJSON(bd)).Methods("POST")
	r.HandleFunc("/api/v2/godownloader/settings", renders.GoDownloadSettingJSON(bd)).Methods("GET", "POST")
	r.HandleFunc("/api/v2/godownloader/settings/table", renders.GoDownloadPartialTableJSON(bd)).Methods("GET")

	r.HandleFunc("/api/v2/godownloader2", renders.GoDownload2JSON(bd)).Methods("GET")

	r.HandleFunc("/api/v2/add-job", renders.HandleAddJobJSON(bd)).Methods("POST")
	r.HandleFunc("/api/v2/jobs/list", renders.HandleListJobsPartialJSON(bd)).Methods("GET")
	r.HandleFunc("/api/v2/add-jobs-multiple", renders.HandleAddJobsMultipleJSON(bd)).Methods("POST")

	r.HandleFunc("/api/v2/stream", renders.StreamHandlerJSON()).Methods("GET")

	r.HandleFunc("/api/v2/pathmedia/{id}", renders.PathMediaJSON(bd)).Methods("GET")
	//r.HandleFunc("/api/media/detail/{partID}", renders.MediaDetailJSON(bd)).Methods("GET")
}

// func RoutesProtected(r *mux.Router, db *gorm.DB) {
//     // —————— HTML routes ——————
//     r.HandleFunc("/login", Login).Methods("GET")

//     r.HandleFunc("/dashboard", Dashboard(db)).Methods("GET")
//     r.HandleFunc("/menu-library", MenuLibrary(db)).Methods("GET")
//     r.HandleFunc("/settings", Settings).Methods("GET")
//     r.HandleFunc("/library", Library).Methods("GET")

//     r.HandleFunc("/godownloader/download", GoDownload).Methods("GET")
//     r.HandleFunc("/godownloader/linkcollectors", GoDownloadLinkCollectors).Methods("GET")
//     r.HandleFunc("/godownloader/settings/delete", GoDownloadSettingDelete(db)).Methods("GET")
//     r.HandleFunc("/godownloader/settings/toggle", GoDownloadSettingToggleActive(db)).Methods("GET")
//     r.HandleFunc("/godownloader/settings", GoDownloadSetting(db)).Methods("GET", "POST")
//     r.HandleFunc("/godownloader/settings/table", GoDownloadPartialTable(db)).Methods("GET")

//     r.HandleFunc("/godownloader2", GoDownload2(db)).Methods("GET")

//     r.HandleFunc("/add-job", HandleAddJob(db)).Methods("POST")
//     r.HandleFunc("/jobs/stream", HandleJobsStream(db)).Methods("GET")
//     r.HandleFunc("/jobs/list", HandleListJobsPartial(db)).Methods("GET")
//     r.HandleFunc("/jobs/start/{id}", HandleStartJob(db)).Methods("POST")
//     r.HandleFunc("/jobs/pause/{id}", HandlePauseJob).Methods("POST")
//     r.HandleFunc("/jobs/resume/{id}", HandleResumeJob(db)).Methods("POST")
//     r.HandleFunc("/jobs/delete/{id}", HandleDeleteJob(db)).Methods("POST")
//     r.HandleFunc("/jobs/delete-multiple", HandleDeleteMultipleJobs(db)).Methods("POST")

//     r.HandleFunc("/stream", StreamHandler).Methods("GET")
//     r.HandleFunc("/detail", DetailHandler).Methods("GET")
//     r.HandleFunc("/add-jobs-multiple", HandleAddJobsMultiple(db)).Methods("POST")

//     r.HandleFunc("/pathmedia/{id}", PathMedia(db)).Methods("GET")
//     r.HandleFunc("/media/detail/{partID}", MediaDetail(db)).Methods("GET")
//     r.PathPrefix("/hls/").Handler(HLSStream(db))

//     // —————— JSON API routes ——————
//     r.HandleFunc("/api/dashboard", DashboardJSON(db)).Methods("GET")
//     r.HandleFunc("/api/menu-library", MenuLibraryJSON(db)).Methods("GET")
//     r.HandleFunc("/api/settings", SettingsJSON()).Methods("GET")
//     r.HandleFunc("/api/library", LibraryJSON()).Methods("GET")

//     r.HandleFunc("/api/godownloader/download", GoDownloadJSON()).Methods("GET")
//     r.HandleFunc("/api/godownloader/linkcollectors", GoDownloadLinkCollectorsJSON()).Methods("GET")
//     r.HandleFunc("/api/godownloader/settings/delete", GoDownloadSettingDeleteJSON(db)).Methods("POST")
//     r.HandleFunc("/api/godownloader/settings/toggle", GoDownloadSettingToggleActiveJSON(db)).Methods("POST")
//     r.HandleFunc("/api/godownloader/settings", GoDownloadSettingJSON(db)).Methods("GET", "POST")
//     r.HandleFunc("/api/godownloader/settings/table", GoDownloadPartialTableJSON(db)).Methods("GET")

//     r.HandleFunc("/api/godownloader2", GoDownload2JSON(db)).Methods("GET")

//     r.HandleFunc("/api/add-job", HandleAddJobJSON(db)).Methods("POST")
//     r.HandleFunc("/api/jobs/list", HandleListJobsPartialJSON(db)).Methods("GET")
//     r.HandleFunc("/api/add-jobs-multiple", HandleAddJobsMultipleJSON(db)).Methods("POST")

//     r.HandleFunc("/api/stream", StreamHandlerJSON()).Methods("GET")

//	    r.HandleFunc("/api/pathmedia/{id}", PathMediaJSON(db)).Methods("GET")
//	    r.HandleFunc("/api/media/detail/{partID}", MediaDetailJSON(db)).Methods("GET")
//	}
func StreamHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/event-stream")
	w.Header().Set("Cache-Control", "no-cache")
	w.Header().Set("Connection", "keep-alive")

	flusher, ok := w.(http.Flusher)
	if !ok {
		http.Error(w, "Le streaming n’est pas supporté par ce serveur", http.StatusInternalServerError)
		return
	}

	ticker := time.NewTicker(1 * time.Second)
	defer ticker.Stop()

	// Boucle infinie (ou jusqu'à annulation)
	for {
		select {
		case <-ticker.C:
			fmt.Fprintf(w, "data: <p>Message #%d</p>\n\n")
			flusher.Flush()
		case <-r.Context().Done():
			// Le client a probablement fermé la connexion
			log.Println("Client déconnecté")
			return
		}
	}
}
