package dev.dinauer.maven.maven.core.artifact.metadata;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import dev.dinauer.maven.Lists;
import dev.dinauer.maven.maven.core.ArtifactId;
import dev.dinauer.maven.maven.core.ArtifactRepo;
import dev.dinauer.maven.maven.core.Version;
import dev.dinauer.maven.maven.core.artifact.metadata.model.ArtifactMetadata;
import dev.dinauer.maven.maven.core.artifact.metadata.model.ArtifactVersioning;
import dev.dinauer.maven.maven.core.context.ArtifactContext;
import dev.dinauer.maven.maven.core.context.VersionContext;
import dev.dinauer.maven.maven.core.release.ReleaseVersion;
import dev.dinauer.maven.maven.core.snapshot.SnapshotBundle;
import dev.dinauer.maven.maven.core.snapshot.metadata.model.Snapshot;
import dev.dinauer.maven.maven.core.snapshot.metadata.model.SnapshotMetadata;
import dev.dinauer.maven.maven.core.snapshot.metadata.model.SnapshotVersion;
import dev.dinauer.maven.maven.core.snapshot.metadata.model.SnapshotVersioning;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.InternalServerErrorException;
import jakarta.ws.rs.NotFoundException;
import org.apache.commons.codec.digest.DigestUtils;

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

@ApplicationScoped
public class ArtifactMetadataService
{
    private static final XmlMapper XML_MAPPER = new XmlMapper();
    private final ArtifactRepo artifactRepo;

    @Inject
    public ArtifactMetadataService(ArtifactRepo artifactRepo)
    {
        this.artifactRepo = artifactRepo;
    }

    public String generate(ArtifactContext artifactContext)
    {
        try
        {
            return XML_MAPPER.writeValueAsString(generateMetadata(artifactContext));
        }
        catch (JsonProcessingException e)
        {
            throw new InternalServerErrorException();
        }
    }

    private ArtifactMetadata generateMetadata(ArtifactContext artifactContext)
    {
        ArtifactId artifactId = artifactRepo.findOptionalByArtifactId(artifactContext.groupId(), artifactContext.artifactId()).orElseThrow(NotFoundException::new);
        ZonedDateTime lastUpdated = artifactId.getUpdatedAt();
        List<Version> versions = artifactId.getVersions();
        Version latest = versions.getFirst();
        String latestRelease = latestRelease(artifactId);
        return new ArtifactMetadata(artifactId.getGroupId(), artifactId.getArtifactId(), new ArtifactVersioning(latest.getVersion(), latestRelease, versions.stream().map(Version::getVersion).toList().reversed(), lastUpdated.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))));
    }

    public String generateHash(ArtifactContext artifactContext)
    {
        switch (artifactContext.extensions().hashExt().orElseThrow())
        {
            case MD5 ->
            {
                return DigestUtils.md5Hex(generate(artifactContext));
            }
            case SHA256 ->
            {
                return DigestUtils.sha256Hex(generate(artifactContext));
            }
        }
        throw new IllegalArgumentException();
    }

    private String latestRelease(ArtifactId artifactId)
    {
        ReleaseVersion releaseVersion = Lists.getFirst(artifactId.getReleaseVersions());
        if (releaseVersion != null)
        {
            return releaseVersion.getVersion();
        }
        return null;
    }
}
