package models

import (
	"encoding/json"
	"net/http"
	"strconv"
	"strings"

	"forge.grandlyon.com/apoyen/elections/internal/auth"
)

func (d *DataHandler) handleParty(w http.ResponseWriter, r *http.Request) {
	id, _ := strconv.Atoi(strings.TrimPrefix(r.URL.Path, "/api/Party/"))
	switch method := r.Method; method {
	case "GET":
		switch auth.GetLoggedUserTechnical(w, r).Role {
		case "ADMIN", "CAPTURER", "VISUALIZER":
			d.getParty(w, r, id)
		default:
			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
		}
	case "POST":
		switch auth.GetLoggedUserTechnical(w, r).Role {
		case "ADMIN":
			d.postParty(w, r)
		case "CAPTURER", "VISUALIZER":
			http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed)
		default:
			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
		}

	case "PUT":
		switch auth.GetLoggedUserTechnical(w, r).Role {
		case "ADMIN":
			d.putParty(w, r, id)
		case "CAPTURER", "VISUALIZER":
			http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed)
		default:
			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
		}
	case "DELETE":
		switch auth.GetLoggedUserTechnical(w, r).Role {
		case "ADMIN":
			d.deleteParty(w, r, id)
		case "CAPTURER", "VISUALIZER":
			http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed)
		default:
			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
		}
	default:
		http.Error(w, "method not allowed", 400)
	}
}

func (d *DataHandler) getParty(w http.ResponseWriter, r *http.Request, id int) {
	if id != 0 {
		var o Party
		if err := d.db.Preload("CandidateLists").First(&o, id).Error; err != nil {
			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
			return
		}
		json.NewEncoder(w).Encode(o)
	} else {
		var o []Party
		d.db.Preload("CandidateLists").Find(&o)
		json.NewEncoder(w).Encode(o)
	}
}

func (d *DataHandler) postParty(w http.ResponseWriter, r *http.Request) {
	var o Party
	err := json.NewDecoder(r.Body).Decode(&o)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	d.db.Create(&o)
	d.db.Last(&o)
	json.NewEncoder(w).Encode(o)

}

func (d *DataHandler) putParty(w http.ResponseWriter, r *http.Request, id int) {
	var o Party
	if err := d.db.Preload("CandidateLists").First(&o, id).Error; err != nil {
		http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
		return
	}
	var party Party
	err := json.NewDecoder(r.Body).Decode(&party)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	o.Name = party.Name
	o.Color = party.Color
	d.db.Save(&o)
	json.NewEncoder(w).Encode(o)

}

func (d *DataHandler) deleteParty(w http.ResponseWriter, r *http.Request, id int) {
	if id != 0 {
		var o Party
		if err := d.db.Preload("CandidateLists").First(&o, id).Error; err != nil {
			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
			return
		}

		for _, candidateList := range o.CandidateLists {
			d.deleteCandidateList(w, r, int(candidateList.ID))
		}

		d.db.Delete(&o)
	} else {
		http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
	}
}