package org.kar.karideo.api;

import java.io.InputStream;
import java.util.List;
import java.util.UUID;

import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.kar.archidata.annotation.AsyncType;
import org.kar.archidata.annotation.TypeScriptProgress;
import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.QueryAnd;
import org.kar.archidata.dataAccess.QueryCondition;
import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson;
import org.kar.archidata.dataAccess.options.Condition;
import org.kar.archidata.tools.DataTools;
import org.kar.karideo.model.Series;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.security.RolesAllowed;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.PATCH;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@Path("/series")
@Produces(MediaType.APPLICATION_JSON)
public class SeriesResource {
	static final Logger LOGGER = LoggerFactory.getLogger(SeriesResource.class);

	@GET
	@RolesAllowed("USER")
	@Operation(description = "Get all Series", tags = "GLOBAL")
	public List<Series> gets() throws Exception {
		return DataAccess.gets(Series.class);
	}

	@GET
	@Path("{id}")
	@RolesAllowed("USER")
	@Consumes(MediaType.APPLICATION_JSON)
	@Operation(description = "Get a specific Series with his ID", tags = "GLOBAL")
	public Series get(@PathParam("id") final Long id) throws Exception {
		return DataAccess.get(Series.class, id);
	}

	public static Series getId(final Long id) throws Exception {
		return DataAccess.get(Series.class, id);
	}
	/* ============================================================================= ADMIN SECTION: ============================================================================= */

	@POST
	@RolesAllowed("ADMIN")
	@Consumes(MediaType.APPLICATION_JSON)
	@Operation(description = "Create a new Series", tags = "GLOBAL")
	public Series post(final Series jsonRequest) throws Exception {
		return DataAccess.insert(jsonRequest);
	}

	@PATCH
	@Path("{id}")
	@RolesAllowed("ADMIN")
	@Consumes(MediaType.APPLICATION_JSON)
	@Operation(description = "Modify a specific Series", tags = "GLOBAL")
	public Series patch(@PathParam("id") final Long id, @AsyncType(Series.class) final String jsonRequest) throws Exception {
		DataAccess.updateWithJson(Series.class, id, jsonRequest);
		return DataAccess.get(Series.class, id);
	}

	@DELETE
	@Path("{id}")
	@RolesAllowed("ADMIN")
	@Operation(description = "Remove a specific Series", tags = "GLOBAL")
	public void remove(@PathParam("id") final Long id) throws Exception {
		DataAccess.delete(Series.class, id);
	}

	@POST
	@Path("{id}/cover")
	@RolesAllowed("ADMIN")
	@Consumes({ MediaType.MULTIPART_FORM_DATA })
	@Operation(description = "Upload a new season cover Series", tags = "GLOBAL")
	@TypeScriptProgress
	public Series uploadCover(@PathParam("id") final Long id, @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData)
			throws Exception {
		try (DBAccess dbIo = DBAccess.createInterface()) {
			DataTools.uploadCover(dbIo, Series.class, id, fileInputStream, fileMetaData);
			return dbIo.get(Series.class, id);
		}
	}

	@DELETE
	@Path("{id}/cover/{coverId}")
	@RolesAllowed("ADMIN")
	@Operation(description = "Remove a specific Series of a season", tags = "GLOBAL")
	public Series removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception {
		try (DBAccess dbIo = DBAccess.createInterface()) {
			AddOnDataJson.removeLink(dbIo, Series.class, "id", id, "covers", coverId);
			return dbIo.get(Series.class, id);
		}
	}

	public static Series getOrCreate(final String name, final Long typeId) {
		try {
			Series out = DataAccess.getWhere(Series.class, new Condition(new QueryAnd(new QueryCondition("name", "=", name), new QueryCondition("parentId", "=", typeId))));
			if (out == null) {
				out = new Series();
				out.name = name;
				out.parentId = typeId;
				out = DataAccess.insert(out);
			}
			return out;
		} catch (final Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

}
