package internal

import (
	"context"

	api "git.vdhsn.com/barretthousen/barretthousen/src/runner/api/grpc"
	"git.vdhsn.com/barretthousen/barretthousen/src/runner/internal/domain"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"google.golang.org/protobuf/types/known/timestamppb"
)

func NewRunnerServer(d *domain.Domain) func(grpcServer grpc.ServiceRegistrar, endpoint string) {
	return func(grpcServer grpc.ServiceRegistrar, endpoint string) {
		api.RegisterRunnerServer(grpcServer, &runnerHandler{domain: d})
	}
}

type runnerHandler struct {
	api.UnimplementedRunnerServer
	domain *domain.Domain
}

func (rh *runnerHandler) StartSync(ctx context.Context, cmd *api.SyncParameters) (*api.SyncStatus, error) {
	out, err := rh.domain.StartSync(ctx, domain.FindNewUpcomingInput{
		TargetSite: cmd.TargetSite,
	})
	if err != nil {
		return nil, status.Errorf(codes.Internal, "method FindNewUpcoming failed: %q", err.Error())
	}

	return &api.SyncStatus{
		Id:             int32(out.Job.ID),
		AuctionsFound:  int32(out.Job.AuctionsFound),
		CreatedTs:      timestamppb.New(out.Job.Started),
		CompletedTs:    nil,
		TargetSiteName: out.Job.TargetSite,
		Errors:         out.Job.Errors,
	}, nil
}

func (rh *runnerHandler) Status(ctx context.Context, cmd *api.StatusFilter) (*api.SyncStatusList, error) {
	out, err := rh.domain.Status(ctx, domain.GetJobsInput{})
	if err != nil {
		return nil, status.Errorf(codes.Internal, "method GetJobs failed: %q", err.Error())
	}

	result := &api.SyncStatusList{
		Results: []*api.SyncStatus{},
	}

	for _, j := range out.Jobs {
		var completedTime *timestamppb.Timestamp

		if !j.Completed.IsZero() {
			completedTime = timestamppb.New(j.Completed)
		}

		result.Results = append(result.Results, &api.SyncStatus{
			Id:             int32(j.ID),
			AuctionsFound:  int32(j.AuctionsFound),
			CreatedTs:      timestamppb.New(j.Started),
			CompletedTs:    completedTime,
			TargetSiteName: j.TargetSite,
			Errors:         j.Errors,
		})

	}

	return result, nil
}
