namespace Domain.Entities.Common
{
    public sealed class Config
    {
        public int ID { get; private set; }
        public DateTime LastUpdatedAt { get; private set; } = DateTime.UtcNow;
        public byte[] RowVersion { get; private set; } = [];
        public BasicConfig Basic { get; private set; } = new();
        public ImagesConfig Images { get; private set; } = new();
        public MetaConfig Meta { get; private set; } = new();
        public CompanyConfig Company { get; private set; } = new();
        public AccountConfig Account { get; private set; } = new();
        public EmailTemplateConfig EmailTemplate { get; private set; } = new();
        public ExternalApiConfig External { get; private set; } = new();
        public PaymentConfig Payment { get; private set; } = new();
        public CryptoConfig Crypto { get; private set; } = new();
        public AttendanceConfig Attendance { get; private set; } = new();
        public SignupRewardConfig SignupReward { get; private set; } = new();
        public RewardConfig Reward { get; private set; } = new();

        private Config() { }

        public static Config Create()
        {
            return new();
        }

        public void Update(
            BasicConfig basic,
            ImagesConfig images,
            MetaConfig meta,
            CompanyConfig company,
            AccountConfig account,
            EmailTemplateConfig emailTemplate,
            ExternalApiConfig external,
            PaymentConfig payment,
            CryptoConfig crypto
        ) {
            Basic = basic ?? throw new ArgumentNullException(nameof(basic));
            Images = images ?? throw new ArgumentNullException(nameof(images));
            Meta = meta ?? throw new ArgumentNullException(nameof(meta));
            Company = company ?? throw new ArgumentNullException(nameof(company));
            Account = account ?? throw new ArgumentNullException(nameof(account));
            EmailTemplate = emailTemplate ?? throw new ArgumentNullException(nameof(emailTemplate));
            External = external ?? throw new ArgumentNullException(nameof(external));
            Payment = payment ?? throw new ArgumentNullException(nameof(payment));
            Crypto = crypto ?? throw new ArgumentNullException(nameof(crypto));
            LastUpdatedAt = DateTime.UtcNow;
        }

        // 보상/출석/가입보상은 모듈러 Update — 기존 Update(9-param) 시그니처를 건드리지 않기 위해 분리.
        public void UpdateAttendance(AttendanceConfig attendance)
        {
            Attendance = attendance ?? throw new ArgumentNullException(nameof(attendance));
            LastUpdatedAt = DateTime.UtcNow;
        }

        public void UpdateSignupReward(SignupRewardConfig signupReward)
        {
            SignupReward = signupReward ?? throw new ArgumentNullException(nameof(signupReward));
            LastUpdatedAt = DateTime.UtcNow;
        }

        public void UpdateReward(RewardConfig reward)
        {
            Reward = reward ?? throw new ArgumentNullException(nameof(reward));
            LastUpdatedAt = DateTime.UtcNow;
        }
    }

    #region Owned Groups

    // ==================================================
    // 기본 정보 (Basic)
    // ==================================================
    public sealed class BasicConfig
    {
        public string? SiteName { get; set; }
        public string? SiteURL { get; set; }
        public string? RootID { get; set; }
        public string? FromEmail { get; set; }
        public string? FromName { get; set; }
        public string? SmtpServer { get; set; }
        public int? SmtpPort { get; set; }
        public bool SmtpEnableSSL { get; set; }
        public string? SmtpUsername { get; set; }
        public string? SmtpPassword { get; set; }
        public string? AdminWhiteIPList { get; set; }
        public string? FrontWhiteIPList { get; set; }
        public string? BlockAlertTitle { get; set; }
        public string? BlockAlertContent { get; set; }
        public bool IsMaintenance { get; set; } = false;
        public string? MaintenanceContent { get; set; }
    }

    // ==================================================
    // 기본 이미지 (Images)
    // ==================================================
    public sealed class ImagesConfig
    {
        public string? Favicon { get; set; }
        public string? LogoSquare { get; set; }
        public string? LogoHorizontal { get; set; }
        public string? OgDefault { get; set; }
        public string? TwitterImage { get; set; }
        public string? AppleTouchIcon { get; set; }
        public string? AppIcon_192 { get; set; }
        public string? AppIcon_512 { get; set; }
    }

