using Application.Abstractions.Data;
using Application.Abstractions.Messaging;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace Admin.Pages.Channel.List
{
    public class WriteModel(IMediator mediator, IAppDbContext db) : PageModel
    {
        public string QueryString { get; private set; } = "";

        [BindProperty]
        public InputModel Input { get; set; } = new();

        public sealed class InputModel
        {
            [DisplayName("회원 ID")]
            [Required(ErrorMessage = "{0}은 필수입니다.")]
            public int MemberID { get; set; }

            [DisplayName("SID")]
            [Required(ErrorMessage = "{0}은 필수입니다.")]
            [StringLength(24, MinimumLength = 24, ErrorMessage = "{0}은 {1}자여야 합니다.")]
            public string SID { get; set; } = default!;

            [DisplayName("이름")]
            [Required(ErrorMessage = "{0}은 필수입니다.")]
            [StringLength(200, ErrorMessage = "{0}은 {1}자 이내로 입력하세요.")]
            public string Name { get; set; } = default!;

            [DisplayName("핸들")]
            [StringLength(30, ErrorMessage = "{0}은 {1}자 이내로 입력하세요.")]
            public string? Handle { get; set; }

            [DisplayName("YouTube 주소")]
            [Required(ErrorMessage = "{0}은 필수입니다.")]
            [StringLength(255, ErrorMessage = "{0}은 {1}자 이내로 입력하세요.")]
            public string YouTubeUrl { get; set; } = default!;

            [DisplayName("수수료(%)")]
            [Range(0, 100, ErrorMessage = "{0}은 {1}~{2} 사이여야 합니다.")]
            public decimal PlatformFeeRate { get; set; } = 0;

            [DisplayName("인증 여부")]
            public bool IsVerified { get; set; } = false;

            [DisplayName("사용 여부")]
            public bool IsActive { get; set; } = false;
        }

        public Task OnGetAsync(CancellationToken _)
        {
            QueryString = HttpContext.Request.QueryString.HasValue ? HttpContext.Request.QueryString.Value!.TrimStart('?') : "";

            return Task.CompletedTask;
        }

        public async Task<IActionResult> OnGetSearchMemberAsync(string keyword, CancellationToken ct)
        {
            if (string.IsNullOrWhiteSpace(keyword) || keyword.Trim().Length < 1)
            {
                return new JsonResult(Array.Empty<object>());
            }

            var kw = keyword.Trim();

            var isNumeric = int.TryParse(kw, out var numericId);

            var list = await db.Member
                .AsNoTracking()
                .Where(x =>
                    (isNumeric && x.ID == numericId) ||
                    x.SID.Contains(kw) ||
                    x.Email.Contains(kw) ||
                    (x.Name != null && x.Name.Contains(kw))
                )
                .OrderByDescending(x => x.ID)
                .Take(10)
                .Select(x => new
                {
                    id = x.ID,
                    email = x.Email,
                    name = x.Name,
                    sid = x.SID
                })
                .ToListAsync(ct);

            return new JsonResult(list);
        }

        public async Task<IActionResult> OnPostAsync(CancellationToken ct)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    throw new Exception("유효성 검사에 실패했습니다.");
                }

                await mediator.Send(new CreateChannel.Command(
                    Input.MemberID,
                    Input.SID,
                    Input.Name,
                    Input.Handle,
                    Input.YouTubeUrl,
                    Input.PlatformFeeRate,
                    Input.IsVerified,
                    Input.IsActive
                ), ct);

                TempData["SuccessMessage"] = "채널이 등록되었습니다.";

                return RedirectToPage("/Channel/List/Index");
            }
            catch (Exception e)
            {
                TempData["ErrorMessages"] = e.Message;

                return Page();
            }
        }
    }
}