using SharedKernel.Extensions;
using SharedKernel.Helpers;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace Admin.Pages.Forum.Board.List;

public class IndexModel(IMediator mediator) : PageModel
{
    [BindProperty(SupportsGet = true)]
    public QueryParams Query { get; set; } = new();

    public sealed class QueryParams
    {
        [Range(1, int.MaxValue)]
        [DisplayName("페이지 번호")]
        public int PageNum { get; set; } = 1;

        [Range(1, 100)]
        [DisplayName("페이지 목록 수")]
        public ushort PerPage { get; set; } = 10;

        [DisplayName("게시판 분류")]
        public int? BoardGroupID { get; set; }

        [DisplayName("검색어")]
        public string? Keyword { get; set; }
    }

    public int Total { get; set; }

    public List<(int ID, string Name)> BoardGroups { get; set; } = [];

    public List<(
        int Num,
        int ID,
        int BoardGroupID,
        string BoardGroupName,
        string Code,
        string Name,
        short Order,
        bool IsSearch,
        bool IsActive,
        int Posts,
        int Comments,
        string? UpdatedAt,
        string CreatedAt,
        string EditURL,
        List<SelectListItem> SelectBoardGroup
    )> Data { get; set; } = [];

    public Pagination? Pagination { get; set; }

    public async Task OnGetAsync(CancellationToken ct)
    {
        if (!ModelState.IsValid)
        {
            return;
        }

        var groups = await mediator.Send(new GetBoardGroups.Query(), ct);
        BoardGroups = [..groups.List.Select(c => (c.ID, c.Name))];

        var selectItems = groups.List.Select(c => new SelectListItem
        {
            Value = c.ID.ToString(),
            Text = c.Name
        }).ToList();

        var result = await mediator.Send(new SearchBoards.Query(Query.BoardGroupID, Query.Keyword, Query.PageNum, Query.PerPage), ct);

        Total = result.Total;
        Data = [..result.List.Select(c => (
            c.Num,
            c.ID,
            c.BoardGroupID,
            c.BoardGroupName,
            c.Code,
            c.Name,
            c.Order,
            c.IsSearch,
            c.IsActive,
            c.Posts,
            c.Comments,
            c.UpdatedAt.GetDateAt() ?? "-",
            c.CreatedAt.GetDateAt(),
            EditURL: $"/Forum/Board/List/Edit/{c.ID}{Request.QueryString}",
            SelectBoardGroup: selectItems.Select(s => new SelectListItem
            {
                Value = s.Value,
                Text = s.Text,
                Selected = s.Value == c.BoardGroupID.ToString()
            }).ToList()
        ))];

        Pagination = new Pagination(result.Total, Query.PageNum, Query.PerPage);
    }

    public sealed class UpdateRequest
    {
        public int ID { get; set; }
        public int BoardGroupID { get; set; }
        public string Code { get; set; } = "";
        public string Name { get; set; } = "";
        public short Order { get; set; }
        public bool IsSearch { get; set; }
        public bool IsActive { get; set; }
    }

    public async Task<IActionResult> OnPostUpdateAsync(int[] ids, Dictionary<int, UpdateRequest> request, CancellationToken ct)
    {
        try
        {
            int count = 0;
            foreach (var id in ids)
            {
                if (request.TryGetValue(id, out var item))
                {
                    await mediator.Send(new UpdateBoard.Command(
                        id, item.BoardGroupID, item.Code, item.Name, item.Order, item.IsSearch, item.IsActive
                    ), ct);

                    count++;
                }
            }
            TempData["SuccessMessage"] = $"{count}건이 수정되었습니다.";
        }
        catch (Exception e)
        {
            TempData["ErrorMessages"] = e.Message;
        }

        return RedirectToPage("/Forum/Board/List/Index", Query);
    }

    public async Task<IActionResult> OnPostDeleteAsync(int[] ids, CancellationToken ct)
    {
        try
        {
            await mediator.Send(new DeleteBoard.Command(ids), ct);

            TempData["SuccessMessage"] = $"{ids.Length}건이 삭제되었습니다.";
        }
        catch (Exception e)
        {
            TempData["ErrorMessages"] = e.Message;
        }

        return RedirectToPage("/Forum/Board/List/Index", Query);
    }
}