    // ==================================================
    // 메타 태그 (Meta)
    // ==================================================
    public sealed class MetaConfig
    {
        public string? Keywords { get; set; }
        public string? Description { get; set; }
        public string? Author { get; set; }
        public string? Viewport { get; set; }
        public string? ApplicationName { get; set; }
        public string? Generator { get; set; }
        public string? Robots { get; set; }
        public string? Adds { get; set; }
    }

    // ==================================================
    // 회사 정보 (Company)
    // ==================================================
    public sealed class CompanyConfig
    {
        public string? Name { get; set; }
        public string? RegNo { get; set; }
        public string? Address { get; set; }
        public string? ZipCode { get; set; }
        public string? Owner { get; set; }
        public string? Tel { get; set; }
        public string? Fax { get; set; }
        public string? RetailSaleNo { get; set; }
        public string? AddedSaleNo { get; set; }
        public string? Hosting { get; set; }
        public string? AdminName { get; set; }
        public string? AdminEmail { get; set; }
        public string? SiteUrl { get; set; }
        public string? BankCode { get; set; }
        public string? BankOwner { get; set; }
        public string? BankNumber { get; set; }
    }

    // ==================================================
    // 회원가입 설정 (Account)
    // ==================================================
    public sealed class AccountConfig
    {
        // 회원 가입 시
        public bool IsRegisterBlock { get; set; } = false;
        public bool IsRegisterEmailAuth { get; set; } = false;
        public ushort? PasswordMinLength { get; set; }
        public ushort? PasswordUppercaseLength { get; set; }
        public ushort? PasswordNumbersLength { get; set; }
        public ushort? PasswordSpecialcharsLength { get; set; }
        public string? DeniedEmailList { get; set; }
        public string? DeniedNameList { get; set; }

        // 회원 수정 시
        public ushort? ChangeEmailDay { get; set; }
        public ushort? ChangeNameDay { get; set; }
        public ushort? ChangeSummaryDay { get; set; }
        public ushort? ChangeIntroDay { get; set; }
        public ushort? ChangePasswordDay { get; set; }

        // 로그인 시
        public bool IsLoginEmailVerifiedOnly { get; set; } = false;
        public ushort? MaxLoginTryCount { get; set; }
        public ushort? MaxLoginTryLimitSecond { get; set; }
    }

    // ==================================================
    // 알림 발송 양식 - 이메일 (EmailTemplate)
    // ==================================================
    public sealed class EmailTemplateConfig
    {
        public string? RegisterEmailFormTitle { get; set; }
        public string? RegisterEmailFormContent { get; set; }
        public string? RegistrationEmailFormTitle { get; set; }
        public string? RegistrationEmailFormContent { get; set; }
        public string? ResetPasswordEmailFormTitle { get; set; }
        public string? ResetPasswordEmailFormContent { get; set; }
        public string? ChangedPasswordEmailFormTitle { get; set; }
        public string? ChangedPasswordEmailFormContent { get; set; }
        public string? WithdrawEmailFormTitle { get; set; }
        public string? WithdrawEmailFormContent { get; set; }
        public string? EmailVerifyFormTitle { get; set; }
        public string? EmailVerifyFormContent { get; set; }
        public string? ChangedEmailFormTitle { get; set; }
        public string? ChangedEmailFormContent { get; set; }
    }

    // ==================================================
    // 외부 API 설정 (External)
    // ==================================================
    public sealed class ExternalApiConfig
    {
        /** YouTube **/
        public string? YouTubeApiKeyEnc { get; set; }
        public string? YouTubeApiName { get; set; }

        /** 구글 **/
        public string? GoogleClientId { get; set; }
        public string? GoogleClientSecretEnc { get; set; }
        public string? GoogleAppId { get; set; }

        /** 다날 페이 **/
        //[Comment("Danal 결제 환경")]
        //public string? DanalPayMode { get; set; }

