"""
Модели пользователей платформы.
"""
import random
import string
import secrets
from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.core.validators import RegexValidator, MinLengthValidator

from .utils import normalize_phone


class UserManager(BaseUserManager):
    """Менеджер для кастомной модели User."""
    
    def create_user(self, email, password=None, **extra_fields):
        """Создать обычного пользователя."""
        if not email:
            raise ValueError(_('Email обязателен'))
        
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user
    
    def create_superuser(self, email, password=None, **extra_fields):
        """Создать суперпользователя."""
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        extra_fields.setdefault('is_active', True)
        extra_fields.setdefault('role', 'admin')
        
        if extra_fields.get('is_staff') is not True:
            raise ValueError(_('Суперпользователь должен иметь is_staff=True'))
        if extra_fields.get('is_superuser') is not True:
            raise ValueError(_('Суперпользователь должен иметь is_superuser=True'))
        
        return self.create_user(email, password, **extra_fields)


class User(AbstractUser):
    """
    Пользователь платформы с ролями.
    
    Роли:
    - mentor: Преподаватель/Ментор
    - client: Ученик/Клиент
    - parent: Родитель ученика
    - admin: Администратор системы
    """
    
    ROLE_CHOICES = [
        ('mentor', 'Ментор'),
        ('client', 'Клиент'),
        ('parent', 'Родитель'),
        ('admin', 'Администратор'),
    ]
    
    # Переопределяем username, делаем его необязательным
    username = models.CharField(
        max_length=150,
        unique=True,
        blank=True,
        null=True,
        verbose_name='Имя пользователя'
    )
    
    # Email как основной идентификатор
    email = models.EmailField(
        unique=True,
        verbose_name='Email',
        help_text='Email используется для входа в систему'
    )
    
    # Роль пользователя
    role = models.CharField(
        max_length=10,
        choices=ROLE_CHOICES,
        default='client',
        verbose_name='Роль',
        help_text='Роль определяет права доступа в системе'
    )
    
    # Telegram интеграция
    telegram_id = models.BigIntegerField(
        null=True,
        blank=True,
        unique=True,
        verbose_name='Telegram ID',
        help_text='ID пользователя в Telegram для уведомлений'
    )
    
    telegram_username = models.CharField(
        max_length=100,
        blank=True,
        verbose_name='Telegram Username'
    )
    
    # Контактные данные
    phone_regex = RegexValidator(
        regex=r'^\+?1?\d{9,15}$',
        message="Телефон должен быть в формате: '+999999999'. До 15 цифр."
    )
    phone = models.CharField(
        validators=[phone_regex],
        max_length=17,
        blank=True,
        verbose_name='Телефон'
    )
    
    # Профиль
    avatar = models.ImageField(
        upload_to='avatars/%Y/%m/',
        null=True,
        blank=True,
        verbose_name='Аватар'
    )
    
    birth_date = models.DateField(
        null=True,
        blank=True,
        verbose_name='Дата рождения'
    )
    
    bio = models.TextField(
        blank=True,
        max_length=500,
        verbose_name='О себе'
    )
    
    # Верификация
    email_verified = models.BooleanField(
        default=False,
        verbose_name='Email подтвержден'
    )
    
    email_verification_token = models.CharField(
        max_length=100,
        blank=True,
        verbose_name='Токен подтверждения email'
    )
    
    # Дополнительные поля
    timezone = models.CharField(
        max_length=50,
        default='Europe/Moscow',
        verbose_name='Часовой пояс'
    )
    
    language = models.CharField(
        max_length=10,
        default='ru',
        verbose_name='Язык интерфейса'
    )
    
    # Telegram интеграция
    telegram_id = models.BigIntegerField(
        null=True,
        blank=True,
        unique=True,
        verbose_name='Telegram ID',
        help_text='ID пользователя в Telegram для уведомлений'
    )
    
    telegram_username = models.CharField(
        max_length=100,
        blank=True,
        verbose_name='Telegram username',
        help_text='Username в Telegram'
    )

    country = models.CharField(
        max_length=100,
        blank=True,
        verbose_name='Страна',
        help_text='Страна проживания пользователя (для подбора часового пояса и аналитики)',
    )

    city = models.CharField(
        max_length=100,
        blank=True,
        verbose_name='Город',
        help_text='Город проживания пользователя',
    )
    
    language = models.CharField(
        max_length=10,
        default='ru',
        verbose_name='Язык',
        choices=[
            ('ru', 'Русский'),
            ('en', 'English'),
        ]
    )
    
    # Универсальный 8-символьный код (цифры + латинские буквы) для безопасного добавления ментором
    universal_code = models.CharField(
        max_length=8,
        unique=True,
        blank=True,
        null=True,
        validators=[],  # Валидация длины выполняется в коде, чтобы не блокировать сохранение при null
        verbose_name='Универсальный код',
        help_text='8-символьный код (цифры и латинские буквы) для добавления ученика ментором',
    )

    # Статус
    is_blocked = models.BooleanField(
        default=False,
        verbose_name='Заблокирован'
    )
    
    blocked_reason = models.TextField(
        blank=True,
        verbose_name='Причина блокировки'
    )
    
    blocked_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name='Дата блокировки'
    )
    
    # Временные метки
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата создания'
    )
    
    updated_at = models.DateTimeField(
        auto_now=True,
        verbose_name='Дата обновления'
    )
    
    last_activity = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name='Последняя активность'
    )
    
    # Прогресс онбординга (какие страницы уже показывали подсказки)
    # Формат: {"dashboard": true, "schedule": true, "students": false, ...}
    onboarding_tours_seen = models.JSONField(
        default=dict,
        blank=True,
        verbose_name='Просмотренные туры онбординга',
        help_text='Страницы, для которых уже показан приветственный тур',
    )

    # Настройки уведомлений
    notifications_enabled = models.BooleanField(
        default=True,
        verbose_name='Уведомления включены'
    )
    
    email_notifications = models.BooleanField(
        default=True,
        verbose_name='Email уведомления'
    )
    
    telegram_notifications = models.BooleanField(
        default=False,
        verbose_name='Telegram уведомления'
    )
    
    # Настройки ментора: доверие AI при проверке ДЗ (только для role=mentor)
    ai_trust_draft = models.BooleanField(
        default=False,
        verbose_name='Доверять AI (черновик)',
        help_text='AI выставит оценку и заполнит комментарий, сохранит как черновик'
    )
    ai_trust_publish = models.BooleanField(
        default=False,
        verbose_name='Полностью доверять AI',
        help_text='AI выставит оценку и заполнит комментарий и опубликует'
    )
    
    # Ссылка для приглашения учеников (только для менторов)
    invitation_link_token = models.CharField(
        max_length=64,
        blank=True,
        null=True,
        unique=True,
        verbose_name='Токен ссылки-приглашения',
        help_text='Токен для публичной ссылки, по которой ученики могут зарегистрироваться'
    )

    # Токен для входа без пароля (для учеников, зарегистрированных по ссылке)
    login_token = models.CharField(
        max_length=64,
        blank=True,
        null=True,
        unique=True,
        verbose_name='Токен для входа',
        help_text='Токен, позволяющий войти в аккаунт по прямой ссылке'
    )
    
    # Используем email для входа вместо username
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name', 'last_name']
    
    objects = UserManager()
    
    class Meta:
        db_table = 'users'
        verbose_name = 'Пользователь'
        verbose_name_plural = 'Пользователи'
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['email']),
            models.Index(fields=['role']),
            models.Index(fields=['telegram_id']),
            models.Index(fields=['created_at']),
        ]
    
    def __str__(self):
        return f"{self.get_full_name()} ({self.email})"

    def _generate_universal_code(self):
        """Генерация уникального 8-символьного кода (цифры + латинские буквы A–Z)."""
        alphabet = string.ascii_uppercase + string.digits
        for _ in range(100):
            code = ''.join(random.choices(alphabet, k=8))
            # Проверяем уникальность кода
            if not User.objects.filter(universal_code=code).exclude(pk=self.pk).exists():
                return code
        # Если не удалось сгенерировать за 100 попыток, используем более длинный fallback
        return secrets.token_hex(4).upper()

    def save(self, *args, **kwargs):
        # 1. Нормализация телефона
        if self.phone:
            self.phone = normalize_phone(self.phone)
        
        # 2. Генерация username из email
        if not self.username and self.email:
            self.username = self.email.split('@')[0]
            counter = 1
            original_username = self.username
            while User.objects.filter(username=self.username).exclude(pk=self.pk).exists():
                self.username = f"{original_username}{counter}"
                counter += 1
            if kwargs.get('update_fields') is not None:
                fields = set(kwargs['update_fields'])
                fields.add('username')
                kwargs['update_fields'] = list(fields)

        # 3. Гарантируем 8-символьный код (universal_code)
        if not self.universal_code or len(str(self.universal_code).strip()) != 8:
            self.universal_code = self._generate_universal_code()
            if kwargs.get('update_fields') is not None:
                fields = set(kwargs['update_fields'])
                fields.add('universal_code')
                kwargs['update_fields'] = list(fields)

        super().save(*args, **kwargs)


