import json

from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.hashers import make_password
from django.core.exceptions import ObjectDoesNotExist  # ORM get查询不到数据
from django.core.urlresolvers import reverse
from django.db.models import Q
from django.shortcuts import render, HttpResponseRedirect, HttpResponse
from django.views.generic.base import View
from pure_pagination import Paginator, PageNotAnInteger

from courses.models import Course
from operation.models import UserCourse, UserFavorite, UserMessage
from organization.models import CourseOrg, Teacher
from utils.email_send import send_register_email
from utils.mixin_utils import LoginRequiredMixin
from .forms import LoginForm, RegisterForm, ForgetForm, ModifyPwdForm, UploadImageForm, UserInfoForm
from .models import UserProfile, EmailVerifyRecord, Banner


class CustomBackend(ModelBackend):
    """自定义auth验证，可以通过用户名邮箱登录"""

    def authenticate(self, username=None, password=None, **kwargs):
        try:
            user = UserProfile.objects.get(Q(username=username) | Q(email=username))  # 通过用户名或邮箱获取用户是否存在
            if user.check_password(password):  # 如果用户密码正确返回user对象
                return user
            else:  # 出错或者用户密码错误就返回None
                return None
        except Exception as e:
            return None


__all__ = [
    'IndexView',
    'LoginView',
    'LogoutView',
    'ActiveUserView',
    'RegisterView',
    'ForgetPwdView',
    'ResetView',
    'ModifyPwdView',
    'UserInfoView',
    'UploadImageView',
    'UpdatePwdView',
    'SendEmailCodeView',
    'UpdateEmailView',
    'MyCourseView',
    'MyFavOrgVIew',
    'MyFavTeacherVIew',
    'MyFavCourseVIew',
    'MyMessageVIew'
]


# Create your views here.

class IndexView(View):
    """首页"""

    def get(self, request):
        all_banner = Banner.objects.all().order_by('index')  # 轮播图
        courses = Course.objects.filter(is_banner=False)[:6]  # 课程
        banner_course = Course.objects.filter(is_banner=True)[:3]  # 轮播图课程
        course_orgs = CourseOrg.objects.all()[:15]  # 课程机构

        return render(request, 'index.html', {
            'all_banner': all_banner,
            'courses': courses,
            'banner_course': banner_course,
            'course_orgs': course_orgs
        })


class LoginView(View):
    def get(self, request):
        """返回登录页面"""
        return render(request, 'login.html', {})

    def post(self, request):
        """验证用户是否是否可以成功登录"""
        login_form = LoginForm(request.POST)  # FORM验证传过来的值是否合法
        if login_form.is_valid():  # 验证是否错误
            user_name = request.POST.get('username', '')  # 获取用户名
            pass_word = request.POST.get('password', '')  # 获取密码
            user = authenticate(username=user_name, password=pass_word)  # 验证用户名和密码
            if user is not None:  # 如果用户名和密码匹配
                if user.is_active:  # 如果用户是激活状态
                    login(request, user)  # 把SESSION和COOKIE写入request
                    return HttpResponseRedirect(reverse('index'))  # 返回首页
                else:  # 用户未激活
                    return render(request, 'login.html', {'msg': '用户尚未激活！'})
            else:  # 用户名和密码错误
                return render(request, 'login.html', {'msg': '用户名或密码错误！'})
        else:  # FORM验证出错，并吧出错信息传递到前端
            return render(request, 'login.html', {'login_form': login_form})


class LogoutView(View):
    def get(self, request):
        logout(request)
        return HttpResponseRedirect(reverse('index'))


class RegisterView(View):
    """用户注册"""

    def get(self, request):
        register_form = RegisterForm()  # 获取验证码
        return render(request, 'register.html', {'register_form': register_form})

    def post(self, request):
        register_form = RegisterForm(request.POST)  # FORM验证
        if register_form.is_valid():  # 验证是否错误
            user_name = request.POST.get('email', '')  # 获取用户注册的邮箱
            try:
                UserProfile.objects.get(email=user_name)  # 如果用户名已存在
                return render(request, 'register.html', {'msg': '用户已存在！', 'register_form': register_form})
            except ObjectDoesNotExist as e:
                pass_word = request.POST.get('password', '')  # 获取密码
                # 保存用户信息
                user_profile = UserProfile()
                user_profile.username = user_name
                user_profile.email = user_name
                user_profile.password = make_password(pass_word)  # 密码使用make_password加密之后保存
                user_profile.is_active = False  # 用户默认未激活
                user_profile.save()
                # 写入欢迎注册消息
                user_message = UserMessage()
                user_message.user = user_profile.id
                user_message.message = "欢迎注册慕学在线网"
                user_message.save()
                send_register_email(email=user_name, send_type='register')  # 发送用户注册邮件
                return HttpResponseRedirect(reverse('login'))  # 跳转到登录页面
        else:
            return render(request, 'register.html', {'register_form': register_form})