        //[Comment("Danal Test CPID")]
        //public string? DanalTestCpid { get; set; }

        //[Comment("Danal Test Client Key (암호화 저장 권장)")]
        //public string? DanalTestClientKeyEnc { get; set; }

        //[Comment("Danal Test Secret Key (암호화 저장 권장)")]
        //public string? DanalTestSecretKeyEnc { get; set; }

        //[Comment("Danal Live CPID")]
        //public string? DanalLiveCpid { get; set; }

        //[Comment("Danal Live Client Key (암호화 저장 권장)")]
        //public string? DanalLiveClientKeyEnc { get; set; }

        //[Comment("Danal Live Secret Key (암호화 저장 권장)")]
        //public string? DanalLiveSecretKeyEnc { get; set; }
    }

    // ==================================================
    // 결제 설정 (Payment)
    // ==================================================
    public sealed class PaymentConfig
    {
        /** 다날 페이 **/
        //[Range(0, 100)]
        //[Comment("다날 신용카드 수수료(%)")]
        //public decimal? DanalCardFeeRate { get; set; }

        //[Range(0, 999_999_999)]
        //[Comment("다날 신용카드 수수료(원)")]
        //public decimal? DanalCardFeeAmount { get; set; }

        //[Range(0, 100)]
        //[Comment("다날 계좌이체 수수료(%)")]
        //public decimal? DanalTransferFeeRate { get; set; }

        //[Range(0, 999_999_999)]
        //[Comment("다날 계좌이체 수수료(원)")]
        //public decimal? DanalTransferFeeAmount { get; set; }

        //[Range(0, 100)]
        //[Comment("다날 가상계좌 수수료(%)")]
        //public decimal? DanalVbankFeeRate { get; set; }

        //[Range(0, 999_999_999)]
        //[Comment("다날 가상계좌 수수료(원)")]
        //public decimal? DanalVbankFeeAmount { get; set; }

        //[Range(0, 100)]
        //[Comment("다날 간편결제 수수료(%)")]
        //public decimal? DanalSimpleFeeRate { get; set; }

        //[Range(0, 999_999_999)]
        //[Comment("다날 간편결제 수수료(원)")]
        //public decimal? DanalSimpleFeeAmount { get; set; }
    }

    // ==================================================
    // 코인/시세 설정 (Crypto)
    // ==================================================
    public sealed class CryptoConfig
    {
        public int TickerRefreshSeconds { get; set; } = 5;
        public decimal SurgeThreshold { get; set; } = 5.0m;
        public decimal PlungeThreshold { get; set; } = -5.0m;
        public int MainPageCoinCount { get; set; } = 10;
    }

    // ==================================================
    // 출석 설정 (Attendance)
    // ==================================================
    public sealed class AttendanceConfig
    {
        /// <summary>출석 기능 활성화</summary>
        public bool IsEnabled { get; set; } = false;
        /// <summary>기본 경험치</summary>
        public int BaseExp { get; set; } = 0;
        /// <summary>기본 포인트</summary>
        public int BasePoint { get; set; } = 0;
        /// <summary>연속 출석 가중치 사용</summary>
        public bool UseStreakBonus { get; set; } = false;
        /// <summary>연속 출석 1일당 추가 경험치</summary>
        public int StreakBonusPerDay { get; set; } = 0;
        /// <summary>연속 출석 1일당 추가 포인트</summary>
        public int StreakBonusPointPerDay { get; set; } = 0;
        /// <summary>가중치 최대 적용 일수</summary>
        public int StreakBonusMaxDays { get; set; } = 0;
        /// <summary>순위 보상 사용</summary>
        public bool UseRankBonus { get; set; } = false;
        /// <summary>순위별 보상 설정 (JSON) [{"rank":1,"exp":100,"point":50},...]</summary>
        public string? RankBonusConfig { get; set; }
    }

