package main

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

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

// GetAllItemsHandler gets all items
func (s *Server) GetAllItemsHandler(c *fiber.Ctx) error {
	items, err := s.GetAllItems()
	if err != nil {
		return err
	}
	return c.Status(fiber.StatusOK).JSON(items)
}

// GetItemHandler returns a single item from an ID
func (s *Server) GetItemHandler(c *fiber.Ctx) error {
	itemID, err := c.ParamsInt("itemID")
	if err != nil {
		return err
	}
	room, err := s.GetItem(itemID)
	if err != nil {
		s.Log.Err(err).Msgf("Unable to fetch item with id: %d", itemID)
		return err
	}
	return c.Status(fiber.StatusOK).JSON(room)
}

// GetAllItemsAtRoomHandler gets all items in a room
func (s *Server) GetAllItemsAtRoomHandler(c *fiber.Ctx) error {
	roomID, err := c.ParamsInt("roomID")
	if err != nil {
		return err
	}
	items, err := s.GetItemsInRoom(roomID)
	fmt.Println("Items: ", items)
	if err != nil {
		return err
	}
	return c.Status(fiber.StatusOK).JSON(items)
}

// GetAllItemsAtCabinetHandler gets all items in a cabinet
func (s *Server) GetAllItemsAtCabinetHandler(c *fiber.Ctx) error {
	cabinetID, err := c.ParamsInt("cabinetID")
	if err != nil {
		return err
	}
	items, err := s.GetItemsInCabinet(cabinetID)
	if err != nil {
		return err
	}
	return c.Status(fiber.StatusOK).JSON(items)
}

// AddNewItemHandler adds a new item
func (s *Server) AddNewItemHandler(c *fiber.Ctx) error {
	// If we supply a room ID it is an item in a room, if not it is in a cabinet
	storageType := "room"
	cabinetID := 0
	roomID, err := c.ParamsInt("roomID")
	if err != nil {
		return err
	}
	if roomID == 0 {
		storageType = "cabinet"
		cabinetID, err = c.ParamsInt("cabinetID")
		if err != nil {
			return err
		}
	}
	form, err := c.MultipartForm()
	if err != nil {
		s.Log.Err(err).Msgf("Unable to fetch item form details: ", err)
		return err
	}
	itemName := form.Value["Name"][0]
	fmt.Println("COverphoto: ", form.File["CoverPhoto"])
	itemPhoto := form.File["CoverPhoto"][0]
	// if err != nil {
	// 	s.Log.Err(err).Msgf("Unable to get CoverPhoto for Room: ", err)
	// 	return err
	// }
	itemAdditionalPhotos := form.File["AdditionalPhotos"]

	room := Room{}
	cabinet := Cabinet{}

	if storageType == "room" {
		room, err = s.GetRoom(roomID)
		if err != nil {
			s.Log.Err(err).Msgf("Unable to fetch room by id: %d with error: %s", roomID, err)
			return err
		}
	} else {
		cabinet, err = s.GetCabinet(cabinetID)
		if err != nil {
			s.Log.Err(err).Msgf("Unable to fetch room by id: %d with error: %s", roomID, err)
			return err
		}
		room, err = s.GetRoom(cabinet.RoomID)
		if err != nil {
			s.Log.Err(err).Msgf("Unable to fetch room by id: %d with error: %s", cabinet.RoomID, err)
			return err
		}
	}
	loc, err := s.GetLocation(room.LocationID)
	if err != nil {
		s.Log.Err(err).Msgf("Unable to fetch location by id: %d with error: %s", room.LocationID, err)
		return err
	}

	urlPrepend := ""

	// setting the path prepend for the photos
	if storageType == "room" {
		urlPrepend = loc.Name + "/" + room.Name + "/" + itemName
	} else {
		urlPrepend = loc.Name + "/" + room.Name + "/" + cabinet.Name + "/" + itemName
	}
	pathPrepend := s.Config.Server.LocationFilesDir + "/" + urlPrepend + "/"

	// Create the directory for this item to store the photos
	err = os.MkdirAll(filepath.ToSlash(pathPrepend), 0755)
	if err != nil {
		return err
	}
	var photoURLsList []string
	for i, photo := range itemAdditionalPhotos {
		src, err := photo.Open()
		if err != nil {
			return err
		}
		defer src.Close()

		photoPath := filepath.ToSlash(pathPrepend + itemName + "_" + strconv.Itoa(i) + filepath.Ext(photo.Filename))
		photoURL := urlPrepend + itemName + "_" + 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
	itemNotes := form.Value["Notes"][0]

	// saving the uploaded image to our images dir
	coverImagePath := filepath.ToSlash(pathPrepend + itemName + "_cover" + filepath.Ext(itemPhoto.Filename))
	// Creating the URL to retrieve photo
	coverImageURL := urlPrepend + itemName + "_cover" + filepath.Ext(itemPhoto.Filename)
	src, err := itemPhoto.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
	}

	newItem := Item{
		Name:       itemName,
		CoverPhoto: coverImageURL,
		Photos:     photoURLsList,
		Notes:      itemNotes,
	}

	if storageType == "room" {
		newItem.RoomID = room.ID
		itemList := room.Items
		itemList = append(itemList, newItem)
		err = s.Database.UpdateField(&Room{ID: roomID}, "Items", itemList)
		if err != nil {
			return err
		}
	} else {
		newItem.CabinetID = cabinet.ID
		itemList := cabinet.Items
		itemList = append(itemList, newItem)
		err = s.Database.UpdateField(&Cabinet{ID: cabinetID}, "Items", itemList)
		if err != nil {
			return err
		}
	}

	err = s.AddItem(newItem)
	if err != nil {
		return err
	}

	s.Log.Debug().Msgf("Adding new Room: %v", newItem)
	return c.Status(fiber.StatusOK).SendString(fmt.Sprintf("New Room Created! %s", newItem.Name))
}

// DeleteItemHandler deletes an item based on an ID
func (s *Server) DeleteItemHandler(c *fiber.Ctx) error {
	itemID, err := c.ParamsInt("itemID")
	if err != nil {
		return err
	}
	item, err := s.GetItem(itemID)
	if err != nil {
		s.Log.Err(err).Msgf("Unable to fetch item with id: %d", itemID)
		return err
	}
	err = s.DeleteItem(item)
	if err != nil {
		s.Log.Err(err).Msgf("Unable to delete item with id: %d", itemID)
		return err
	}
	return c.Status(fiber.StatusOK).SendString(fmt.Sprintf("Item Deleted! %d", itemID))
}
