using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Domain.Entities.Members
{
    public class Channel
    {
        [ForeignKey(nameof(MemberID))]
        public virtual Member Member { get; private set; } = null!;

        [Key]
        public int ID { get; private set; }

        public int MemberID { get; private set; }

        public string SID { get; private set; } = default!;

        public string Name { get; private set; } = default!;

        public string? Handle { get; private set; }

        public string YouTubeUrl { get; private set; } = default!;

        public string? YouTubeChannelID { get; private set; }

        public string? Description { get; private set; }

        public string? ThumbnailUrl { get; private set; }

        public string? BannerUrl { get; private set; }

        public long SubscriberCount { get; private set; }

        public long VideoCount { get; private set; }

        public long ViewCount { get; private set; }

        public string? Email { get; private set; }

        public DateTime? YouTubePublishedAt { get; private set; }

        public decimal PlatformFeeRate { get; private set; } = 0;

        public bool IsVerified { get; private set; } = false;

        public bool IsActive { get; private set; } = true;

        public string WidgetToken { get; private set; } = GenerateWidgetToken();

        public DateTime? UpdatedAt { get; private set; }

        public DateTime CreatedAt { get; private set; } = DateTime.UtcNow;

        private Channel() { }

        private Channel(int memberID, string sid, string name, string youtubeUrl)
        {
            if (memberID <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(memberID));
            }

            if (string.IsNullOrWhiteSpace(sid))
            {
                throw new ArgumentException("SID is required.", nameof(sid));
            }

            if (sid.Length != 24)
            {
                throw new ArgumentOutOfRangeException(nameof(sid));
            }

            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ArgumentException("Name is required.", nameof(name));
            }

            if (name.Length > 200)
            {
                throw new ArgumentOutOfRangeException(nameof(name));
            }

            if (string.IsNullOrWhiteSpace(youtubeUrl))
            {
                throw new ArgumentException("YouTubeUrl is required.", nameof(youtubeUrl));
            }

            if (youtubeUrl.Length > 255)
            {
                throw new ArgumentOutOfRangeException(nameof(youtubeUrl));
            }

            MemberID = memberID;
            SID = sid;
            Name = name;
            YouTubeUrl = youtubeUrl;
        }

        public static Channel Create(int memberID, string sid, string name, string youtubeUrl)
        {
            return new(memberID, sid, name, youtubeUrl);
        }

        public void Update(string name, string? handle, string youtubeUrl, decimal platformFeeRate, bool isVerified, bool isActive)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ArgumentException("Name is required.", nameof(name));
            }

            if (name.Length > 200)
            {
                throw new ArgumentOutOfRangeException(nameof(name));
            }

            if (handle is not null && handle.Length > 30)
            {
                throw new ArgumentOutOfRangeException(nameof(handle));
            }

            if (string.IsNullOrWhiteSpace(youtubeUrl))
            {
                throw new ArgumentException("YouTubeUrl is required.", nameof(youtubeUrl));
            }

            if (youtubeUrl.Length > 255)
            {
                throw new ArgumentOutOfRangeException(nameof(youtubeUrl));
            }

            if (platformFeeRate < 0 || platformFeeRate > 100)
            {
                throw new ArgumentOutOfRangeException(nameof(platformFeeRate));
            }

            Name = name;
            Handle = handle;
            YouTubeUrl = youtubeUrl;
            PlatformFeeRate = platformFeeRate;
            IsVerified = isVerified;
            IsActive = isActive;
            UpdatedAt = DateTime.UtcNow;
        }

        public void UpdateYouTubeInfo(
            string youtubeChannelID,
            string name,
            string? handle,
            string? description,
            string? thumbnailUrl,
            string? bannerUrl,
            long subscriberCount,
            long videoCount,
            long viewCount,
            string? email,
            DateTime? youtubePublishedAt
        ) {
            YouTubeChannelID = youtubeChannelID;
            Name = name;
            Handle = handle;
            Description = description;
            ThumbnailUrl = thumbnailUrl;
            BannerUrl = bannerUrl;
            SubscriberCount = subscriberCount;
            VideoCount = videoCount;
            ViewCount = viewCount;
            Email = email;
            IsActive = true;
            YouTubePublishedAt = youtubePublishedAt;
            UpdatedAt = DateTime.UtcNow;
        }

        public void Deactivate()
        {
            IsActive = false;
            UpdatedAt = DateTime.UtcNow;
        }

        public void ResetWidgetToken()
        {
            WidgetToken = GenerateWidgetToken();
            UpdatedAt = DateTime.UtcNow;
        }

        private static string GenerateWidgetToken()
        {
            return Guid.NewGuid().ToString("N");
        }
    }
}