class MentorManager(UserManager):
    def get_queryset(self):
        return super().get_queryset().filter(role='mentor')


class Mentor(User):
    """
    Прокси-модель для отображения только менторов в админке.
    Использует ту же таблицу users, фильтр по role='mentor'.
    """
    objects = MentorManager()

    class Meta:
        proxy = True
        verbose_name = 'Ментор'
        verbose_name_plural = 'Менторы'
    
    def get_full_name(self):
        """Получить полное имя пользователя."""
        full_name = f"{self.first_name} {self.last_name}".strip()
        return full_name or self.email
    
    def get_short_name(self):
        """Получить короткое имя пользователя."""
        return self.first_name or self.email.split('@')[0]
    
    @property
    def is_mentor(self):
        """Проверка, является ли пользователь ментором."""
        return self.role == 'mentor'
    
    @property
    def is_client(self):
        """Проверка, является ли пользователь клиентом."""
        return self.role == 'client'
    
    @property
    def is_parent(self):
        """Проверка, является ли пользователь родителем."""
        return self.role == 'parent'
    
    @property
    def is_admin_role(self):
        """Проверка, является ли пользователь администратором по роли."""
        return self.role == 'admin'
    
    def can_access_admin(self):
        """Может ли пользователь получить доступ к админ-панели."""
        return self.is_staff or self.is_superuser or self.role == 'admin'

    # Мы удалили Mentor.save и _generate_universal_code, так как они теперь в User


