// EN: Shops Controller for shop management.
// VI: Controller Shops để quản lý shop.

using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MerchantService.API.Application.Commands.Shops;
using MerchantService.API.Application.Queries.Shops;

namespace MerchantService.API.Controllers;

/// <summary>
/// EN: Controller for shop management.
/// VI: Controller để quản lý shop.
/// </summary>
[ApiController]
[Route("api/v1/shops")]
[Authorize]
public class ShopsController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly ILogger<ShopsController> _logger;

    public ShopsController(IMediator mediator, ILogger<ShopsController> logger)
    {
        _mediator = mediator;
        _logger = logger;
    }

    /// <summary>
    /// EN: Get current merchant's shops.
    /// VI: Lấy danh sách shops của merchant hiện tại.
    /// </summary>
    [HttpGet]
    [ProducesResponseType(typeof(IReadOnlyList<ShopDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetMyShops()
    {
        var result = await _mediator.Send(new GetMyShopsQuery());
        return Ok(result);
    }

    /// <summary>
    /// EN: Get shop by ID.
    /// VI: Lấy shop theo ID.
    /// </summary>
    [HttpGet("{shopId:guid}")]
    [AllowAnonymous]
    [ProducesResponseType(typeof(ShopDetailDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetById(Guid shopId)
    {
        var result = await _mediator.Send(new GetShopByIdQuery(shopId));
        if (result == null)
        {
            return NotFound(new { message = "Shop not found" });
        }
        return Ok(result);
    }

    /// <summary>
    /// EN: Get shop by slug.
    /// VI: Lấy shop theo slug.
    /// </summary>
    [HttpGet("slug/{slug}")]
    [AllowAnonymous]
    [ProducesResponseType(typeof(ShopDetailDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetBySlug(string slug)
    {
        var result = await _mediator.Send(new GetShopBySlugQuery(slug));
        if (result == null)
        {
            return NotFound(new { message = "Shop not found" });
        }
        return Ok(result);
    }

    /// <summary>
    /// EN: Create a new shop.
    /// VI: Tạo shop mới.
    /// </summary>
    [HttpPost]
    [ProducesResponseType(typeof(CreateShopResult), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status409Conflict)]
    public async Task<IActionResult> Create([FromBody] CreateShopCommand command)
    {
        try
        {
            var result = await _mediator.Send(command);
            _logger.LogInformation("Shop created: {ShopId}", result.ShopId);
            return CreatedAtAction(nameof(GetById), new { shopId = result.ShopId }, result);
        }
        catch (Domain.Exceptions.DomainException ex) when (ex.Message.Contains("already taken"))
        {
            return Conflict(new { message = ex.Message });
        }
    }

    /// <summary>
    /// EN: Update an existing shop.
    /// VI: Cập nhật shop.
    /// </summary>
    [HttpPut("{shopId:guid}")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> Update(Guid shopId, [FromBody] UpdateShopRequest request)
    {
        try
        {
            var command = new UpdateShopCommand
            {
                ShopId = shopId,
                Name = request.Name,
                Description = request.Description,
                Phone = request.Phone,
                Email = request.Email,
                Website = request.Website,
                LogoUrl = request.LogoUrl,
                CoverImageUrl = request.CoverImageUrl
            };
            await _mediator.Send(command);
            _logger.LogInformation("Shop updated: {ShopId}", shopId);
            return Ok(new { message = "Shop updated successfully" });
        }
        catch (Domain.Exceptions.DomainException ex) when (ex.Message.Contains("not found"))
        {
            return NotFound(new { message = ex.Message });
        }
        catch (Domain.Exceptions.DomainException ex) when (ex.Message.Contains("permission"))
        {
            return StatusCode(StatusCodes.Status403Forbidden, new { message = ex.Message });
        }
    }

    /// <summary>
    /// EN: Publish a shop (make visible to customers).
    /// VI: Công khai shop (hiển thị với khách hàng).
    /// </summary>
    [HttpPost("{shopId:guid}/publish")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> Publish(Guid shopId)
    {
        await _mediator.Send(new PublishShopCommand(shopId));
        return Ok(new { message = "Shop published successfully" });
    }

    /// <summary>
    /// EN: Set shop as inactive.
    /// VI: Đặt shop thành không hoạt động.
    /// </summary>
    [HttpPost("{shopId:guid}/deactivate")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<IActionResult> Deactivate(Guid shopId)
    {
        await _mediator.Send(new SetShopInactiveCommand(shopId));
        return Ok(new { message = "Shop deactivated" });
    }

    /// <summary>
    /// EN: Close shop permanently.
    /// VI: Đóng cửa shop vĩnh viễn.
    /// </summary>
    [HttpPost("{shopId:guid}/close")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<IActionResult> Close(Guid shopId)
    {
        await _mediator.Send(new CloseShopCommand(shopId));
        return Ok(new { message = "Shop closed permanently" });
    }

    /// <summary>
    /// EN: Add a branch to a shop.
    /// VI: Thêm chi nhánh vào shop.
    /// </summary>
    [HttpPost("{shopId:guid}/branches")]
    [ProducesResponseType(typeof(AddShopBranchResult), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> AddBranch(Guid shopId, [FromBody] AddBranchRequest request)
    {
        var command = new AddShopBranchCommand
        {
            ShopId = shopId,
            Name = request.Name,
            Code = request.Code,
            Street = request.Street,
            Ward = request.Ward,
            District = request.District,
            City = request.City,
            Province = request.Province,
            Latitude = request.Latitude,
            Longitude = request.Longitude,
            Phone = request.Phone
        };
        
        var result = await _mediator.Send(command);
        return CreatedAtAction(nameof(GetById), new { shopId }, result);
    }

    /// <summary>
    /// EN: Get all branches of a shop.
    /// VI: Lấy tất cả chi nhánh của shop.
    /// </summary>
    [HttpGet("{shopId:guid}/branches")]
    [AllowAnonymous]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<IActionResult> GetBranches(Guid shopId)
    {
        var result = await _mediator.Send(new GetBranchesQuery(shopId));
        return Ok(result);
    }

    /// <summary>
    /// EN: Update a branch.
    /// VI: Cập nhật chi nhánh.
    /// </summary>
    [HttpPut("{shopId:guid}/branches/{branchId:guid}")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> UpdateBranch(Guid shopId, Guid branchId, [FromBody] UpdateBranchRequest request)
    {
        try
        {
            var command = new UpdateBranchCommand
            {
                ShopId = shopId,
                BranchId = branchId,
                Name = request.Name,
                Code = request.Code,
                Street = request.Street,
                Ward = request.Ward,
                District = request.District,
                City = request.City,
                Province = request.Province,
                Latitude = request.Latitude,
                Longitude = request.Longitude,
                Phone = request.Phone
            };
            await _mediator.Send(command);
            return Ok(new { message = "Branch updated successfully" });
        }
        catch (Domain.Exceptions.DomainException ex) when (ex.Message.Contains("not found"))
        {
            return NotFound(new { message = ex.Message });
        }
    }

    /// <summary>
    /// EN: Delete a branch.
    /// VI: Xóa chi nhánh.
    /// </summary>
    [HttpDelete("{shopId:guid}/branches/{branchId:guid}")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> DeleteBranch(Guid shopId, Guid branchId)
    {
        try
        {
            await _mediator.Send(new DeleteBranchCommand(shopId, branchId));
            return Ok(new { message = "Branch deleted successfully" });
        }
        catch (Domain.Exceptions.DomainException ex) when (ex.Message.Contains("not found"))
        {
            return NotFound(new { message = ex.Message });
        }
    }

    /// <summary>
    /// EN: Find shops with branches near a location.
    /// VI: Tìm shops có chi nhánh gần vị trí.
    /// </summary>
    [HttpGet("nearby")]
    [AllowAnonymous]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<IActionResult> GetNearbyShops(
        [FromQuery] double lat,
        [FromQuery] double lng,
        [FromQuery] double radius = 5.0,
        [FromQuery] int limit = 20)
    {
        var result = await _mediator.Send(new GetNearbyShopsQuery(lat, lng, radius, limit));
        return Ok(result);
    }
}

/// <summary>
/// EN: Request model for adding a branch.
/// VI: Model request để thêm chi nhánh.
/// </summary>
public record AddBranchRequest
{
    public string Name { get; init; } = null!;
    public string? Code { get; init; }
    public string Street { get; init; } = null!;
    public string? Ward { get; init; }
    public string District { get; init; } = null!;
    public string City { get; init; } = null!;
    public string? Province { get; init; }
    public double? Latitude { get; init; }
    public double? Longitude { get; init; }
    public string? Phone { get; init; }
}

/// <summary>
/// EN: Request model for updating a shop.
/// VI: Model request để cập nhật shop.
/// </summary>
public record UpdateShopRequest
{
    public string Name { get; init; } = null!;
    public string? Description { get; init; }
    public string? Phone { get; init; }
    public string? Email { get; init; }
    public string? Website { get; init; }
    public string? LogoUrl { get; init; }
    public string? CoverImageUrl { get; init; }
}

/// <summary>
/// EN: Request model for updating a branch.
/// VI: Model request để cập nhật chi nhánh.
/// </summary>
public record UpdateBranchRequest
{
    public string Name { get; init; } = null!;
    public string? Code { get; init; }
    public string Street { get; init; } = null!;
    public string? Ward { get; init; }
    public string District { get; init; } = null!;
    public string City { get; init; } = null!;
    public string? Province { get; init; }
    public double? Latitude { get; init; }
    public double? Longitude { get; init; }
    public string? Phone { get; init; }
}

