package storage

import (
	"context"
	"io"
	"mime/multipart"
	"os"
	"path/filepath"

	filemanager "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/file_manager"
)

type Storage struct {
	basePath string
}

func New(basePath string) *Storage {
	return &Storage{
		basePath: basePath,
	}
}

func (s *Storage) GetFilePaths(
	ctx context.Context,
	fileType filemanager.FileType,
	parameters filemanager.ParameterTable,
) ([]string, error) {
	var dirPath string

	fileNames := make([]string, 0)

	switch fileType {
	case filemanager.AvatarFileType:
		userId, ok := parameters[filemanager.UserIdParam]
		if !ok {
			return nil, filemanager.ErrParameterNotFound
		}

		dirPath = filepath.Join(s.basePath, userId.(string), "avatars")

	case filemanager.CVFileType:
		submId, ok := parameters[filemanager.SubmissionIdParam]
		if !ok {
			return nil, filemanager.ErrParameterNotFound
		}

		dirPath = filepath.Join(s.basePath, "CVs", submId.(string))

	default:
		return nil, filemanager.ErrInvalidFileType
	}

	if _, err := os.Stat(dirPath); os.IsNotExist(err) {
		return nil, filemanager.ErrFileNotFound
	}

	if err := filepath.WalkDir(dirPath, func(path string, d os.DirEntry, err error) error {
		if err != nil {
			return err
		}

		if d.IsDir() {
			return nil
		}

		fileNames = append(fileNames, path)

		return nil
	}); err != nil {
		return nil, err
	}

	if len(fileNames) == 0 {
		return nil, filemanager.ErrFileNotFound
	}

	return fileNames, nil
}

func (s *Storage) SaveFile(
	ctx context.Context,
	fileType filemanager.FileType,
	file multipart.File,
	fileHeader *multipart.FileHeader,
	parameters filemanager.ParameterTable,
) error {
	var dirPath string

	switch fileType {
	case filemanager.AvatarFileType:
		userId, ok := parameters[filemanager.UserIdParam]
		if !ok {
			return filemanager.ErrParameterNotFound
		}

		dirPath = filepath.Join(s.basePath, userId.(string), "avatars")

	case filemanager.CVFileType:
		submId, ok := parameters[filemanager.SubmissionIdParam]
		if !ok {
			return filemanager.ErrParameterNotFound
		}

		dirPath = filepath.Join(s.basePath, "CVs", submId.(string))

	default:
		return filemanager.ErrInvalidFileType
	}

	if err := os.MkdirAll(dirPath, 0755); err != nil {
		return err
	}

	filePath := filepath.Join(dirPath, fileHeader.Filename)

	dstFile, err := os.Create(filePath)
	if err != nil {
		return err
	}
	defer dstFile.Close()

	if _, err := io.Copy(dstFile, file); err != nil {
		return err
	}

	return nil
}