class ActiveUserView(View):
    """用户激活"""

    def get(self, request, active_code):
        """
        :param active_code: 激活的字符串
        """
        try:
            all_records = EmailVerifyRecord.objects.get(code=active_code)  # 获取到这个CODE
        except Exception as e:
            # 如果没有这个code存在则返回一个错误页面
            return render(request, 'active_fail.html')

        if all_records:
            email = all_records.email  # 获取用户邮箱
            user = UserProfile.objects.get(email=email)  # 获取这个用户
            user.is_active = True  # 把用户状态改为激活
            user.save()  # 保存
            all_records.delete()  # 删除激活码
        else:
            # 验证码不存在
            return render(request, 'active_fail.html')
        return HttpResponseRedirect(reverse('login'))  # 激活之后跳转到登录页面


class ForgetPwdView(View):
    """密码重置"""

    def get(self, request):
        forget_form = ForgetForm()  # 获取重置密码Form
        return render(request, 'forgetpwd.html', {'forget_form': forget_form})

    def post(self, request):
        forget_form = ForgetForm(request.POST)
        if forget_form.is_valid():  # Form验证成功
            email = request.POST.get('email', '')  # 获取用户邮箱
            send_register_email(email=email, send_type='forget')  # 发送密码重置链接
            return render(request, 'send_success.html')
        else:
            return render(request, 'forgetpwd.html', {'forget_form': forget_form})


class ResetView(View):
    """修改密码"""

    def get(self, request, reset_code):
        try:
            all_records = EmailVerifyRecord.objects.get(code=reset_code)  # 取出验证码
        except Exception as e:
            return render(request, 'active_fail.html')

        if all_records:
            email = all_records.email  # 获取email
            all_records.delete()  # 删除验证码
            return render(request, 'password_reset.html', {'email': email})
        else:
            return render(request, 'active_fail.html')


class ModifyPwdView(View):
    """修改用户密码"""

    def post(self, request):
        modify_form = ModifyPwdForm(request.POST)  # 验证参数
        if modify_form.is_valid():  # 验证是否铸错
            # 取出用户的用户名和密码
            pwd1 = request.POST.get('password1', '')
            pwd2 = request.POST.get('password2', '')
            email = request.POST.get('email', '')
            if pwd1 != pwd2:  # 两个密码是否一致
                return render(request, 'password_reset.html',
                              {'email': email, 'msg': '密码不一致！'})
            user = UserProfile.objects.get(email=email)  # 获取用户
            user.password = make_password(pwd2)  # 修改密码
            user.save()  # 保存到数据库
            return HttpResponseRedirect(reverse('login'))  # 跳转到登录页面
        else:
            email = request.POST.get('email', None)
            return render(request, 'password_reset.html',
                          {'email': email, 'modify_form': modify_form})


class UserInfoView(LoginRequiredMixin, View):
    """用户个人信息"""

    def get(self, request):
        return render(request, 'usercenter-info.html')

    def post(self, request):
        user_info_form = UserInfoForm(request.POST, instance=request.user)  # 通过Form保存用户信息
        if user_info_form.is_valid():  # 是否报错
            user_info_form.save()  # 保存到数据库
            return HttpResponse('{"status":"success"}', content_type='application/json')
        else:
            return HttpResponse(json.dumps(user_info_form.errors), content_type='application/json')


class UploadImageView(LoginRequiredMixin, View):
    """用户头像上传"""

    def post(self, request):
        # 文件类型需要传递两个参数，第三个参数返回一个UserProfile对象
        image_form = UploadImageForm(request.POST, request.FILES, instance=request.user)
        if image_form.is_valid():  # 是否验证通过
            request.user.save()  # 保存到数据库
            return HttpResponse('{"status":"success"}', content_type='application/json')
        return HttpResponse('{"status":"fail"}', content_type='application/json')


class UpdatePwdView(View):
    """个人中心修改用户密码"""

    def post(self, request):
        modify_form = ModifyPwdForm(request.POST)  # 验证密码
        if modify_form.is_valid():  # 是否验证成功
            pwd1 = request.POST.get('password1', '')
            pwd2 = request.POST.get('password2', '')
            if pwd1 != pwd2:  # 密码是否一致
                return HttpResponse('{"status":"fail","msg":"密码不一致"}', content_type='application/json')
            user = request.user  # 获取用户
            user.password = make_password(pwd2)  # 更新密码
            user.save()  # 保存到数据库
            return HttpResponse('{"status":"success","msg":"密码修改成功"}', content_type='application/json')
        else:
            return HttpResponse(json.dumps(modify_form.errors), content_type='application/json')


