package main

import (
	"encoding/json"
	"fmt"
	"github.com/gocql/gocql"
	"log"
	"net/http"
	"strings"
)

type Note struct {
	ID      gocql.UUID `json:"id"`
	Title   string     `json:"title"`
	Content string     `json:"content"`
}

type ApiResponse struct {
	Status  int    `json:"status"`
	Message string `json:"message"`
	Data    interface{} `json:"data,omitempty"`
}

var session *gocql.Session

func main() {
	var err error
	cluster := gocql.NewCluster("127.0.0.1")
	cluster.Keyspace = "notes_keyspace"
	session, err = cluster.CreateSession()
	if err != nil {
		log.Fatal(err)
	}
	defer session.Close()

	http.HandleFunc("/api/notes", notesHandler)
	http.HandleFunc("/api/note/", noteHandler)

	log.Println("Server running on port 8080")
	log.Fatal(http.ListenAndServe(":8080", nil))
}

func notesHandler(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		getAllNotes(w, r)
	case "POST":
		createNote(w, r)
	default:
		sendResponse(w, http.StatusMethodNotAllowed, "Invalid method")
	}
}

func noteHandler(w http.ResponseWriter, r *http.Request) {
	idStr := strings.TrimPrefix(r.URL.Path, "/api/note/")
	id, err := gocql.ParseUUID(idStr)
	if err != nil {
		sendResponse(w, http.StatusBadRequest, "Invalid ID")
		return
	}

	switch r.Method {
	case "GET":
		getNoteByID(w, id)
	case "PUT":
		updateNote(w, r, id)
	case "DELETE":
		deleteNote(w, id)
	default:
		sendResponse(w, http.StatusMethodNotAllowed, "Invalid method")
	}
}

func getAllNotes(w http.ResponseWriter, _ *http.Request) {
	iter := session.Query("SELECT id, title, content FROM notes").Iter()
	var notes []Note
	var note Note

	for iter.Scan(&note.ID, &note.Title, &note.Content) {
		notes = append(notes, note)
	}

	if err := iter.Close(); err != nil {
		sendResponse(w, http.StatusInternalServerError, "Error fetching data from database")
		return
	}

	sendResponse(w, http.StatusOK, "Success", notes)
}

func getNoteByID(w http.ResponseWriter, id gocql.UUID) {
	var note Note
	err := session.Query("SELECT id, title, content FROM notes WHERE id=?", id).Scan(&note.ID, &note.Title, &note.Content)

	if err == gocql.ErrNotFound {
		sendResponse(w, http.StatusNotFound, "Note not found")
		return
	} else if err != nil {
		sendResponse(w, http.StatusInternalServerError, "Error fetching data from database")
		return
	}

	sendResponse(w, http.StatusOK, "Success", note)
}

func createNote(w http.ResponseWriter, r *http.Request) {
	var note Note
	err := json.NewDecoder(r.Body).Decode(&note)
	if err != nil {
		sendResponse(w, http.StatusBadRequest, "Invalid request payload")
		return
	}

	note.ID = gocql.TimeUUID()
	err = session.Query("INSERT INTO notes (id, title, content) VALUES (?, ?, ?)", note.ID, note.Title, note.Content).Exec()

	if err != nil {
		sendResponse(w, http.StatusInternalServerError, "Error inserting data into database")
		return
	}

	sendResponse(w, http.StatusCreated, "Note created", note)
}

func updateNote(w http.ResponseWriter, r *http.Request, id gocql.UUID) {
	var note Note
	err := json.NewDecoder(r.Body).Decode(&note)
	if err != nil {
		sendResponse(w, http.StatusBadRequest, "Invalid request payload")
		return
	}

	err = session.Query("UPDATE notes SET title=?, content=? WHERE id=?", note.Title, note.Content, id).Exec()

	if err != nil {
		sendResponse(w, http.StatusInternalServerError, "Error updating data in database")
		return
	}

	sendResponse(w, http.StatusOK, "Note updated")
}

func deleteNote(w http.ResponseWriter, id gocql.UUID) {
	err := session.Query("DELETE FROM notes WHERE id=?", id).Exec()

	if err != nil {
		sendResponse(w, http.StatusInternalServerError, "Error deleting data from database")
		return
	}

	sendResponse(w, http.StatusOK, "Note deleted")
}

func sendResponse(w http.ResponseWriter, status int, message string, data ...interface{}) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)

	response := ApiResponse{
		Status:  status,
		Message: message,
	}

	if len(data) > 0 {
		response.Data = data[0]
	}

	json.NewEncoder(w).Encode(response)
}
package main

