package repository

import (
	"campaign-pool-be/app/database"
	"campaign-pool-be/app/database/entity"
	"campaign-pool-be/app/module/campaign_files/request"
	"campaign-pool-be/utils/paginator"
	utilSvc "campaign-pool-be/utils/service"
	"fmt"

	"github.com/rs/zerolog"
)

type campaignFilesRepository struct {
	DB  *database.Database
	Log zerolog.Logger
}

type CampaignFilesRepository interface {
	GetAll(req request.CampaignFilesQueryRequest) (campaignFiless []*entity.CampaignFiles, paging paginator.Pagination, err error)
	FindOne(id uint) (campaignFiles *entity.CampaignFiles, err error)
	FindByCampaign(campaignID uint) (campaignFiles []*entity.CampaignFiles, err error)
	Create(campaignFiles *entity.CampaignFiles) (campaignFilesReturn *entity.CampaignFiles, err error)
	Update(id uint, campaignFiles *entity.CampaignFiles) (err error)
	Delete(id uint) (err error)
}

func NewCampaignFilesRepository(db *database.Database, log zerolog.Logger) CampaignFilesRepository {
	return &campaignFilesRepository{
		DB:  db,
		Log: log,
	}
}

func (_i *campaignFilesRepository) GetAll(req request.CampaignFilesQueryRequest) (campaignFiless []*entity.CampaignFiles, paging paginator.Pagination, err error) {
	var count int64

	query := _i.DB.DB.Model(&entity.CampaignFiles{}).Preload("Campaign")

	if req.CampaignID != nil {
		query = query.Where("campaign_id = ?", req.CampaignID)
	}
	if req.Type != nil && *req.Type != "" {
		query = query.Where("type = ?", req.Type)
	}
	query.Count(&count)

	if req.Pagination.SortBy != "" {
		direction := "ASC"
		if req.Pagination.Sort == "desc" {
			direction = "DESC"
		}
		query.Order(fmt.Sprintf("%s %s", req.Pagination.SortBy, direction))
	} else {
		query.Order("created_at DESC")
	}

	req.Pagination.Count = count
	req.Pagination = paginator.Paging(req.Pagination)

	err = query.Offset(req.Pagination.Offset).Limit(req.Pagination.Limit).Find(&campaignFiless).Error
	if err != nil {
		return
	}

	paging = *req.Pagination
	return
}

func (_i *campaignFilesRepository) FindOne(id uint) (campaignFiles *entity.CampaignFiles, err error) {
	query := _i.DB.DB.Where("id = ?", id).Preload("Campaign")
	if err := query.First(&campaignFiles).Error; err != nil {
		return nil, err
	}
	return campaignFiles, nil
}

func (_i *campaignFilesRepository) FindByCampaign(campaignID uint) (campaignFiles []*entity.CampaignFiles, err error) {
	query := _i.DB.DB.Where("campaign_id = ?", campaignID).Preload("Campaign")
	err = query.Find(&campaignFiles).Error
	return
}

func (_i *campaignFilesRepository) Create(campaignFiles *entity.CampaignFiles) (campaignFilesReturn *entity.CampaignFiles, err error) {
	result := _i.DB.DB.Create(campaignFiles)
	return campaignFiles, result.Error
}

func (_i *campaignFilesRepository) Update(id uint, campaignFiles *entity.CampaignFiles) (err error) {
	campaignFilesMap, err := utilSvc.StructToMap(campaignFiles)
	if err != nil {
		return err
	}
	return _i.DB.DB.Model(&entity.CampaignFiles{}).Where(&entity.CampaignFiles{ID: id}).Updates(campaignFilesMap).Error
}

func (_i *campaignFilesRepository) Delete(id uint) error {
	return _i.DB.DB.Delete(&entity.CampaignFiles{}, id).Error
}

