package banner

import (
    "context"
    "time"

    "bindbox-game/internal/pkg/logger"
    "bindbox-game/internal/repository/mysql"
    "bindbox-game/internal/repository/mysql/dao"
    "bindbox-game/internal/repository/mysql/model"
)

type Service interface {
    Create(ctx context.Context, in CreateInput) (*model.Banner, error)
    Modify(ctx context.Context, id int64, in ModifyInput) error
    Delete(ctx context.Context, id int64) error
    List(ctx context.Context, in ListInput) (items []*model.Banner, total int64, err error)
    ListEnabled(ctx context.Context) ([]*model.Banner, error)
}

type service struct {
    logger  logger.CustomLogger
    readDB  *dao.Query
    writeDB *dao.Query
}

func New(l logger.CustomLogger, db mysql.Repo) Service {
    return &service{logger: l, readDB: dao.Use(db.GetDbR()), writeDB: dao.Use(db.GetDbW())}
}

type CreateInput struct {
    Title    string
    ImageURL string
    LinkURL  string
    Sort     int32
    Status   int32
}

type ModifyInput struct {
    Title    *string
    ImageURL *string
    LinkURL  *string
    Sort     *int32
    Status   *int32
}

type ListInput struct {
    Status   *int32
    Page     int
    PageSize int
}

func (s *service) Create(ctx context.Context, in CreateInput) (*model.Banner, error) {
    m := &model.Banner{Title: in.Title, ImageURL: in.ImageURL, LinkURL: in.LinkURL, Sort: in.Sort, Status: in.Status}
    if err := s.writeDB.Banner.WithContext(ctx).Create(m); err != nil {
        return nil, err
    }
    return m, nil
}

func (s *service) Modify(ctx context.Context, id int64, in ModifyInput) error {
    updater := s.writeDB.Banner.WithContext(ctx).Where(s.writeDB.Banner.ID.Eq(id))
    set := map[string]any{}
    if in.Title != nil {
        set["title"] = *in.Title
    }
    if in.ImageURL != nil {
        set["image_url"] = *in.ImageURL
    }
    if in.LinkURL != nil {
        set["link_url"] = *in.LinkURL
    }
    if in.Sort != nil {
        set["sort"] = *in.Sort
    }
    if in.Status != nil {
        set["status"] = *in.Status
    }
    if len(set) == 0 {
        return nil
    }
    _, err := updater.Updates(set)
    return err
}

func (s *service) Delete(ctx context.Context, id int64) error {
    _, err := s.writeDB.Banner.WithContext(ctx).Where(s.writeDB.Banner.ID.Eq(id)).Updates(map[string]any{"deleted_at": time.Now()})
    return err
}

func (s *service) List(ctx context.Context, in ListInput) (items []*model.Banner, total int64, err error) {
    if in.Page <= 0 {
        in.Page = 1
    }
    if in.PageSize <= 0 {
        in.PageSize = 20
    }
    q := s.readDB.Banner.WithContext(ctx).ReadDB()
    if in.Status != nil {
        q = q.Where(s.readDB.Banner.Status.Eq(*in.Status))
    }
    total, err = q.Count()
    if err != nil {
        return
    }
    items, err = q.Order(s.readDB.Banner.Sort.Asc()).Order(s.readDB.Banner.ID.Desc()).Limit(in.PageSize).Offset((in.Page-1)*in.PageSize).Find()
    return
}

func (s *service) ListEnabled(ctx context.Context) ([]*model.Banner, error) {
    return s.readDB.Banner.WithContext(ctx).ReadDB().Where(s.readDB.Banner.Status.Eq(1)).Order(s.readDB.Banner.Sort.Asc()).Order(s.readDB.Banner.ID.Desc()).Find()
}