using Managing.Application.Abstractions;
using Managing.Application.Abstractions.Services;
using Managing.Domain.Scenarios;
using Managing.Domain.Strategies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using static Managing.Common.Enums;

namespace Managing.Api.Controllers;

/// <summary>
/// Controller for managing scenarios and strategies within the application.
/// Provides endpoints for creating, retrieving, and deleting scenarios and strategies.
/// Requires authorization for access and produces JSON responses.
/// </summary>
[ApiController]
[Authorize]
[Route("[controller]")]
[Produces("application/json")]
public class ScenarioController : BaseController
{
    private readonly IScenarioService _scenarioService;

    /// <summary>
    /// Initializes a new instance of the <see cref="ScenarioController"/> class.
    /// </summary>
    /// <param name="scenarioService">The service for managing scenarios.</param>
    /// <param name="userService">The service for user-related operations.</param>
    public ScenarioController(
        IScenarioService scenarioService,
        IUserService userService) 
        : base(userService)
    {
        _scenarioService = scenarioService;
    }

    /// <summary>
    /// Retrieves all scenarios for the authenticated user.
    /// </summary>
    /// <returns>A list of scenarios.</returns>
    [HttpGet]
    public async Task<ActionResult<IEnumerable<Scenario>>> GetScenarios()
    {
        var user = await GetUser();
        return Ok(_scenarioService.GetScenariosByUser(user));
    }

    /// <summary>
    /// Creates a new scenario with the specified name and strategies for the authenticated user.
    /// </summary>
    /// <param name="name">The name of the scenario.</param>
    /// <param name="strategies">A list of strategy names to include in the scenario.</param>
    /// <returns>The created scenario.</returns>
    [HttpPost]
    public async Task<ActionResult<Scenario>> CreateScenario(string name, List<string> strategies, int? loopbackPeriod = null)
    {
        var user = await GetUser();
        return Ok(_scenarioService.CreateScenarioForUser(user, name, strategies, loopbackPeriod));
    }

    /// <summary>
    /// Deletes a scenario by name for the authenticated user.
    /// </summary>
    /// <param name="name">The name of the scenario to delete.</param>
    /// <returns>An ActionResult indicating the outcome of the operation.</returns>
    [HttpDelete]
    public async Task<ActionResult> DeleteScenario(string name)
    {
        var user = await GetUser();
        return Ok(_scenarioService.DeleteScenarioByUser(user, name));
    }

    // Update scenario
    [HttpPut]
    public async Task<ActionResult> UpdateScenario(string name, List<string> strategies, int? loopbackPeriod = null)
    {
        var user = await GetUser();
        return Ok(_scenarioService.UpdateScenarioByUser(user, name, strategies, loopbackPeriod));
    }

    /// <summary>
    /// Retrieves all strategies for the authenticated user.
    /// </summary>
    /// <returns>A list of strategies.</returns>
    [HttpGet]
    [Route("strategy")]
    public async Task<ActionResult<IEnumerable<Strategy>>> GetStrategies()
    {
        var user = await GetUser();
        return Ok(_scenarioService.GetStrategiesByUser(user));
    }

    /// <summary>
    /// Creates a new strategy with specified parameters for the authenticated user.
    /// </summary>
    /// <param name="strategyType">The type of the strategy.</param>
    /// <param name="name">The name of the strategy.</param>
    /// <param name="period">The period for the strategy (optional).</param>
    /// <param name="fastPeriods">The fast periods for the strategy (optional).</param>
    /// <param name="slowPeriods">The slow periods for the strategy (optional).</param>
    /// <param name="signalPeriods">The signal periods for the strategy (optional).</param>
    /// <param name="multiplier">The multiplier for the strategy (optional).</param>
    /// <param name="stochPeriods">The stochastic periods for the strategy (optional).</param>
    /// <param name="smoothPeriods">The smooth periods for the strategy (optional).</param>
    /// <param name="cyclePeriods">The cycle periods for the strategy (optional).</param>
    /// <returns>The created strategy.</returns>
    [HttpPost]
    [Route("strategy")]
    public async Task<ActionResult<Strategy>> CreateStrategy(
        StrategyType strategyType,
        string name,
        int? period = null,
        int? fastPeriods = null,
        int? slowPeriods = null,
        int? signalPeriods = null,
        double? multiplier = null,
        int? stochPeriods = null,
        int? smoothPeriods = null,
        int? cyclePeriods = null)
    {
        var user = await GetUser();
        return Ok(_scenarioService.CreateStrategyForUser(
            user,
            strategyType,
            name,
            period,
            fastPeriods,
            slowPeriods,
            signalPeriods,
            multiplier,
            stochPeriods,
            smoothPeriods,
            cyclePeriods));
    }

    /// <summary>
    /// Deletes a strategy by name for the authenticated user.
    /// </summary>
    /// <param name="name">The name of the strategy to delete.</param>
    /// <returns>An ActionResult indicating the outcome of the operation.</returns>
    [HttpDelete]
    [Route("strategy")]
    public async Task<ActionResult> DeleteStrategy(string name)
    {
        var user = await GetUser();
        return Ok(_scenarioService.DeleteStrategyByUser(user, name));
    }

    // Update strategy
    [HttpPut]
    [Route("strategy")]
    public async Task<ActionResult> UpdateStrategy(
        StrategyType strategyType,
        string name,
        int? period = null,
        int? fastPeriods = null,
        int? slowPeriods = null,
        int? signalPeriods = null,
        double? multiplier = null,
        int? stochPeriods = null,
        int? smoothPeriods = null,
        int? cyclePeriods = null)
    {
        var user = await GetUser();
        return Ok(_scenarioService.UpdateStrategyByUser(
            user,
            strategyType,
            name,
            period,
            fastPeriods,
            slowPeriods,
            signalPeriods,
            multiplier,
            stochPeriods,
            smoothPeriods,
            cyclePeriods));
    }
}