package service

import (
	"fmt"
	"iot_manager_service/app/multimedia/dao"
	"iot_manager_service/app/multimedia/model"
	"iot_manager_service/app/system/service"
	"iot_manager_service/config"
	"iot_manager_service/util/common"
	"iot_manager_service/util/logger"
	"iot_manager_service/util/minio"
	"mime/multipart"
	"strings"
	"time"
)

var LibraryService = new(libraryService)

type libraryService struct{}

func (s *libraryService) Get(id int) (*dao.Library, *common.Errors) {
	library := &dao.Library{
		ID: id,
	}
	err := library.Get()
	if err != nil {
		return nil, common.FailResponse(err.Error(), nil)
	}
	return library, nil
}

func (s *libraryService) List(tenantId string, searchValue string, current, size, sysType, libType int) ([]model.LibraryDetail, int64,
	*common.Errors) {
	library := &dao.Library{
		TenantId: tenantId,
		SysType:  sysType,
		LibType:  libType,
	}

	offset := (current - 1) * size
	limit := size

	if searchValue != "" {
		library.LibName = searchValue
	}
	if sysType != -1 {
		library.SysType = sysType
	}
	libraries, total, err := library.GetLibraries(offset, limit)
	if err != nil {
		return nil, 0, common.FailResponse(err.Error(), nil)
	}

	var rsp []model.LibraryDetail
	for _, lib := range libraries {
		rsp = append(rsp, model.LibToModel(lib))
	}
	return rsp, total, nil
}

func (s *libraryService) Remove(userId int, tenantId string, id int) *common.Errors {
	library := &dao.Library{
		ID:         id,
		IsDeleted:  1,
		UpdateUser: userId,
		UpdateTime: time.Now(),
	}
	err := library.Delete()
	if err != nil {
		return common.FailResponse(err.Error(), nil)
	}
	service.OperationHisService.Save(userId, tenantId, common.OperationRemove, common.ModuleTypeInfoBar,
		common.DeviceTypeDefault, "", common.OperationSuccess)
	return nil
}

func (s *libraryService) GetList(tenantId string, libName string, libType, sysType int) ([]dao.Library, *common.Errors) {
	library := &dao.Library{
		TenantId: tenantId,
		LibName:  libName,
		LibType:  libType,
		SysType:  sysType,
	}
	libraries, err := library.GetAll()
	if err != nil {
		return nil, common.FailResponse(err.Error(), nil)
	}

	return libraries, nil
}

func (s *libraryService) UploadFile(tenantId string, fileHeader *multipart.FileHeader) (*model.RspUploadFile,
	*common.Errors) {
	fileContent, err := fileHeader.Open()
	if err != nil {
		logger.Logger.Errorf("UploadFile fileHeader.Open fail, err = %s", err.Error())
		return nil, common.ParamsInvalidResponse(err.Error(), nil)
	}

	fileNameArray := strings.Split(fileHeader.Filename, ".")
	if len(fileNameArray) < 2 {
		return nil, common.ParamsInvalidResponse("invalid file name", nil)
	}
	// happy8as8f0980f_92389h.jpg
	objectName := "library/" + common.RandomString2(16) + "_" + common.RandomString2(6) + "." + fileNameArray[len(
		fileNameArray)-1]

	bucket := fmt.Sprintf("longchi-%v", tenantId)
	err = minio.PutFile(minio.FileObject{
		Bucket:     bucket,
		ObjectName: objectName,
		ObjectSize: fileHeader.Size,
		Reader:     fileContent,
	})
	if err != nil {
		logger.Logger.Errorf("UploadFile PutFile fail, err = %s", err.Error())
		return nil, common.FailResponse("", nil)
	}

	contentTypeArr := fileHeader.Header["Content-Type"]
	contentType := ""
	if len(contentTypeArr) > 0 {
		contentType = contentTypeArr[0]
	}
	fileType := 0
	if contentType == "image/jpeg" {
		fileType = 2
	} else if contentType == "video/mp4" {
		fileType = 1
	} else if contentType == "audio/mpeg" {
		fileType = 3
	}
	duration := 0
	if fileType == 2 {
		duration = 3
	} else {
		duration, err = common.GetMediaDuration(fileContent, contentType)
		if err != nil {
			logger.Logger.Errorf("UploadFile duration fail, err = %s", err.Error())
			duration = 0
		}
	}
	return &model.RspUploadFile{
		Link:         config.Instance().Minio.Link + "/" + bucket + "/" + objectName,
		Domain:       "",
		Name:         objectName,
		OriginalName: fileHeader.Filename,
		AttachId:     0,
		Duration:     duration,
		Resolution:   "",
		FileSize:     fileHeader.Size,
		FileType:     fileType,
	}, nil
}

func (s *libraryService) Submit(tenantId string, userId int, req dao.Library) *common.Errors {
	library := &req
	library.TenantId = tenantId
	library.UpdateUser = userId
	library.UpdateTime = time.Now()

	if library.ID == 0 {
		library.CreateTime = time.Now()
		library.CreateUser = userId
		if err := library.Create(); err != nil {
			logger.Logger.Errorf("Create err = %s \n", err.Error())
			return common.FailResponse(err.Error(), nil)
		}
		service.OperationHisService.Save(userId, tenantId, common.OperationCreate, common.ModuleTypeInfoBar,
			common.DeviceTypeDefault, library.LibName, common.OperationSuccess)
		return common.SuccessResponse(common.Succeeded, nil)
	}
	if err := library.Update(); err != nil {
		logger.Logger.Errorf("Update err = %s \n", err.Error())
		return common.FailResponse(err.Error(), nil)
	}

	service.OperationHisService.Save(userId, tenantId, common.OperationUpdate, common.ModuleTypeInfoBar,
		common.DeviceTypeDefault, library.LibName, common.OperationSuccess)
	return common.SuccessResponse(common.Succeeded, nil)
}