import (
	"encoding/json"
	"fmt"
	"github.com/gocql/gocql"
	"log"
	"net/http"
	"strings"
)

type Note struct {
	ID      gocql.UUID `json:"id"`
	Title   string     `json:"title"`
	Content string     `json:"content"`
}

type ApiResponse struct {
	Status  int    `json:"status"`
	Message string `json:"message"`
	Data    interface{} `json:"data,omitempty"`
}

var session *gocql.Session

func main() {
	var err error
	cluster := gocql.NewCluster("127.0.0.1")
	cluster.Keyspace = "notes_keyspace"
	session, err = cluster.CreateSession()
	if err != nil {
		log.Fatal(err)
	}
	defer session.Close()

	http.HandleFunc("/api/notes", notesHandler)
	http.HandleFunc("/api/note/", noteHandler)

	log.Println("Server running on port 8080")
	log.Fatal(http.ListenAndServe(":8080", nil))
}

func notesHandler(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		getAllNotes(w, r)
	case "POST":
		createNote(w, r)
	default:
		sendResponse(w, http.StatusMethodNotAllowed, "Invalid method")
	}
}

func noteHandler(w http.ResponseWriter, r *http.Request) {
	idStr := strings.TrimPrefix(r.URL.Path, "/api/note/")
	id, err := gocql.ParseUUID(idStr)
	if err != nil {
		sendResponse(w, http.StatusBadRequest, "Invalid ID")
		return
	}

	switch r.Method {
	case "GET":
		getNoteByID(w, id)
	case "PUT":
		updateNote(w, r, id)
	case "DELETE":
		deleteNote(w, id)
	default:
		sendResponse(w, http.StatusMethodNotAllowed, "Invalid method")
	}
}

func getAllNotes(w http.ResponseWriter, _ *http.Request) {
	iter := session.Query("SELECT id, title, content FROM notes").Iter()
	var notes []Note
	var note Note

	for iter.Scan(&note.ID, &note.Title, &note.Content) {
		notes = append(notes, note)
	}

	if err := iter.Close(); err != nil {
		sendResponse(w, http.StatusInternalServerError, "Error fetching data from database")
		return
	}

	sendResponse(w, http.StatusOK, "Success", notes)
}

func getNoteByID(w http.ResponseWriter, id gocql.UUID) {
	var note Note
	err := session.Query("SELECT id, title, content FROM notes WHERE id=?", id).Scan(&note.ID, &note.Title, &note.Content)

	if err == gocql.ErrNotFound {
		sendResponse(w, http.StatusNotFound, "Note not found")
		return
	} else if err != nil {
		sendResponse(w, http.StatusInternalServerError, "Error fetching data from database")
		return
	}

	sendResponse(w, http.StatusOK, "Success", note)
}

func createNote(w http.ResponseWriter, r *http.Request) {
	var note Note
	err := json.NewDecoder(r.Body).Decode(&note)
	if err != nil {
		sendResponse(w, http.StatusBadRequest, "Invalid request payload")
		return
	}

	note.ID = gocql.TimeUUID()
	err = session.Query("INSERT INTO notes (id, title, content) VALUES (?, ?, ?)", note.ID, note.Title, note.Content).Exec()

	if err != nil {
		sendResponse(w, http.StatusInternalServerError, "Error inserting data into database")
		return
	}

	sendResponse(w, http.StatusCreated, "Note created", note)
}

func updateNote(w http.ResponseWriter, r *http.Request, id gocql.UUID) {
	var note Note
	err := json.NewDecoder(r.Body).Decode(&note)
	if err != nil {
		sendResponse(w, http.StatusBadRequest, "Invalid request payload")
		return
	}

	err = session.Query("UPDATE notes SET title=?, content=? WHERE id=?", note.Title, note.Content, id).Exec()

	if err != nil {
		sendResponse(w, http.StatusInternalServerError, "Error updating data in database")
		return
	}

	sendResponse(w, http.StatusOK, "Note updated")
}

func deleteNote(w http.ResponseWriter, id gocql.UUID) {
	err := session.Query("DELETE FROM notes WHERE id=?", id).Exec()

	if err != nil {
		sendResponse(w, http.StatusInternalServerError, "Error deleting data from database")
		return
	}

	sendResponse(w, http.StatusOK, "Note deleted")
}

func sendResponse(w http.ResponseWriter, status int, message string, data ...interface{}) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)

	response := ApiResponse{
		Status:  status,
		Message: message,
	}

	if len(data) > 0 {
		response.Data = data[0]
	}

	json.NewEncoder(w).Encode(response)
}