package job

import (
	"haixun-backend/internal/model/job/domain/entity"
	"haixun-backend/internal/types"
)

func toJobTemplateData(template *entity.Template) types.JobTemplateData {
	steps := make([]types.JobTemplateStepData, 0, len(template.Steps))
	for _, step := range template.Steps {
		steps = append(steps, types.JobTemplateStepData{
			ID:             step.ID,
			Name:           step.Name,
			WorkerType:     step.WorkerType,
			TimeoutSeconds: step.TimeoutSeconds,
			Cancelable:     step.Cancelable,
		})
	}
	return types.JobTemplateData{
		Type:              template.Type,
		Version:           template.Version,
		Name:              template.Name,
		Description:       template.Description,
		Enabled:           template.Enabled,
		Repeatable:        template.Repeatable,
		ConcurrencyPolicy: template.ConcurrencyPolicy,
		DedupeKeys:        template.DedupeKeys,
		TimeoutSeconds:    template.TimeoutSeconds,
		CancelPolicy: types.JobCancelPolicyData{
			Supported:    template.CancelPolicy.Supported,
			Mode:         template.CancelPolicy.Mode,
			GraceSeconds: template.CancelPolicy.GraceSeconds,
		},
		RetryPolicy: types.JobRetryPolicyData{
			MaxAttempts:    template.RetryPolicy.MaxAttempts,
			BackoffSeconds: template.RetryPolicy.BackoffSeconds,
		},
		Steps: steps,
	}
}

func toJobData(run *entity.Run) types.JobData {
	steps := make([]types.JobStepProgressData, 0, len(run.Progress.Steps))
	for _, step := range run.Progress.Steps {
		steps = append(steps, types.JobStepProgressData{
			ID:        step.ID,
			Status:    string(step.Status),
			StartedAt: step.StartedAt,
			EndedAt:   step.EndedAt,
			Message:   step.Message,
		})
	}
	return types.JobData{
		ID:              run.ID.Hex(),
		TemplateType:    run.TemplateType,
		TemplateVersion: run.TemplateVersion,
		Scope:           run.Scope,
		ScopeID:         run.ScopeID,
		Status:          string(run.Status),
		Phase:           run.Phase,
		WorkerType:      run.WorkerType,
		Payload:         run.Payload,
		Progress: types.JobProgressData{
			Summary:    run.Progress.Summary,
			Percentage: run.Progress.Percentage,
			Steps:      steps,
		},
		Result:            run.Result,
		Error:             run.Error,
		Attempt:           run.Attempt,
		MaxAttempts:       run.MaxAttempts,
		CancelRequestedAt: run.CancelRequestedAt,
		CancelReason:      run.CancelReason,
		StartedAt:         run.StartedAt,
		CompletedAt:       run.CompletedAt,
		CreateAt:          run.CreateAt,
		UpdateAt:          run.UpdateAt,
	}
}

func ToJobData(run *entity.Run) types.JobData {
	return toJobData(run)
}

func toJobScheduleData(schedule *entity.Schedule) types.JobScheduleData {
	return types.JobScheduleData{
		ID:              schedule.ID.Hex(),
		TemplateType:    schedule.TemplateType,
		Scope:           schedule.Scope,
		ScopeID:         schedule.ScopeID,
		Enabled:         schedule.Enabled,
		Cron:            schedule.Cron,
		Timezone:        schedule.Timezone,
		PayloadTemplate: schedule.PayloadTemplate,
		LastRunAt:       schedule.LastRunAt,
		NextRunAt:       schedule.NextRunAt,
		CreateAt:        schedule.CreateAt,
		UpdateAt:        schedule.UpdateAt,
	}
}

func toJobEventData(event *entity.Event) types.JobEventData {
	return types.JobEventData{
		ID:       event.ID.Hex(),
		JobID:    event.JobID,
		Type:     event.Type,
		From:     event.From,
		To:       event.To,
		Message:  event.Message,
		Metadata: event.Metadata,
		CreateAt: event.CreateAt,
	}
}

func toTemplateSteps(steps []types.JobTemplateStepData) []entity.TemplateStep {
	out := make([]entity.TemplateStep, 0, len(steps))
	for _, step := range steps {
		out = append(out, entity.TemplateStep{
			ID:             step.ID,
			Name:           step.Name,
			WorkerType:     step.WorkerType,
			TimeoutSeconds: step.TimeoutSeconds,
			Cancelable:     step.Cancelable,
		})
	}
	return out
}
