using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using PlotLine.Services;
using PlotLine.ViewModels;

namespace PlotLine.Controllers;

[Authorize]
public sealed class ProjectMetricsController(ISceneMetricTypeService metrics) : Controller
{
    public async Task<IActionResult> Index(int projectId)
    {
        var model = await metrics.GetAsync(projectId);
        return model is null ? NotFound() : View(model);
    }

    public async Task<IActionResult> Edit(int projectId, int id)
    {
        var model = await metrics.GetEditAsync(projectId, id);
        return model is null ? NotFound() : View(model);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Save(SceneMetricTypeEditViewModel model)
    {
        if (model.MinValue >= model.MaxValue)
        {
            ModelState.AddModelError(nameof(model.MaxValue), "Maximum value must be greater than minimum value.");
        }

        if (model.DefaultValue < model.MinValue || model.DefaultValue > model.MaxValue)
        {
            ModelState.AddModelError(nameof(model.DefaultValue), "Default value must sit inside the metric range.");
        }

        if (!ModelState.IsValid)
        {
            return model.MetricTypeID == 0
                ? RedirectToAction(nameof(Index), new { projectId = model.ProjectID })
                : View("Edit", model);
        }

        await metrics.SaveAsync(model);
        TempData["ProjectMetricMessage"] = model.MetricTypeID == 0 ? "Scene metric added." : "Scene metric updated.";
        return RedirectToAction(nameof(Index), new { projectId = model.ProjectID });
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> AddMissingDefaults(int projectId)
    {
        await metrics.AddMissingDefaultsAsync(projectId);
        TempData["ProjectMetricMessage"] = "Missing default scene metrics added.";
        return RedirectToAction(nameof(Index), new { projectId });
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> SetActive(int projectId, int id, bool isActive)
    {
        var updated = await metrics.SetActiveAsync(projectId, id, isActive);
        TempData["ProjectMetricMessage"] = updated
            ? (isActive ? "Metric reactivated." : "Metric deactivated.")
            : (isActive ? "Metric could not be reactivated." : "Metric could not be deactivated.");
        return RedirectToAction(nameof(Index), new { projectId });
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Move(int projectId, int id, string direction)
    {
        direction = string.Equals(direction, "Up", StringComparison.OrdinalIgnoreCase) ? "Up" : "Down";
        var moved = await metrics.MoveAsync(projectId, id, direction);
        TempData["ProjectMetricMessage"] = moved
            ? $"Metric moved {direction.ToLowerInvariant()}."
            : $"Metric could not be moved {direction.ToLowerInvariant()} because it is already at the edge of its group.";
        return RedirectToAction(nameof(Index), new { projectId });
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Remove(int projectId, int id)
    {
        var removed = await metrics.RemoveUnusedAsync(projectId, id);
        TempData["ProjectMetricMessage"] = removed
            ? "Unused metric removed."
            : "Metric cannot be removed because scene values exist or the metric is still active.";
        return RedirectToAction(nameof(Index), new { projectId });
    }
}