class Client(models.Model):
    """
    Модель клиента (ученика).
    Расширяет User дополнительными полями для учеников.
    """
    user = models.OneToOneField(
        User,
        on_delete=models.CASCADE,
        related_name='client_profile',
        verbose_name='Пользователь'
    )
    
    # Учебная информация
    grade = models.CharField(
        max_length=50,
        blank=True,
        verbose_name='Класс/Курс'
    )
    
    school = models.CharField(
        max_length=200,
        blank=True,
        verbose_name='Школа/Учебное заведение'
    )
    
    learning_goals = models.TextField(
        blank=True,
        verbose_name='Цели обучения'
    )
    
    # Связь с менторами
    mentors = models.ManyToManyField(
        User,
        related_name='clients',
        limit_choices_to={'role': 'mentor'},
        blank=True,
        verbose_name='Менторы'
    )
    
    # Статистика
    total_lessons = models.IntegerField(
        default=0,
        verbose_name='Всего занятий'
    )
    
    completed_lessons = models.IntegerField(
        default=0,
        verbose_name='Завершенных занятий'
    )
    
    # Даты
    enrollment_date = models.DateField(
        auto_now_add=True,
        verbose_name='Дата регистрации'
    )
    
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата создания'
    )
    
    updated_at = models.DateTimeField(
        auto_now=True,
        verbose_name='Дата обновления'
    )
    
    class Meta:
        db_table = 'clients'
        verbose_name = 'Клиент'
        verbose_name_plural = 'Клиенты'
        ordering = ['-created_at']
    
    def __str__(self):
        return f"Клиент: {self.user.get_full_name()}"


class Parent(models.Model):
    """
    Модель родителя.
    Может быть привязан к нескольким ученикам.
    """
    user = models.OneToOneField(
        User,
        on_delete=models.CASCADE,
        related_name='parent_profile',
        verbose_name='Пользователь'
    )
    
    # Связь с детьми (клиентами)
    children = models.ManyToManyField(
        Client,
        related_name='parents',
        verbose_name='Дети'
    )
    
    # Контактная информация
    relation_type = models.CharField(
        max_length=50,
        choices=[
            ('mother', 'Мать'),
            ('father', 'Отец'),
            ('guardian', 'Опекун'),
            ('other', 'Другое'),
        ],
        default='other',
        verbose_name='Тип родства'
    )
    
    # Доступ к информации
    can_view_progress = models.BooleanField(
        default=True,
        verbose_name='Может просматривать прогресс'
    )
    
    can_view_schedule = models.BooleanField(
        default=True,
        verbose_name='Может просматривать расписание'
    )
    
    can_receive_reports = models.BooleanField(
        default=True,
        verbose_name='Получает отчеты'
    )
    
    # Даты
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата создания'
    )
    
    updated_at = models.DateTimeField(
        auto_now=True,
        verbose_name='Дата обновления'
    )
    
    class Meta:
        db_table = 'parents'
        verbose_name = 'Родитель'
        verbose_name_plural = 'Родители'
        ordering = ['-created_at']
    
    def __str__(self):
        return f"Родитель: {self.user.get_full_name()}"


