using System.Data;
using System.Security.Principal;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.SessionState;

namespace ynhtm.BLL
{
    using Common;
    using DBUtility;

    /// <summary>
    /// 评论操作。
    /// </summary>
    public class Comment
    {
        public const string SQL_TABLE = DAL.Comment.SQL_TABLE + " INNER JOIN " + DAL.Post.SQL_TABLE + " ON " + DAL.Comment.SQL_TABLE + "." + DAL.Comment.POSTID + " = " + DAL.Post.SQL_TABLE + "." + DAL.Post.POSTID;
        public const string SQL_ORDER = "ORDER BY " + DAL.Comment.SQL_TABLE + "." + DAL.Comment.COMMENTID + " DESC";
        public static readonly string SQL_FIELD;

        static Comment()
        {
            SQL_FIELD = Regex.Replace(DAL.Comment.SQL_FIELD, @"(^|,)([^,]+)", "$1" + DAL.Comment.SQL_TABLE + ".$2", RegexOptions.Compiled) + "," + DAL.Post.SQL_TABLE + "." + DAL.Post.TITLE + " AS PostTitle" + "," + DAL.Post.SQL_TABLE + "." + DAL.Post.URL + " AS PostUrl";
        }

        /// <summary>
        /// 插入评论实例到数据库。
        /// </summary>
        /// <param name="item">评论实例。</param>
        public void Insert(Model.Comment item)
        {
            DAL.Comment.Insert(item);
            using (var db = DbBase.GetDb())
                db.ExecuteNonQuery("UPDATE " + DAL.Setting.SQL_TABLE + " SET " + DAL.Setting.COMMENTCOUNT + " = " + DAL.Setting.COMMENTCOUNT + " + 1;UPDATE " + DAL.Category.SQL_TABLE + " SET " + DAL.Category.COMMENTCOUNT + " = " + DAL.Category.COMMENTCOUNT + " + 1 WHERE " + DAL.Category.CATEGORYID + " IN (SELECT " + DAL.Post.CATEGORYID + " FROM " + DAL.Post.SQL_TABLE + " WHERE " + DAL.Post.POSTID + " = @" + DAL.Post.POSTID + ");UPDATE " + DAL.Post.SQL_TABLE + " SET " + DAL.Post.COMMENTCOUNT + " = " + DAL.Post.COMMENTCOUNT + " + 1," + DAL.Post.LASTDATE + " = " + db.Now + " WHERE " + DAL.Post.POSTID + " = @" + DAL.Post.POSTID, db.CreateParameter(DAL.Comment.POSTID, item.PostID));
        }

        #region CommentID

        /// <summary>
        /// 取得评论实例。
        /// </summary>
        /// <param name="commentID">评论编号。</param>
        /// <returns>返回评论实例，没有将返回 null 。</returns>
        public Model.Comment GetByCommentID(int commentID)
        {
            return DAL.Comment.GetByCommentID(commentID);
        }

        /// <summary>
        /// 更新评论。
        /// </summary>
        /// <param name="item">评论实例。</param>
        /// <returns>返回受到影响的行数。</returns>
        public int Update(Model.Comment item)
        {
            return DAL.Comment.Update(item);
        }

        /// <summary>
        /// 删除评论。
        /// </summary>
        /// <param name="commentID">评论编号。</param>
        /// <returns>返回受到影响的行数。</returns>
        public int Delete(int commentID)
        {
            using (var db = DbBase.GetDb())
                db.ExecuteNonQuery("UPDATE " + DAL.Setting.SQL_TABLE + " SET " + DAL.Setting.COMMENTCOUNT + " = " + DAL.Setting.COMMENTCOUNT + " - 1;UPDATE " + DAL.Category.SQL_TABLE + " SET " + DAL.Category.COMMENTCOUNT + " = " + DAL.Category.COMMENTCOUNT + " - 1 WHERE " + DAL.Category.CATEGORYID + " IN (SELECT " + DAL.Post.SQL_TABLE + "." + DAL.Post.CATEGORYID + " FROM " + DAL.Comment.SQL_TABLE + " INNER JOIN " + DAL.Post.SQL_TABLE + " ON " + DAL.Comment.SQL_TABLE + "." + DAL.Comment.POSTID + " = " + DAL.Post.SQL_TABLE + "." + DAL.Post.POSTID + " WHERE " + DAL.Comment.SQL_TABLE + "." + DAL.Comment.COMMENTID + " = @" + DAL.Comment.COMMENTID + ");UPDATE " + DAL.Post.SQL_TABLE + " SET " + DAL.Post.COMMENTCOUNT + " = " + DAL.Post.COMMENTCOUNT + " - 1 WHERE " + DAL.Post.POSTID + " IN (SELECT " + DAL.Comment.POSTID + " FROM " + DAL.Comment.SQL_TABLE + " WHERE " + DAL.Comment.COMMENTID + " = @" + DAL.Comment.COMMENTID + ")", db.CreateParameter(DAL.Comment.COMMENTID, commentID));
            return DAL.Comment.Delete(commentID);
        }

