package main

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strconv"

	"github.com/gofiber/fiber/v2"
)

//Get Server Config
func (s *Server) GetServerConfig(c *fiber.Ctx) error {
	fmt.Println("SENDING CONFIG!")
	return c.Status(fiber.StatusOK).JSON(fiber.Map{"BasicAuth": s.Config.Authentication.BasicAuth, "Timezone": s.Config.Timezone})
}

// Add a new location
func (s *Server) AddNewLocationHandler(c *fiber.Ctx) error {
	form, err := c.MultipartForm()
	if err != nil {
		s.Log.Err(err).Msgf("Unable to fetch locations: ", err)
		return err
	}
	locName := form.Value["Name"][0]
	locPhoto := form.File["CoverPhoto"][0]
	if err != nil {
		s.Log.Err(err).Msgf("Unable to get CoverPhoto for location: ", err)
		return err
	}
	locAdditionalPhotos := form.File["AdditionalPhotos"]
	// Create the directory for this location to store the photos
	err = os.MkdirAll(s.Config.Server.LocationPhotoDir+locName, 0755)
	if err != nil {
		return err
	}
	var photoURLsList []string
	for i, photo := range locAdditionalPhotos {
		src, err := photo.Open()
		if err != nil {
			return err
		}
		defer src.Close()

		photoPath := filepath.ToSlash(s.Config.Server.LocationPhotoDir + locName + "/" + locName + "_" + strconv.Itoa(i) + filepath.Ext(photo.Filename))
		photoURL := locName + "_" + strconv.Itoa(i) + filepath.Ext(photo.Filename)
		photoURLsList = append(photoURLsList, photoURL)
		photoData, err := io.ReadAll(src)
		if err != nil {
			return err
		}
		os.WriteFile(photoPath, photoData, 0644)
	}
	// create files on server for all uploads
	locNotes := form.Value["Notes"][0]

	// saving the uploaded image to our images dir
	coverImagePath := filepath.ToSlash(s.Config.Server.LocationPhotoDir + locName + "/" + locName + "_cover" + filepath.Ext(locPhoto.Filename))
	// Creating the URL to retrieve photo
	coverImageURL := locName + "_cover" + filepath.Ext(locPhoto.Filename)
	src, err := locPhoto.Open()
	if err != nil {
		return err
	}
	defer src.Close()
	coverImageData, err := io.ReadAll(src)
	if err != nil {
		s.Log.Err(err).Msgf("Unable to read cover photo file: ", err)
		return err
	}
	err = os.WriteFile(coverImagePath, coverImageData, 0644)
	if err != nil {
		return err
	}
	newLocation := Location{
		Name:       locName,
		CoverPhoto: coverImageURL,
		Photos:     photoURLsList,
		Notes:      locNotes,
	}
	err = s.AddLocation(newLocation)
	if err != nil {
		return err
	}
	s.Log.Debug().Msgf("Adding new location: %v", newLocation)
	return c.Status(fiber.StatusOK).SendString(fmt.Sprintf("New Location Created! %s", newLocation.Name))
}

func (s *Server) GetAllLocationsHandler(c *fiber.Ctx) error {
	locations, err := s.GetLocations()
	if err != nil {
		s.Log.Err(err).Msgf("Unable to fetch locations: ", err)
		return err
	}
	s.Log.Debug().Msgf("Returning Locations: %+v", locations)
	return c.Status(fiber.StatusOK).JSON(locations)
}

func (s *Server) GetSingleLocationHandler(c *fiber.Ctx) error {
	locID, err := c.ParamsInt("locID")
	if err != nil {
		return err
	}
	location, err := s.GetLocation(locID)
	if err != nil {
		return err
	}
	fmt.Println("Returning A single location: ", location)
	return c.Status(fiber.StatusOK).JSON(location)
}

func (s *Server) DeleteLocationHandler(c *fiber.Ctx) error {
	locID, err := c.ParamsInt("locID")
	if err != nil {
		return err
	}
	location, err := s.GetLocation(locID)
	if err != nil {
		s.Log.Err(err).Msgf("Unable to fetch location with id: %d", locID)
		return err
	}
	err = s.DeleteLocation(location)
	if err != nil {
		s.Log.Err(err).Msgf("Unable to delete location with id: %d", locID)
		return err
	}
	return c.Status(fiber.StatusOK).SendString(fmt.Sprintf("Location Deleted! %d", locID))
}

// DeleteRoomHandler deletes a room based on an ID
func (s *Server) DeleteRoomHandler(c *fiber.Ctx) error {
	roomID, err := c.ParamsInt("roomID")
	if err != nil {
		return err
	}
	room, err := s.GetRoom(roomID)
	if err != nil {
		s.Log.Err(err).Msgf("Unable to fetch room with id: %d", roomID)
		return err
	}
	err = s.DeleteRoom(room)
	if err != nil {
		s.Log.Err(err).Msgf("Unable to delete room with id: %d", roomID)
		return err
	}
	return c.Status(fiber.StatusOK).SendString(fmt.Sprintf("Room Deleted! %d", roomID))
}

