package handlers

import (
	"PersonApp/httpClient"
	"PersonApp/models"
	"PersonApp/repository"
	"encoding/json"
	"fmt"
	"github.com/gorilla/mux"
	"net/http"
	"strconv"
)

func InitRoutes(r *mux.Router, rep repository.PersonRepository, cln httpClient.Client) {
	r.HandleFunc("/", GetPersons(rep, cln)).Methods("GET")
	r.HandleFunc("/{id:[0-9]+}", GetPersonById(rep, cln)).Methods("GET")
	r.HandleFunc("/", CreatePerson(rep)).Methods("POST")
	r.HandleFunc("/{id:[0-9]+}", UpdatePerson(rep)).Methods("PUT")
	r.HandleFunc("/{id:[0-9]+}", DeletePerson(rep)).Methods("DELETE")
}

func GetPersons(rep repository.PersonRepository, cln httpClient.Client) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		fmt.Println("GET PERSONS")

		persons, err := rep.GetAllPersons()
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		for i := 0; i < len(persons); i++ {
			tasks, _ := cln.GetPersonTasks(persons[i].Id)
			persons[i].Tasks = tasks
		}

		err = json.NewEncoder(w).Encode(persons)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	}
}

func GetPersonById(rep repository.PersonRepository, cln httpClient.Client) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		id, err := strconv.Atoi(mux.Vars(r)["id"])
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		person, err := rep.GetPersonById(id)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		tasks, err := cln.GetPersonTasks(id)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		} else {
			person.Tasks = tasks
		}

		err = json.NewEncoder(w).Encode(person)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	}
}

func CreatePerson(rep repository.PersonRepository) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")

		var person *models.Person

		err := json.NewDecoder(r.Body).Decode(&person)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		person, err = rep.CreatePerson(*person)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		w.WriteHeader(http.StatusCreated)
		err = json.NewEncoder(w).Encode(person)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	}
}

func UpdatePerson(rep repository.PersonRepository) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")

		id, err := strconv.Atoi(mux.Vars(r)["id"])
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		var person *models.Person
		err = json.NewDecoder(r.Body).Decode(&person)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		person, err = rep.UpdatePerson(models.Person{
			Id:    id,
			Name:  person.Name,
			Tasks: nil,
		})
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		w.WriteHeader(http.StatusAccepted)
		err = json.NewEncoder(w).Encode(person)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
	}
}

func DeletePerson(rep repository.PersonRepository) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")

		id, err := strconv.Atoi(mux.Vars(r)["id"])
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		err = rep.DeletePerson(id)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		w.WriteHeader(http.StatusOK)
	}
}