class MentorStudentConnection(models.Model):
    """
    Унифицированная модель связи ментор—студент и её статус.
    Объединяет запросы студента (MentorshipRequest) и приглашения ментора (MentorClientInvitation).
    """
    STATUS_PENDING_MENTOR = 'pending_mentor'   # студент отправил запрос, ждём ответа ментора
    STATUS_PENDING_STUDENT = 'pending_student'  # ментор отправил приглашение, ждём студента
    STATUS_PENDING_PARENT = 'pending_parent'    # студент подтвердил, ждём родителя
    STATUS_ACCEPTED = 'accepted'
    STATUS_REJECTED = 'rejected'

    STATUS_CHOICES = [
        (STATUS_PENDING_MENTOR, 'Ожидает ответа ментора'),
        (STATUS_PENDING_STUDENT, 'Ожидает подтверждения студента'),
        (STATUS_PENDING_PARENT, 'Ожидает подтверждения родителя'),
        (STATUS_ACCEPTED, 'Принято'),
        (STATUS_REJECTED, 'Отклонено'),
    ]
    INITIATOR_STUDENT = 'student'
    INITIATOR_MENTOR = 'mentor'
    INITIATOR_CHOICES = [
        (INITIATOR_STUDENT, 'Студент'),
        (INITIATOR_MENTOR, 'Ментор'),
    ]

    mentor = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='connections_as_mentor',
        limit_choices_to={'role': 'mentor'},
        verbose_name='Ментор',
    )
    student = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='connections_as_student',
        limit_choices_to={'role': 'client'},
        verbose_name='Студент',
    )
    status = models.CharField(
        max_length=20,
        choices=STATUS_CHOICES,
        db_index=True,
        verbose_name='Статус',
    )
    initiator = models.CharField(
        max_length=10,
        choices=INITIATOR_CHOICES,
        verbose_name='Инициатор',
    )
    student_confirmed_at = models.DateTimeField(null=True, blank=True, verbose_name='Подтверждено студентом')
    parent_confirmed_at = models.DateTimeField(null=True, blank=True, verbose_name='Подтверждено родителем')
    confirm_token = models.CharField(
        max_length=64,
        blank=True,
        unique=True,
        null=True,
        verbose_name='Токен подтверждения',
    )
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='Дата обновления')

    class Meta:
        db_table = 'mentor_student_connections'
        verbose_name = 'Связь ментор—студент'
        verbose_name_plural = 'Связи ментор—студент'
        ordering = ['-created_at']
        unique_together = [['mentor', 'student']]
        indexes = [
            models.Index(fields=['status']),
            models.Index(fields=['mentor', 'status']),
            models.Index(fields=['student', 'status']),
            models.Index(fields=['confirm_token']),
        ]

    def __str__(self):
        return f'{self.mentor.get_full_name()} ↔ {self.student.get_full_name()} ({self.get_status_display()})'

    def requires_parent_confirmation(self):
        """Нужно ли подтверждение родителя. Отключено — студент подтверждает сам."""
        return False


class Group(models.Model):
    """
    Учебная группа.
    Привязана к одному ментору и может включать неограниченное число учеников.
    Один ученик может состоять в нескольких группах.
    """
    mentor = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='mentor_groups',
        limit_choices_to={'role': 'mentor'},
        verbose_name='Ментор',
    )

    name = models.CharField(
        max_length=255,
        verbose_name='Название группы',
    )

    description = models.TextField(
        blank=True,
        verbose_name='Описание',
    )

    students = models.ManyToManyField(
        Client,
        related_name='groups',
        blank=True,
        verbose_name='Ученики',
    )

    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата создания',
    )

    updated_at = models.DateTimeField(
        auto_now=True,
        verbose_name='Дата обновления',
    )

    class Meta:
        db_table = 'groups'
        verbose_name = 'Группа'
        verbose_name_plural = 'Группы'
        ordering = ['name']
        indexes = [
            models.Index(fields=['mentor', 'name']),
        ]

    def __str__(self):
        return f"{self.name} (ментор: {self.mentor.get_full_name()})"