using Application.Interfaces{{ GroupNamespace }};
using Application.DTOs{{ GroupNamespace }}.{{ TableNamePascal }};
using Core.Entities{{ GroupNamespace }};
using Core.Common;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using WebApi.DTOs{{ GroupNamespace }};
using WebApi.DTOs.Common;

namespace WebApi.Controllers{{ GroupNamespace }}
{
    /// <summary>
    /// {{ TableNamePascal }} management endpoints
    /// </summary>
    [ApiController]
    [Route("api/{% if Group != 'General' %}{{ Group }}/{% endif %}[controller]")]
    [Produces("application/json")]
    public class {{ TableNamePascal }}Controller : ControllerBase
    {
        private readonly I{{ TableNamePascal }}Service _service;

        /// <summary>
        /// Initializes a new instance of the {{ TableNamePascal }}Controller
        /// </summary>
        public {{ TableNamePascal }}Controller(I{{ TableNamePascal }}Service service)
        {
            _service = service ?? throw new ArgumentNullException(nameof(service));
        }

        /// <summary>
        /// Get {{ TableNamePascal }} by ID
        /// </summary>
        /// <param name="id">The {{ TableNamePascal }} ID</param>
        /// <returns>The {{ TableNamePascal }} entity</returns>
        /// <response code="200">Returns the {{ TableNamePascal }} entity</response>
        /// <response code="404">{{ TableNamePascal }} not found</response>
        [HttpGet("{id}")]
        [ProducesResponseType(typeof({{ TableNamePascal }}), 200)]
        [ProducesResponseType(400)]
        [ProducesResponseType(404)]
        public async Task<IActionResult> GetById({{ PrimaryKey.CSharpType }} id)
        {
            var result = await _service.GetByIdAsync(id);
            
            if (result.IsFailure)
            {
                return result.Error!.Type switch
                {
                    ErrorType.Validation => BadRequest(result.Error.Message),
                    ErrorType.NotFound => NotFound(result.Error.Message),
                    _ => BadRequest(result.Error.Message)
                };
            }
            
            return Ok(result.Value);
        }

        /// <summary>
        /// Get all {{ TableNamePascal }} entities
        /// </summary>
        /// <returns>List of {{ TableNamePascal }} entities</returns>
        /// <response code="200">Returns the list of {{ TableNamePascal }} entities</response>
        [HttpGet]
        [ProducesResponseType(typeof(IEnumerable<{{ TableNamePascal }}>), 200)]
        public async Task<IActionResult> GetAll()
        {
            var result = await _service.GetAllAsync();
            
            if (result.IsFailure)
            {
                return result.Error!.Type switch
                {
                    ErrorType.Internal => StatusCode(500, result.Error.Message),
                    _ => BadRequest(result.Error.Message)
                };
            }
            
            return Ok(result.Value);
        }

        /// <summary>
        /// Get paginated {{ TableNamePascal }} entities with filtering and sorting
        /// </summary>
        /// <param name="request">Pagination and filter parameters</param>
        /// <returns>Paginated list of {{ TableNamePascal }} entities</returns>
        /// <response code="200">Returns the paginated list of {{ TableNamePascal }} entities</response>
        [HttpGet("paged")]
        [ProducesResponseType(typeof(PagedResponse<{{ TableNamePascal }}>), 200)]
        public async Task<IActionResult> GetPaged([FromQuery] {{ TableNamePascal }}FilterRequest request)
        {
            var result = await _service.GetPagedAsync(
                request.PageNumber,
                request.PageSize,
                request.SearchTerm,
                request.SortBy,
                request.SortDescending,
                request.GetFilters());
            
            if (result.IsFailure)
            {
                return result.Error!.Type switch
                {
                    ErrorType.Validation => BadRequest(result.Error.Message),
                    ErrorType.Internal => StatusCode(500, result.Error.Message),
                    _ => BadRequest(result.Error.Message)
                };
            }
            
            var (items, totalCount) = result.Value;
            var response = new PagedResponse<{{ TableNamePascal }}>(
                items,
                totalCount,
                request.PageNumber,
                request.PageSize);
            
            return Ok(response);
        }

