package download

import (
	"app/shelfly/internal/debridlink"
	"app/shelfly/internal/models"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"os"
	"strings"
	"github.com/gorilla/mux"
	"gorm.io/gorm"
)
func renderPathHTML(path models.PathDownload) string {
	return fmt.Sprintf(`
		<div class="column">
			<form>
				<div id="path-%d" class="path-update grid is-col-min-1">
					<input class="input is-primary cell" name="id" disabled value="%d"></input>
					<input class="input is-primary fff cell" name="pathName" value="%s" disabled></span>

					<button class="button is-primary is-dark" id="btn-path-edit-%d"
						hx-trigger="click"
						hx-target="#path-%d"
						hx-swap="outerHTML"
						onclick="enableAllInputPath(%d)">
						Edit
					</button>

					<button class="button is-danger" type="button" id="btn-path-annuler-%d"
						onclick="disableAllInputPath(%d)" style="display:none">
						Annuler
					</button>

					<button class="button is-primary is-dark" id="btn-path-valider-%d"
						hx-put="/api/pathDownload/update/%d"
						hx-trigger="click[checkGlobalState()]"
						hx-target="#path-%d"
						hx-swap="outerHTML"
						hx-ext="json-enc" style="display:none">
						Valider
					</button>

					<button class="button is-danger"
						hx-delete="/api/pathDownload/delete/%d"
						hx-target="#path-%d"
						hx-swap="outerHTML swap:1s"
						hx-confirm="Are you sure?">
						Delete
					</button>
				</div>
			</form>
		</div>`,
		path.ID, path.ID, path.PathName,
		path.ID, path.ID, path.ID,
		path.ID, path.ID,
		path.ID, path.ID, path.ID,
		path.ID, path.ID)
}


func GetFirstActiveAccount(client *debridlink.Client) *debridlink.DebridAccount {
	ctx := context.Background() // ✅ on remplace ici

	accounts, err := client.ListDebridAccounts(ctx)
	if err != nil {
		log.Println("[ERROR] Impossible de récupérer les comptes :", err)
		return nil
	}

	for _, acc := range accounts {
		if acc.IsActive {
			return &acc
		}
	}

	return nil
}

func CreateSavePath(db *gorm.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")

		var pathDownload models.PathDownload
		if err := json.NewDecoder(r.Body).Decode(&pathDownload); err != nil {
			http.Error(w, `{"error": "Invalid JSON format"}`, http.StatusBadRequest)
			return
		}

		if pathDownload.PathName == "" {
			http.Error(w, `{"error": "PathName cannot be empty"}`, http.StatusBadRequest)
			return
		}

		fullPath := "/app/upload/" + pathDownload.PathName
		if _, err := os.Stat(fullPath); err == nil {
			http.Error(w, `{"error": "Path already exists"}`, http.StatusConflict)
			return
		}

		if err := os.MkdirAll(fullPath, 0755); err != nil {
			http.Error(w, `{"error": "Failed to create directory"}`, http.StatusInternalServerError)
			return
		}

		pathDownload.Path = fullPath
		if err := db.Create(&pathDownload).Error; err != nil {
			http.Error(w, `{"error": "Failed to save path"}`, http.StatusInternalServerError)
			return
		}

		fmt.Fprint(w, renderPathHTML(pathDownload))
	}
}


func ReadAllSavePath(db *gorm.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")

		var paths []models.PathDownload
		if err := db.Find(&paths).Error; err != nil {
			http.Error(w, `{"error": "Failed to retrieve paths"}`, http.StatusInternalServerError)
			return
		}

		var response strings.Builder
		for _, path := range paths {
			response.WriteString(renderPathHTML(path))
		}

		fmt.Fprint(w, response.String())
	}
}


