package models

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

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

// handleCapturer handle API calls on Capturer
func (d *DataHandler) handleCapturer(w http.ResponseWriter, r *http.Request) {
	id, _ := strconv.Atoi(strings.TrimPrefix(r.URL.Path, "/api/Capturer/"))
	switch method := r.Method; method {
	case "GET":
		switch auth.GetLoggedUserTechnical(w, r).Role {
		case "ADMIN":
			d.getCapturerAdmin(w, r, id)
		case "CAPTURER":
			d.getCapturerCapturer(w, r, id)
		case "VISUALIZER":
			http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed)
		default:
			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
		}
	case "POST":
		switch auth.GetLoggedUserTechnical(w, r).Role {
		case "ADMIN":
			d.postCapturerAdmin(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.putCapturerAdmin(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.deleteCapturerAdmin(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) getCapturerAdmin(w http.ResponseWriter, r *http.Request, id int) {
	if id != 0 {
		var o Capturer
		if err := d.db.Preload("DeskRounds").First(&o, id).Error; err != nil {
			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
			return
		}
		json.NewEncoder(w).Encode(o)
	} else {
		var o []Capturer
		d.db.Preload("DeskRounds").Find(&o)
		json.NewEncoder(w).Encode(o)
	}
}

func (d *DataHandler) getCapturerCapturer(w http.ResponseWriter, r *http.Request, id int) {
	user := d.getLoggedUser(w, r).(Capturer)
	fmt.Println(user)
	if id != 0 {
		var o Capturer
		if err := d.db.Preload("DeskRounds").First(&o, id).Error; err != nil {
			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
			return
		}
		if o.UserID != user.UserID {
			http.Error(w, ErrorCannotAccessRessource, http.StatusForbidden)
			return
		}
		json.NewEncoder(w).Encode(o)
	} else {
		var o []Capturer
		d.db.Preload("DeskRounds").Where("id = ?", user.ID).Find(&o)
		json.NewEncoder(w).Encode(o)
	}
}

func (d *DataHandler) postCapturerAdmin(w http.ResponseWriter, r *http.Request) {
	var o Capturer
	err := json.NewDecoder(r.Body).Decode(&o)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	var capturer Capturer
	if err := d.db.Where("user_id = ?", o.UserID).First(&capturer).Error; err == nil {
		http.Error(w, "UserID is already bind to a Capturer", http.StatusInternalServerError)
		return
	}
	d.db.Create(&o)
	d.db.Last(&o)
	json.NewEncoder(w).Encode(o)

}

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

}

func (d *DataHandler) deleteCapturerAdmin(w http.ResponseWriter, r *http.Request, id int) {
	if id != 0 {
		var o Capturer
		if err := d.db.First(&o, id).Error; err != nil {
			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
			return
		}
		d.db.Delete(&o)
	} else {
		http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
	}
}