class SendEmailCodeView(LoginRequiredMixin, View):
    """发送邮箱验证码"""

    def get(self, request):
        email = request.GET.get('email', '')  # 获取邮箱
        if UserProfile.objects.filter(email=email):  # 邮箱是否存在
            return HttpResponse('"email":"邮箱已经存在"}', content_type='application/json')
        send_register_email(email, 'update_email')  # 发送邮件
        return HttpResponse('{"status":"success"}', content_type='application/json')


class UpdateEmailView(LoginRequiredMixin, View):
    """修改个人邮箱"""

    def post(self, request):
        email = request.POST.get('email', '')  # 获取邮箱
        code = request.POST.get('code', '')  # 获取验证码
        existed_records = EmailVerifyRecord.objects.filter(email=email, code=code,
                                                           send_type='update_email')  # 邮箱是否能匹配到验证码
        if existed_records:  # 如果有
            user = request.user  # 获取的用户
            user.email = email  # 更改邮箱
            user.save()  # 保存到数据库
            return HttpResponse('{"status":"success"}', content_type='application/json')
        else:
            return HttpResponse('"email":"验证码出错"}', content_type='application/json')


class MyCourseView(LoginRequiredMixin, View):
    """我学习的课程"""

    def get(self, request):
        user_courses = UserCourse.objects.filter(user=request.user)  # 获取用户的所有课程
        return render(request, 'usercenter-mycourse.html', {
            'user_courses': user_courses
        })


class MyFavOrgVIew(LoginRequiredMixin, View):
    """我收藏的课程机构"""

    def get(self, request):
        org_list = []  # 机构列表
        fav_orgs = UserFavorite.objects.filter(user=request.user, fav_type=2)  # 当前用户收藏的课程机构
        for fav_org in fav_orgs:
            org_id = fav_org.fav_id  # 获取机构ID
            org = CourseOrg.objects.get(id=org_id)  # 获取指定的机构
            org_list.append(org)  # 把机构添加到列表中
        return render(request, 'usercenter-fav-org.html', {
            'org_list': org_list
        })


class MyFavTeacherVIew(LoginRequiredMixin, View):
    """我收藏的机构讲师"""

    def get(self, request):
        teacher_list = []
        fav_teacher = UserFavorite.objects.filter(user=request.user, fav_type=3)
        for teacher in fav_teacher:
            teacher_id = teacher.fav_id
            teacher = Teacher.objects.get(id=teacher_id)
            teacher_list.append(teacher)
        return render(request, 'usercenter-fav-teacher.html', {
            'teacher_list': teacher_list
        })


class MyFavCourseVIew(LoginRequiredMixin, View):
    """我收藏的机构课程"""

    def get(self, request):
        course_list = []
        fav_course = UserFavorite.objects.filter(user=request.user, fav_type=1)
        for course in fav_course:
            course_id = course.fav_id
            course = Course.objects.get(id=course_id)
            course_list.append(course)
        return render(request, 'usercenter-fav-course.html', {
            'course_list': course_list
        })


class MyMessageVIew(LoginRequiredMixin, View):
    def get(self, request):
        all_message = UserMessage.objects.filter(user=request.user.id)  # 获取用户的所有消息
        all_unread_message = UserMessage.objects.filter(user=request.user.id, has_read=False)  # 获取用户未读的所有消息
        for unread_message in all_unread_message:  # 用户进入个人消息后清空未读消息记录
            unread_message.has_read = True
            unread_message.save()
        try:
            page = request.GET.get('page', 1)
        except PageNotAnInteger:
            page = 1
        p = Paginator(all_message, 10, request=request)  # 每页显示10条
        messages = p.page(page)  # 获取指定页的消息
        return render(request, 'usercenter-message.html', {
            'messages': messages
        })


def page_not_found(request):
    # 全局404处理函数
    from django.shortcuts import render_to_response
    response = render_to_response('404.html', {})
    response.status_code = 404
    return response


def forbidden(request):
    # 全局403处理函数
    from django.shortcuts import render_to_response
    response = render_to_response('403.html', {})
    response.status_code = 403
    return response


def page_error(request):
    # 全局500处理函数
    from django.shortcuts import render_to_response
    response = render_to_response('500.html', {})
    response.status_code = 500
    return response