func UpdateSavePath(db *gorm.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		id := mux.Vars(r)["id"]

		var pathDownload models.PathDownload
		if err := json.NewDecoder(r.Body).Decode(&pathDownload); err != nil {
			http.Error(w, `{"error": "Invalid JSON format"}`, http.StatusBadRequest)
			return
		}

		var existingPath models.PathDownload
		if err := db.First(&existingPath, "id = ?", id).Error; err != nil {
			http.Error(w, `{"error": "Path not found"}`, http.StatusNotFound)
			return
		}

		oldFullPath := "/app/upload/" + existingPath.PathName
		newFullPath := "/app/upload/" + pathDownload.PathName
		if oldFullPath != newFullPath {
			if err := os.Rename(oldFullPath, newFullPath); err != nil {
				http.Error(w, `{"error": "Failed to rename directory"}`, http.StatusInternalServerError)
				return
			}
		}

		existingPath.PathName = pathDownload.PathName
		existingPath.Path = newFullPath
		if err := db.Save(&existingPath).Error; err != nil {
			http.Error(w, `{"error": "Failed to update path"}`, http.StatusInternalServerError)
			return
		}

		fmt.Fprint(w, renderPathHTML(existingPath))
	}
}



func DeleteSavePath(db *gorm.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		id := mux.Vars(r)["id"]

		var pathDownload models.PathDownload
		if err := db.First(&pathDownload, "id = ?", id).Error; err != nil {
			http.Error(w, `{"error": "Path not found"}`, http.StatusNotFound)
			return
		}

		fullPath := "/app/upload/" + pathDownload.PathName
		if err := os.RemoveAll(fullPath); err != nil {
			http.Error(w, `{"error": "Failed to delete directory"}`, http.StatusInternalServerError)
			return
		}

		if err := db.Delete(&pathDownload).Error; err != nil {
			http.Error(w, `{"error": "Failed to delete path"}`, http.StatusInternalServerError)
			return
		}
	}
}

func IsPathValid(pathName string) error {
	if pathName == "" {
		return errors.New("PathName cannot be empty")
	}
	if strings.Contains(pathName, "/") || strings.Contains(pathName, "\\") {
		return errors.New("PathName cannot contain '/' or '\\'")
	}

	fullPath := "/app/upload/" + pathName

	if _, err := os.Stat(fullPath); err == nil {
		return errors.New("Path already exists")
	}

	// os.Stat() retourne une erreur si le dossier n'existe pas, on ignore cette erreur ici

	return nil
}


// PathValidationHandler handles HTTP requests to validate a path
func PathValidationHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
		return
	}

	var requestBody struct {
		PathName string `json:"pathName"`
	}

	if err := json.NewDecoder(r.Body).Decode(&requestBody); err != nil {
		http.Error(w, "Invalid request body", http.StatusBadRequest)
		return
	}

	err := IsPathValid(requestBody.PathName)

	response := map[string]string{
		"pathName": requestBody.PathName,
		"status": "valid",
	}

	if err != nil {
		response["status"] = "invalid"
		response["error"] = err.Error()
		w.WriteHeader(http.StatusBadRequest)
	}

	w.Header().Set("Content-Type", "application/json")
	if err := json.NewEncoder(w).Encode(response); err != nil {
		http.Error(w, "Failed to encode response", http.StatusInternalServerError)
	}
}


type StreamPageData struct {
	StreamURL string
}

func HandleStreamPage() http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		id := mux.Vars(r)["id"]
		job := jobs[id]
		if job == nil || job.StreamURL == "" {
			http.Error(w, "Stream non disponible", http.StatusNotFound)
			return
		}

		tmpl := `<html>
<head><title>Streaming</title></head>
<body style="margin:0;background:#000;">
  <video controls autoplay style="width:100vw;height:100vh;">
    <source src="{{.StreamURL}}" type="video/mp4">
    Votre navigateur ne supporte pas la vidéo HTML5.
  </video>
</body>
</html>`
		t := template.Must(template.New("stream").Parse(tmpl))
		t.Execute(w, StreamPageData{StreamURL: job.StreamURL})
	}
}
