package models

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

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

func (d *DataHandler) handleArea(w http.ResponseWriter, r *http.Request) {
	id, _ := strconv.Atoi(strings.TrimPrefix(r.URL.Path, "/api/Area/"))
	switch method := r.Method; method {
	case "GET":
		switch auth.GetLoggedUserTechnical(w, r).Role {
		case "ADMIN", "CAPTURER", "VISUALIZER":
			d.getArea(w, r, id)
		default:
			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
		}
	case "POST":
		switch auth.GetLoggedUserTechnical(w, r).Role {
		case "ADMIN":
			d.postArea(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.putArea(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.deleteArea(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) getArea(w http.ResponseWriter, r *http.Request, id int) {
	if id != 0 {
		var o Area
		if err := d.db.Preload("Sections").First(&o, id).Error; err != nil {
			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
			return
		}
		json.NewEncoder(w).Encode(o)
	} else {
		var o []Area
		d.db.Preload("Sections").Find(&o)
		json.NewEncoder(w).Encode(o)
	}
}

func (d *DataHandler) postArea(w http.ResponseWriter, r *http.Request) {
	var o Area
	err := json.NewDecoder(r.Body).Decode(&o)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	// Check that ElectionID exist
	var election Election
	if err := d.db.First(&election, o.ElectionID).Error; err != nil {
		http.Error(w, ErrorParentNotFound, http.StatusInternalServerError)
		return
	}

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

}

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

}

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

		for _, section := range o.Sections {
			d.deleteSection(w, r, int(section.ID))
		}

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