package admin

import (
	"fmt"
	"net/http"
	"strings"

	"arimelody-web/global"
	"arimelody-web/controller"
	"arimelody-web/model"
)

func serveRelease() http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        slices := strings.Split(r.URL.Path[1:], "/")
        releaseID := slices[0]

        release, err := controller.GetRelease(global.DB, releaseID, true)
        if err != nil {
            if strings.Contains(err.Error(), "no rows") {
                http.NotFound(w, r)
                return
            }
            fmt.Printf("FATAL: Failed to pull full release data for %s: %s\n", releaseID, err)
            http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
            return
        }

        authorised := GetSession(r) != nil
        if !authorised && !release.Visible {
            http.NotFound(w, r)
            return
        }

        if len(slices) > 1 {
            switch slices[1] {
            case "editcredits":
                serveEditCredits(release).ServeHTTP(w, r)
                return
            case "addcredit":
                serveAddCredit(release).ServeHTTP(w, r)
                return
            case "newcredit":
                serveNewCredit().ServeHTTP(w, r)
                return
            case "editlinks":
                serveEditLinks(release).ServeHTTP(w, r)
                return
            case "edittracks":
                serveEditTracks(release).ServeHTTP(w, r)
                return
            case "addtrack":
                serveAddTrack(release).ServeHTTP(w, r)
                return
            case "newtrack":
                serveNewTrack().ServeHTTP(w, r)
                return
            }
            http.NotFound(w, r)
            return
        }

        err = pages["release"].Execute(w, release)
        if err != nil {
            fmt.Printf("Error rendering admin release page for %s: %s\n", release.ID, err)
            http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
        }
    })
}

func serveEditCredits(release *model.Release) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "text/html")
        err := components["editcredits"].Execute(w, release)
        if err != nil {
            fmt.Printf("Error rendering edit credits component for %s: %s\n", release.ID, err)
            http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
        }
    })
}

func serveAddCredit(release *model.Release) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        artists, err := controller.GetArtistsNotOnRelease(global.DB, release.ID)
        if err != nil {
            fmt.Printf("FATAL: Failed to pull artists not on %s: %s\n", release.ID, err)
            http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
            return
        }

        type response struct {
            ReleaseID   string;
            Artists     []*model.Artist
        }

        w.Header().Set("Content-Type", "text/html")
        err = components["addcredit"].Execute(w, response{
            ReleaseID: release.ID,
            Artists: artists,
        })
        if err != nil {
            fmt.Printf("Error rendering add credits component for %s: %s\n", release.ID, err)
            http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
        }
    })
}

func serveNewCredit() http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        artistID := strings.Split(r.URL.Path, "/")[3]
        artist, err := controller.GetArtist(global.DB, artistID)
        if err != nil {
            fmt.Printf("FATAL: Failed to pull artists %s: %s\n", artistID, err)
            http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
            return
        }
        if artist == nil {
            http.NotFound(w, r)
            return
        }

        w.Header().Set("Content-Type", "text/html")
        err = components["newcredit"].Execute(w, artist)
        if err != nil {
            fmt.Printf("Error rendering new credit component for %s: %s\n", artist.ID, err)
            http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
        }
    })
}

func serveEditLinks(release *model.Release) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "text/html")
        err := components["editlinks"].Execute(w, release)
        if err != nil {
            fmt.Printf("Error rendering edit links component for %s: %s\n", release.ID, err)
            http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
        }
    })
}

func serveEditTracks(release *model.Release) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "text/html")
        err := components["edittracks"].Execute(w, release)
        if err != nil {
            fmt.Printf("Error rendering edit tracks component for %s: %s\n", release.ID, err)
            http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
        }
    })
}

func serveAddTrack(release *model.Release) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        tracks, err := controller.GetTracksNotOnRelease(global.DB, release.ID)
        if err != nil {
            fmt.Printf("FATAL: Failed to pull tracks not on %s: %s\n", release.ID, err)
            http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
            return
        }

        type response struct {
            ReleaseID   string;
            Tracks      []*model.Track
        }

        w.Header().Set("Content-Type", "text/html")
        err = components["addtrack"].Execute(w, response{
            ReleaseID: release.ID,
            Tracks: tracks,
        })
        if err != nil {
            fmt.Printf("Error rendering add tracks component for %s: %s\n", release.ID, err)
            http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
        }
        return
    })
}

func serveNewTrack() http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        trackID := strings.Split(r.URL.Path, "/")[3]
        track, err := controller.GetTrack(global.DB, trackID)
        if err != nil {
            fmt.Printf("Error rendering new track component for %s: %s\n", trackID, err)
            http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
            return
        }
        if track == nil {
            http.NotFound(w, r)
            return
        }

        w.Header().Set("Content-Type", "text/html")
        err = components["newtrack"].Execute(w, track)
        if err != nil {
            fmt.Printf("Error rendering new track component for %s: %s\n", track.ID, err)
            http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
        }
        return
    })
}