        #endregion

        /// <summary>
        /// 取得评论分页集合。
        /// </summary>
        /// <param name="recordCount">记录总数。</param>
        /// <param name="pageSize">分页大小。</param>
        /// <param name="pageIndex">要返回的页数。</param>
        /// <param name="query">查询条件。</param>
        /// <param name="order">排序方式。</param>
        /// <returns>返回分页数据。</returns>
        public DataTable GetList(ref int recordCount, int pageSize, int pageIndex = 1, IQuery query = null, string order = SQL_ORDER)
        {
            using (var db = DbBase.GetDb())
                return db.GetPage(ref recordCount, SQL_TABLE, order, pageSize, pageIndex, query, SQL_FIELD);
        }

        /// <summary>
        /// 取得评论分页集合。
        /// </summary>
        /// <param name="pageSize">分页大小。</param>
        /// <param name="pageIndex">要返回的页数。</param>
        /// <param name="query">查询条件。</param>
        /// <param name="order">排序方式。</param>
        /// <returns>返回分页数据。</returns>
        public DataTable GetList(int pageSize, int pageIndex = 1, IQuery query = null, string order = SQL_ORDER)
        {
            using (var db = DbBase.GetDb())
                return db.GetPage(SQL_TABLE, order, pageSize, pageIndex, query, SQL_FIELD);
        }

        /// <summary>
        /// 发表新评论。
        /// </summary>
        /// <param name="request">客户端 Web 请求。</param>
        /// <param name="response">客户端 HTTP 响应的信息。</param>
        /// <param name="session">Session 对象。</param>
        /// <param name="principal">System.Web.HttpRequest 对象。</param>
        /// <param name="isWap">是否来自 WAP。</param>
        /// <returns>返回一个 Ajax 结果。</returns>
        public Model.AjaxResult Post(HttpRequest request, HttpResponse response, HttpSessionState session, IPrincipal principal, bool isWap = false)
        {
            var setting = new BLL.Setting();
            var settingItem = setting.Get();

            var code = session[Setting.AUTHCODEKEY];
            if (settingItem.AuthcodeEnabled && (code == null || !string.Equals(request["Authcode"], code.ToString()))) return new Model.AjaxResult(-1, "验证码不正确！");
            var item = new Model.Comment();
            item.PostID = int.Parse(request["PostID"]);
            item.Email = request["Email"];
            item.Name = request["Name"];
            item.Content = request["Content"];
            item.IPAddr = request.UserHostAddress;
            item.IsWap = isWap;

            if (item.Content.IsNullOrWhiteSpace()) return new Model.AjaxResult(-2, "评论内容不能为空！");
            if (!settingItem.CommentEnabled) return new Model.AjaxResult(-3, "系统不允许评论！");
            var post = new BLL.Post();
            if (!post.GetCommentEnabled(item.PostID)) return new Model.AjaxResult(-4, "文章不允许评论！");
            switch (settingItem.CommentAudit)
            {
                case 1:
                    item.IsAudit = true;
                    break;
                case 2:
                    item.IsAudit = !setting.HasDirty(item.Content);
                    break;
                default:
                    item.IsAudit = false;
                    break;
            }
            var id = principal.Identity;
            if (id.IsAuthenticated && id.AuthenticationType == "Forms")
            {
                var user = ((BLL.Principal)principal).User;
                item.UserID = user.UserID;
                if (user.IsAdmin) item.IsAudit = true;
            }
            this.Insert(item);
            return new Model.AjaxResult(0, "发表评论成功！");
        }

        /// <summary>
        /// 切换评论审核状态。
        /// </summary>
        /// <param name="commentID">评论编号。</param>
        /// <returns>返回受到影响的行数。</returns>
        public int AuditToggle(int commentID)
        {
            using (var db = DbBase.GetDb())
                return db.ExecuteNonQuery("UPDATE " + DAL.Comment.SQL_TABLE + " SET " + DAL.Comment.ISAUDIT + " = ABS(" + DAL.Comment.ISAUDIT + " - 1) WHERE " + DAL.Comment.COMMENTID + " = @" + DAL.Comment.COMMENTID, db.CreateParameter(DAL.Comment.COMMENTID, commentID));
        }

        /// <summary>
        /// 设置评论审核状态。
        /// </summary>
        /// <param name="commentID">评论编号的集合。</param>
        /// <param name="isAudit">审核状态。</param>
        /// <returns>返回受到影响的行数。</returns>
        public int Audit(int[] commentID, bool isAudit)
        {
            if (commentID == null || commentID.Length == 0) return 0;
            using (var db = DbBase.GetDb())
                return db.ExecuteNonQuery("UPDATE " + DAL.Comment.SQL_TABLE + " SET " + DAL.Comment.ISAUDIT + " = @" + DAL.Comment.ISAUDIT + " WHERE " + DAL.Comment.COMMENTID + " IN (" + string.Join(",", commentID) + ")", db.CreateParameter(DAL.Comment.ISAUDIT, isAudit));
        }
    }
}