package app.mealsmadeeasy.api.recipe.job;

import app.mealsmadeeasy.api.ai.InferenceService;
import app.mealsmadeeasy.api.job.Job;
import app.mealsmadeeasy.api.job.JobHandler;
import app.mealsmadeeasy.api.recipe.Recipe;
import app.mealsmadeeasy.api.recipe.RecipeRepository;
import app.mealsmadeeasy.api.recipe.RecipeSummary;
import app.mealsmadeeasy.api.util.NoSuchEntityWithIdException;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.stereotype.Component;

import java.time.OffsetDateTime;
import java.util.List;

@Component
@RequiredArgsConstructor
public class RecipeSummaryJobHandler implements JobHandler<RecipeSummaryJobHandler.RecipeSummaryJobPayload> {

    public static final String JOB_KEY = "RECIPE_SUMMARY";

    public record RecipeSummaryJobPayload(Integer recipeId) {}

    private static final Logger logger = LoggerFactory.getLogger(RecipeSummaryJobHandler.class);

    private final RecipeRepository recipeRepository;
    private final InferenceService inferenceService;
    private final EmbeddingModel embeddingModel;

    @Override
    public Class<RecipeSummaryJobPayload> getPayloadType() {
        return RecipeSummaryJobPayload.class;
    }

    @Override
    public String getJobKey() {
        return JOB_KEY;
    }

    @Override
    public void handle(Job job, RecipeSummaryJobPayload payload) {
        logger.info("Summarizing recipe with id {}", payload.recipeId());
        final Recipe recipe = this.recipeRepository.findById(payload.recipeId())
                .orElseThrow(() -> new NoSuchEntityWithIdException(Recipe.class, payload.recipeId()));
        final @Nullable String summary = this.inferenceService.infer(List.of(
                SystemMessage.builder()
                        .text(
                                "Summarize the given recipe in three sentences or less. " +
                                        "Output your summary as plain text. " +
                                        "Make sure to include the title of the recipe in your summary."
                        )
                        .build(),
                UserMessage.builder().text(
                        "<title>" + recipe.getTitle() + "</title>\n" + recipe.getRawText()
                ).build()
        ));
        if (summary == null) {
            throw new RuntimeException("Summary of recipe with id " + recipe.getId() + " came back null");
        }
        logger.debug("Summary of recipe with id {}: {}", recipe.getId(), summary);

        final float[] summaryEmbedding = this.embeddingModel.embed(summary);

        final RecipeSummary recipeSummary = recipe.getSummary() != null ? recipe.getSummary() : new RecipeSummary();
        recipeSummary.setSummary(summary);
        recipeSummary.setEmbedding(summaryEmbedding);
        recipeSummary.setRecipe(recipe);
        recipeSummary.setTimestamp(OffsetDateTime.now());
        recipe.setSummary(recipeSummary);
        this.recipeRepository.saveAndFlush(recipe);

        logger.info("Finished summarizing and creating embedding for recipe with id {}", recipe.getId());
    }

}