        /// <summary>
        /// Create a new {{ TableNamePascal }}
        /// </summary>
        /// <param name="dto">The {{ TableNamePascal }} to create</param>
        /// <returns>The created {{ TableNamePascal }}</returns>
        /// <response code="201">{{ TableNamePascal }} created successfully</response>
        /// <response code="400">Invalid input</response>
        [HttpPost]
        [ProducesResponseType(typeof({{ TableNamePascal }}), 201)]
        [ProducesResponseType(400)]
        public async Task<IActionResult> Create([FromBody] Create{{ TableNamePascal }}Dto dto)
        {
            if (!ModelState.IsValid)
                return BadRequest(ModelState);

            var result = await _service.CreateAsync(dto);
            
            if (result.IsFailure)
            {
                return result.Error!.Type switch
                {
                    ErrorType.Validation => BadRequest(result.Error.Message),
                    ErrorType.Conflict => Conflict(result.Error.Message),
                    ErrorType.Internal => StatusCode(500, result.Error.Message),
                    _ => BadRequest(result.Error.Message)
                };
            }

            return CreatedAtAction(nameof(GetById), new { id = result.Value!.{{ PrimaryKey.NamePascal }} }, result.Value);
        }

        /// <summary>
        /// Update an existing {{ TableNamePascal }}
        /// </summary>
        /// <param name="id">The {{ TableNamePascal }} ID</param>
        /// <param name="dto">The updated {{ TableNamePascal }} data</param>
        /// <returns>No content</returns>
        /// <response code="204">{{ TableNamePascal }} updated successfully</response>
        /// <response code="400">Invalid input</response>
        /// <response code="404">{{ TableNamePascal }} not found</response>
        [HttpPut("{id}")]
        [ProducesResponseType(204)]
        [ProducesResponseType(400)]
        [ProducesResponseType(404)]
        public async Task<IActionResult> Update({{ PrimaryKey.CSharpType }} id, [FromBody] Update{{ TableNamePascal }}Dto dto)
        {
            if (!ModelState.IsValid)
                return BadRequest(ModelState);

            var result = await _service.UpdateAsync(id, dto);
            
            if (result.IsFailure)
            {
                return result.Error!.Type switch
                {
                    ErrorType.Validation => BadRequest(result.Error.Message),
                    ErrorType.NotFound => NotFound(result.Error.Message),
                    ErrorType.Conflict => Conflict(result.Error.Message),
                    ErrorType.Internal => StatusCode(500, result.Error.Message),
                    _ => BadRequest(result.Error.Message)
                };
            }

            return NoContent();
        }

        /// <summary>
        /// Delete a {{ TableNamePascal }}
        /// </summary>
        /// <param name="id">The {{ TableNamePascal }} ID to delete</param>
        /// <returns>No content</returns>
        /// <response code="204">{{ TableNamePascal }} deleted successfully</response>
        /// <response code="404">{{ TableNamePascal }} not found</response>
        [HttpDelete("{id}")]
        [ProducesResponseType(204)]
        [ProducesResponseType(400)]
        [ProducesResponseType(404)]
        public async Task<IActionResult> Delete({{ PrimaryKey.CSharpType }} id)
        {
            var result = await _service.DeleteAsync(id);
            
            if (result.IsFailure)
            {
                return result.Error!.Type switch
                {
                    ErrorType.Validation => BadRequest(result.Error.Message),
                    ErrorType.NotFound => NotFound(result.Error.Message),
                    ErrorType.Conflict => Conflict(result.Error.Message),
                    ErrorType.Internal => StatusCode(500, result.Error.Message),
                    _ => BadRequest(result.Error.Message)
                };
            }

            return NoContent();
        }
    }
}