package dev.lions.unionflow.server.resource;

import dev.lions.unionflow.server.service.BudgetService;
import dev.lions.unionflow.server.common.ErrorResponse;
import dev.lions.unionflow.server.api.dto.finance_workflow.request.CreateBudgetRequest;
import dev.lions.unionflow.server.api.dto.finance_workflow.response.BudgetResponse;
import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.jboss.logging.Logger;

import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * Resource REST pour la gestion des budgets
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2026-03-13
 */
@Path("/api/finance/budgets")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Finance - Budgets", description = "Gestion des budgets organisationnels")
public class BudgetResource {

    private static final Logger LOG = Logger.getLogger(BudgetResource.class);

    @Inject
    BudgetService budgetService;

    @GET
    @RolesAllowed({"ADMIN_ORGANISATION", "SUPER_ADMIN"})
    @Operation(summary = "Récupère les budgets",
               description = "Liste tous les budgets d'une organisation avec filtres optionnels")
    public Response getBudgets(
            @QueryParam("organizationId") UUID organizationId,
            @QueryParam("status") String status,
            @QueryParam("year") Integer year) {
        LOG.infof("GET /api/finance/budgets?organizationId=%s&status=%s&year=%s",
            organizationId, status, year);

        try {
            List<BudgetResponse> budgets = budgetService.getBudgets(organizationId, status, year);
            return Response.ok(budgets).build();
        } catch (BadRequestException e) {
            return Response.status(Response.Status.BAD_REQUEST)
                .entity(ErrorResponse.of(e.getMessage()))
                .build();
        } catch (Exception e) {
            LOG.error("Erreur lors de la récupération des budgets", e);
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                .entity(ErrorResponse.of(e.getMessage()))
                .build();
        }
    }

    @GET
    @Path("/{budgetId}")
    @RolesAllowed({"ADMIN_ORGANISATION", "SUPER_ADMIN"})
    @Operation(summary = "Récupère un budget par ID",
               description = "Retourne les détails complets d'un budget")
    public Response getBudgetById(@PathParam("budgetId") UUID budgetId) {
        LOG.infof("GET /api/finance/budgets/%s", budgetId);

        try {
            BudgetResponse budget = budgetService.getBudgetById(budgetId);
            return Response.ok(budget).build();
        } catch (NotFoundException e) {
            return Response.status(Response.Status.NOT_FOUND)
                .entity(ErrorResponse.of(e.getMessage()))
                .build();
        } catch (Exception e) {
            LOG.error("Erreur lors de la récupération du budget", e);
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                .entity(ErrorResponse.of(e.getMessage()))
                .build();
        }
    }

    @POST
    @RolesAllowed({"ADMIN_ORGANISATION", "SUPER_ADMIN"})
    @Operation(summary = "Crée un nouveau budget",
               description = "Crée un budget avec ses lignes budgétaires")
    public Response createBudget(@Valid CreateBudgetRequest request) {
        LOG.infof("POST /api/finance/budgets - Creating budget: %s", request.getName());

        try {
            BudgetResponse budget = budgetService.createBudget(request);
            return Response.status(Response.Status.CREATED)
                .entity(budget)
                .build();
        } catch (NotFoundException e) {
            return Response.status(Response.Status.NOT_FOUND)
                .entity(ErrorResponse.of(e.getMessage()))
                .build();
        } catch (BadRequestException e) {
            return Response.status(Response.Status.BAD_REQUEST)
                .entity(ErrorResponse.of(e.getMessage()))
                .build();
        } catch (Exception e) {
            LOG.error("Erreur lors de la création du budget", e);
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                .entity(ErrorResponse.of(e.getMessage()))
                .build();
        }
    }

    @GET
    @Path("/{budgetId}/tracking")
    @RolesAllowed({"ADMIN_ORGANISATION", "SUPER_ADMIN"})
    @Operation(summary = "Récupère le suivi budgétaire",
               description = "Retourne les statistiques de suivi et réalisation du budget")
    public Response getBudgetTracking(@PathParam("budgetId") UUID budgetId) {
        LOG.infof("GET /api/finance/budgets/%s/tracking", budgetId);

        try {
            Map<String, Object> tracking = budgetService.getBudgetTracking(budgetId);
            return Response.ok(tracking).build();
        } catch (NotFoundException e) {
            return Response.status(Response.Status.NOT_FOUND)
                .entity(ErrorResponse.of(e.getMessage()))
                .build();
        } catch (Exception e) {
            LOG.error("Erreur lors de la récupération du suivi budgétaire", e);
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                .entity(ErrorResponse.of(e.getMessage()))
                .build();
        }
    }

    @PUT
    @Path("/{budgetId}")
    @RolesAllowed({"ADMIN_ORGANISATION", "SUPER_ADMIN"})
    @Operation(summary = "Met à jour un budget",
               description = "Modifie un budget existant (nom, description, lignes, statut)")
    public Response updateBudget(
            @PathParam("budgetId") UUID budgetId,
            Map<String, Object> updates) {
        LOG.infof("PUT /api/finance/budgets/%s", budgetId);

        try {
            BudgetResponse budget = budgetService.updateBudget(budgetId, updates);
            return Response.ok(budget).build();
        } catch (NotFoundException e) {
            return Response.status(Response.Status.NOT_FOUND)
                .entity(ErrorResponse.of(e.getMessage()))
                .build();
        } catch (BadRequestException e) {
            return Response.status(Response.Status.BAD_REQUEST)
                .entity(ErrorResponse.of(e.getMessage()))
                .build();
        } catch (Exception e) {
            LOG.error("Erreur lors de la mise à jour du budget", e);
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                .entity(ErrorResponse.of(e.getMessage()))
                .build();
        }
    }

    @DELETE
    @Path("/{budgetId}")
    @RolesAllowed({"ADMIN_ORGANISATION", "SUPER_ADMIN"})
    @Operation(summary = "Supprime un budget",
               description = "Supprime logiquement un budget (soft delete)")
    public Response deleteBudget(@PathParam("budgetId") UUID budgetId) {
        LOG.infof("DELETE /api/finance/budgets/%s", budgetId);

        try {
            budgetService.deleteBudget(budgetId);
            return Response.noContent().build();
        } catch (NotFoundException e) {
            return Response.status(Response.Status.NOT_FOUND)
                .entity(ErrorResponse.of(e.getMessage()))
                .build();
        } catch (Exception e) {
            LOG.error("Erreur lors de la suppression du budget", e);
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                .entity(ErrorResponse.of(e.getMessage()))
                .build();
        }
    }

}

