package dev.dinauer.maven.maven.core;

import dev.dinauer.maven.maven.core.artifact.metadata.ArtifactMetadataService;
import dev.dinauer.maven.maven.core.context.ArtifactContext;
import dev.dinauer.maven.maven.core.context.ReleaseContext;
import dev.dinauer.maven.maven.core.context.SnapshotContext;
import dev.dinauer.maven.maven.core.context.VersionContext;
import dev.dinauer.maven.maven.core.model.*;
import dev.dinauer.maven.maven.core.release.ReleaseService;
import dev.dinauer.maven.maven.core.release.parser.ReleaseFile;
import dev.dinauer.maven.maven.core.release.parser.ReleaseFileParser;
import dev.dinauer.maven.maven.core.snapshot.SnapshotFile;
import dev.dinauer.maven.maven.core.snapshot.SnapshotService;
import dev.dinauer.maven.maven.core.snapshot.metadata.SnapshotMetadataService;
import dev.dinauer.maven.maven.core.snapshot.parser.SnapshotFileParser;
import dev.dinauer.maven.maven.shared.ParserResult;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Objects;

@ApplicationScoped
public class MavenService
{
    private static final Logger LOG = LoggerFactory.getLogger(MavenService.class);

    @Inject
    ReleaseService releaseService;

    @Inject
    SnapshotService snapshotService;
    @Inject
    SnapshotMetadataService snapshotMetadataService;
    @Inject
    ArtifactMetadataService artifactMetadataService;

    public void upload(String path, byte[] body)
    {
        ArtifactContext context = MavenContextProvider.parse(path);
        if (context.getClass() == VersionContext.class)
        {
            if (List.of(FileExt.JAR, FileExt.POM).contains(context.extensions().ext()) && context.extensions().hashExt().isEmpty())
            {
                VersionContext versionContext = (VersionContext) context;
                if (versionContext.isSnapshot())
                {
                    snapshotService.upload(toSnapshotContext(versionContext), body);
                }
                else
                {
                    releaseService.upload(toReleaseContext(versionContext), body);
                }
            }
            if (Objects.equals(FileExt.XML, context.extensions().ext()))
            {
                LOG.debug("Ignoring metadata upload for {}. Metadata files are generated by the registry.", path);
            }
        }
        if (context.getClass() == ArtifactContext.class)
        {
            LOG.debug("Ignoring metadata upload for {}. Metadata files are generated by the registry.", path);
        }
    }

    public Response serve(String path)
    {
        ArtifactContext context = MavenContextProvider.parse(path);
        if (context.getClass() == VersionContext.class)
        {
            VersionContext versionContext = (VersionContext) context;
            if (List.of(FileExt.JAR, FileExt.POM).contains(context.extensions().ext()))
            {
                if (versionContext.isSnapshot())
                {
                    return snapshotService.serve(toSnapshotContext(versionContext));
                }
                else
                {
                    return releaseService.serve(toReleaseContext(versionContext));
                }
            }
            if (Objects.equals(FileExt.XML, context.extensions().ext()))
            {
                if (context.extensions().hashExt().isEmpty())
                {
                    return Response.status(200).type(MediaType.APPLICATION_XML).entity(snapshotMetadataService.generate(versionContext)).build();
                }
                else
                {
                    return Response.status(200).type(MediaType.TEXT_PLAIN).entity(snapshotMetadataService.generateHash(versionContext)).build();
                }
            }
        }
        if (context.getClass() == ArtifactContext.class)
        {
            if (context.extensions().hashExt().isEmpty())
            {
                return Response.status(200).type(MediaType.APPLICATION_XML).entity(artifactMetadataService.generate(context)).build();
            }
            else
            {
                return Response.status(200).type(MediaType.TEXT_PLAIN).entity(artifactMetadataService.generateHash(context)).build();
            }
        }
        throw new BadRequestException();
    }

    private SnapshotContext toSnapshotContext(VersionContext versionContext)
    {
        ParserResult<SnapshotFile> result = new SnapshotFileParser(versionContext.artifactId(), versionContext.plainVersion()).parse(versionContext.filename());
        return new SnapshotContext(
            versionContext.extensions(),
            versionContext.groupId(),
            versionContext.artifactId(),
            versionContext.filename(),
            versionContext.version(),
            result.result().getDate(),
            result.result().getTime(),
            result.result().getBuildNumber(),
            result.result().getClassifier()
        );
    }

    private ReleaseContext toReleaseContext(VersionContext versionContext)
    {
        ParserResult<ReleaseFile> result = new ReleaseFileParser(versionContext.artifactId(), versionContext.plainVersion()).parse(versionContext.filename());
        return new ReleaseContext(
            versionContext.extensions(),
            versionContext.groupId(),
            versionContext.artifactId(),
            versionContext.filename(),
            versionContext.version(),
            result.result().getClassifier()
        );
    }
}
