package job

import (
	"system-altrak/internal/domain"
	"time"
)

type JobService interface {
	CreateJob(jobType, description string, totalItems int, branchID, userID uint) (*domain.BackgroundJob, error)
	StartJob(jobID uint) error
	UpdateProgress(jobID uint, processed int, description string) error
	CompleteJob(jobID uint) error
	FailJob(jobID uint, message string) error
	GetActiveJobs(branchID uint) ([]domain.BackgroundJob, error)
	ListJobs(page, limit int, branchID uint) ([]domain.BackgroundJob, int64, error)
	GetJobByID(id uint) (*domain.BackgroundJob, error)
}

type serviceImpl struct {
	repo JobRepository
}

func NewService(repo JobRepository) JobService {
	return &serviceImpl{repo: repo}
}

func (s *serviceImpl) CreateJob(jobType, description string, totalItems int, branchID, userID uint) (*domain.BackgroundJob, error) {
	job := &domain.BackgroundJob{
		JobType:     jobType,
		Description: description,
		Status:      "PENDING",
		TotalItems:  totalItems,
		Progress:    0,
		BranchID:    branchID,
		CreatedBy:   userID,
	}
	err := s.repo.Create(job)
	return job, err
}

func (s *serviceImpl) StartJob(jobID uint) error {
	job, err := s.repo.GetByID(jobID)
	if err != nil {
		return err
	}
	now := time.Now()
	job.Status = "PROCESSING"
	job.StartedAt = &now
	return s.repo.Update(job)
}

func (s *serviceImpl) UpdateProgress(jobID uint, processed int, description string) error {
	job, err := s.repo.GetByID(jobID)
	if err != nil {
		return err
	}
	job.Processed = processed
	if job.TotalItems > 0 {
		job.Progress = (processed * 100) / job.TotalItems
	}
	if description != "" {
		job.Description = description
	}
	return s.repo.Update(job)
}

func (s *serviceImpl) CompleteJob(jobID uint) error {
	job, err := s.repo.GetByID(jobID)
	if err != nil {
		return err
	}
	now := time.Now()
	job.Status = "COMPLETED"
	job.Progress = 100
	job.CompletedAt = &now
	return s.repo.Update(job)
}

func (s *serviceImpl) FailJob(jobID uint, message string) error {
	job, err := s.repo.GetByID(jobID)
	if err != nil {
		return err
	}
	now := time.Now()
	job.Status = "FAILED"
	job.ErrorMessage = message
	job.CompletedAt = &now
	return s.repo.Update(job)
}

func (s *serviceImpl) GetActiveJobs(branchID uint) ([]domain.BackgroundJob, error) {
	return s.repo.ListActive(branchID)
}

func (s *serviceImpl) ListJobs(page, limit int, branchID uint) ([]domain.BackgroundJob, int64, error) {
	return s.repo.ListAll(page, limit, branchID)
}

func (s *serviceImpl) GetJobByID(id uint) (*domain.BackgroundJob, error) {
	return s.repo.GetByID(id)
}