// AddNewRoomHandler adds a new room
func (s *Server) AddNewRoomHandler(c *fiber.Ctx) error {
	locID, err := c.ParamsInt("locID")
	if err != nil {
		return err
	}
	form, err := c.MultipartForm()
	if err != nil {
		s.Log.Err(err).Msgf("Unable to fetch rooms: ", err)
		return err
	}
	roomName := form.Value["Name"][0]
	fmt.Println("COverphoto: ", form.File["CoverPhoto"])
	roomPhoto := form.File["CoverPhoto"][0]
	if err != nil {
		s.Log.Err(err).Msgf("Unable to get CoverPhoto for Room: ", err)
		return err
	}
	roomAdditionalPhotos := form.File["AdditionalPhotos"]
	// Fetch the location information
	loc, err := s.GetLocation(locID)
	if err != nil {
		s.Log.Err(err).Msgf("Unable to fetch location by id: %d with error: %s", locID, err)
		return err
	}
	// setting the path prepend for the photos
	urlPrepend := loc.Name + "/" + roomName + "/"
	pathPrepend := s.Config.Server.LocationPhotoDir + "/" + urlPrepend

	// Create the directory for this room to store the photos
	err = os.MkdirAll(filepath.ToSlash(s.Config.Server.LocationPhotoDir+"/"+loc.Name+"/"+roomName), 0755)
	if err != nil {
		return err
	}
	var photoURLsList []string
	for i, photo := range roomAdditionalPhotos {
		src, err := photo.Open()
		if err != nil {
			return err
		}
		defer src.Close()

		photoPath := filepath.ToSlash(pathPrepend + roomName + "_" + strconv.Itoa(i) + filepath.Ext(photo.Filename))
		photoURL := urlPrepend + roomName + "_" + strconv.Itoa(i) + filepath.Ext(photo.Filename)
		photoURLsList = append(photoURLsList, photoURL)
		photoData, err := io.ReadAll(src)
		if err != nil {
			return err
		}
		os.WriteFile(photoPath, photoData, 0644)
	}
	// create files on server for all uploads
	roomNotes := form.Value["Notes"][0]

	// saving the uploaded image to our images dir
	coverImagePath := filepath.ToSlash(pathPrepend + roomName + "_cover" + filepath.Ext(roomPhoto.Filename))
	// Creating the URL to retrieve photo
	coverImageURL := urlPrepend + roomName + "_cover" + filepath.Ext(roomPhoto.Filename)
	src, err := roomPhoto.Open()
	if err != nil {
		return err
	}
	defer src.Close()
	coverImageData, err := io.ReadAll(src)
	if err != nil {
		s.Log.Err(err).Msgf("Unable to read cover photo file: ", err)
		return err
	}
	err = os.WriteFile(coverImagePath, coverImageData, 0644)
	if err != nil {
		return err
	}
	newRoom := Room{
		Name:         roomName,
		CoverPhoto:   coverImageURL,
		Photos:       photoURLsList,
		Notes:        roomNotes,
		LocationID:   locID,
		LocationName: loc.Name,
	}
	err = s.AddRoom(newRoom)
	if err != nil {
		return err
	}
	// Update our location in the db to add the new room as attached to the ID
	loc, err = s.GetLocation(newRoom.LocationID)
	if err != nil {
		return err
	}
	roomList := loc.Rooms
	roomList = append(roomList, newRoom)

	err = s.Database.UpdateField(&Location{ID: newRoom.LocationID}, "Rooms", roomList)
	if err != nil {
		return err
	}
	s.Log.Debug().Msgf("Adding new Room: %v", newRoom)
	return c.Status(fiber.StatusOK).SendString(fmt.Sprintf("New Room Created! %s", newRoom.Name))
}

// GetAllRoomsHandler gets all of the rooms in the db
func (s *Server) GetAllRoomsHandler(c *fiber.Ctx) error {
	rooms, err := s.GetAllRooms()
	if err != nil {
		return err
	}
	return c.Status(fiber.StatusOK).JSON(rooms)
}

// GetRoomsAtLocationHandler gets rooms at a location
func (s *Server) GetRoomsAtLocationHandler(c *fiber.Ctx) error {
	locID, err := c.ParamsInt("locID")
	if err != nil {
		return err
	}
	rooms, err := s.GetRoomsAtLocation(locID)
	fmt.Println("ROOMS: ", rooms)
	if err != nil {
		return err
	}
	return c.Status(fiber.StatusOK).JSON(rooms)
}
