package main

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

	"git.gocasts.ir/ebhomengo/niki/staffapp/repository/database"
	"git.gocasts.ir/ebhomengo/niki/staffapp/service"
)

func main() {

	staffDb := database.New()
	staffService := service.NewStaffService(staffDb)

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Staffapp OK!")
	})

	http.HandleFunc("/staff", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
			return
		}

		var newStaff service.Staff
		decoder := json.NewDecoder(r.Body)
		err := decoder.Decode(&newStaff)
		if err != nil {
			http.Error(w, "Invalid request payload: "+err.Error(), http.StatusBadRequest)
			return
		}
		defer r.Body.Close()

		createdStaff, err := staffService.RegisterStaff(newStaff.Name, newStaff.LastName, newStaff.PhoneNumber)
		if err != nil {
			http.Error(w, "Failed to register staff: "+err.Error(), http.StatusInternalServerError)
			return
		}

		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusCreated)
		json.NewEncoder(w).Encode(createdStaff)
	})

	http.HandleFunc("/staff/", func(w http.ResponseWriter, r *http.Request) {

		idStr := r.URL.Path[len("/staff/"):]
		if idStr == "" {
			http.Error(w, "Missing staff ID", http.StatusBadRequest)
			return
		}

		id, err := strconv.Atoi(idStr)
		if err != nil {
			http.Error(w, "Invalid staff ID format", http.StatusBadRequest)
			return
		}

		switch r.Method {
		case http.MethodGet:

			st, err := staffService.Get(id)
			if err != nil {

				if err.Error() == "staff not found" {
					http.Error(w, "Staff not found", http.StatusNotFound)
				} else {
					http.Error(w, "Failed to fetch staff: "+err.Error(), http.StatusInternalServerError)
				}
				return
			}

			w.Header().Set("Content-Type", "application/json")
			json.NewEncoder(w).Encode(st)

		case http.MethodPut:

			var staffData struct {
				Name        string `json:"Name"`
				LastName    string `json:"LastName"`
				PhoneNumber string `json:"PhoneNumber"`
			}
			decoder := json.NewDecoder(r.Body)
			if err := decoder.Decode(&staffData); err != nil {
				http.Error(w, "Invalid request payload: "+err.Error(), http.StatusBadRequest)
				return
			}
			defer r.Body.Close()

			updatedStaff, err := staffService.Update(id, staffData.Name, staffData.LastName, staffData.PhoneNumber)
			if err != nil {

				if err.Error() == "staff not found" {
					http.Error(w, "Staff not found", http.StatusNotFound)
				} else {
					http.Error(w, "Failed to update staff: "+err.Error(), http.StatusInternalServerError)
				}
				return
			}

			w.Header().Set("Content-Type", "application/json")
			json.NewEncoder(w).Encode(updatedStaff)

		case http.MethodDelete:

			err = staffService.Remove(id)
			if err != nil {
				if err.Error() == "staff not found" {
					http.Error(w, "Staff not found", http.StatusNotFound)
				} else {
					http.Error(w, "Failed to remove staff: "+err.Error(), http.StatusInternalServerError)
				}
				return
			}
			w.WriteHeader(http.StatusNoContent)

		default:
			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		}
	})

	http.HandleFunc("/staffs", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodGet {
			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
			return
		}

		list, err := staffService.List()
		if err != nil {
			http.Error(w, "Failed to fetch staff list: "+err.Error(), http.StatusInternalServerError)
			return
		}

		w.Header().Set("Content-Type", "application/json")
		json.NewEncoder(w).Encode(list)
	})

	log.Fatal(http.ListenAndServe(":8080", nil))
}