    // ==================================================
    // 가입 축하 보상 설정 (SignupReward)
    // 신규 회원 최초 가입 시 1회 지급. 멱등: WalletTransaction RefID "signup:{memberID}"
    // ==================================================
    public sealed class SignupRewardConfig
    {
        /// <summary>가입 축하 보상 활성화</summary>
        public bool Enabled { get; set; } = false;
        /// <summary>지급 코인(무상, Airdrop 파티션)</summary>
        public int CoinAmount { get; set; } = 0;
        /// <summary>지급 캐시(유상 취급, Adjusted 파티션). 기본 0</summary>
        public int CashAmount { get; set; } = 0;
        /// <summary>지급 경험치(XP)</summary>
        public int ExpAmount { get; set; } = 0;
    }

    // ==================================================
    // 보상 엔진 설정 (Reward) — RewardService 가 단일 지급 관문에서 참조하는 XP/토큰 수치 + 액션별 일일 캡.
    // 캡 필드는 0 = 무제한. XP=경험치(MemberStats.Exp), Point=토큰(Wallet Reward 파티션).
    // (채팅/응원(Cheer) 보상은 미포팅 — 게시글/댓글/추천만)
    // ==================================================
    public sealed class RewardConfig
    {
        /// <summary>게시글 1건 작성 시 지급 경험치 (0 = 미지급)</summary>
        public int PostExp { get; set; } = 0;
        /// <summary>게시글 1건 작성 시 지급 토큰 (0 = 미지급)</summary>
        public int PostPoint { get; set; } = 0;

        /// <summary>댓글 1건 작성 시 지급 경험치 (0 = 미지급)</summary>
        public int CommentExp { get; set; } = 0;
        /// <summary>댓글 1건 작성 시 지급 토큰 (0 = 미지급)</summary>
        public int CommentPoint { get; set; } = 0;

        /// <summary>추천(좋아요)을 누른 회원에게 지급 경험치 (0 = 미지급)</summary>
        public int LikeGivenExp { get; set; } = 0;
        /// <summary>추천(좋아요)을 받은 글 작성자에게 지급 토큰 (0 = 미지급)</summary>
        public int LikeReceivedPoint { get; set; } = 0;

        /// <summary>보상 지급 최소 게시글 길이 (미만이면 미지급, 0 = 제한 없음)</summary>
        public int MinPostLength { get; set; } = 0;
        /// <summary>보상 지급 최소 댓글 길이 (미만이면 미지급, 0 = 제한 없음)</summary>
        public int MinCommentLength { get; set; } = 0;

        /// <summary>신규 가입 후 보상 유예 기간(일) — 가입 N일 이내 회원은 활동 보상 미지급 (어뷰징 방지, 0 = 유예 없음)</summary>
        public int NewMemberHoldDays { get; set; } = 0;

        // ---- 액션별 일일 캡 (0 = 무제한) ----

        /// <summary>게시글 보상 일일 횟수 상한</summary>
        public int PostDailyCount { get; set; } = 0;
        /// <summary>게시글 보상 일일 경험치 상한</summary>
        public int PostDailyExp { get; set; } = 0;
        /// <summary>게시글 보상 일일 토큰 상한</summary>
        public int PostDailyPoint { get; set; } = 0;

        /// <summary>댓글 보상 일일 횟수 상한</summary>
        public int CommentDailyCount { get; set; } = 0;
        /// <summary>댓글 보상 일일 경험치 상한</summary>
        public int CommentDailyExp { get; set; } = 0;
        /// <summary>댓글 보상 일일 토큰 상한</summary>
        public int CommentDailyPoint { get; set; } = 0;

        /// <summary>추천(누른 쪽) 보상 일일 횟수 상한</summary>
        public int LikeGivenDailyCount { get; set; } = 0;
        /// <summary>추천(누른 쪽) 보상 일일 경험치 상한</summary>
        public int LikeGivenDailyExp { get; set; } = 0;

        /// <summary>추천(받은 쪽) 보상 일일 횟수 상한</summary>
        public int LikeReceivedDailyCount { get; set; } = 0;
        /// <summary>추천(받은 쪽) 보상 일일 토큰 상한</summary>
        public int LikeReceivedDailyPoint { get; set; } = 0;
    }

    #endregion
}