"""
Модели базы данных
"""
from datetime import datetime
from sqlalchemy import (
    Column, Integer, BigInteger, String, Boolean, DateTime, 
    Text, Float, ForeignKey, Index
)
from sqlalchemy.orm import relationship, declarative_base

Base = declarative_base()


def get_level_by_rating(rating: int) -> str:
    """Определить уровень по рейтингу"""
    if rating >= 1000:
        return 'Лидер'
    elif rating >= 500:
        return 'Активист'
    elif rating >= 100:
        return 'Сосед'
    else:
        return 'Новичок'


class User(Base):
    """Пользователи (жильцы)"""
    __tablename__ = 'users'
    
    user_id = Column(BigInteger, primary_key=True)
    username = Column(String(255), nullable=True)
    first_name = Column(String(255), nullable=True)
    last_name = Column(String(255), nullable=True)
    apartment = Column(String(10), nullable=True)  # Номер квартиры
    phone = Column(String(20), nullable=True)  # Телефон жильца
    verified = Column(Boolean, default=False)  # Прошёл верификацию
    verification_date = Column(DateTime, nullable=True)
    join_date = Column(DateTime, default=datetime.utcnow)
    message_count = Column(Integer, default=0)
    is_banned = Column(Boolean, default=False)
    is_admin = Column(Boolean, default=False)
    last_seen = Column(DateTime, nullable=True)
    
    # Рейтинг активности
    rating = Column(Integer, default=0)  # Баллы активности
    level = Column(String(50), default='Новичок')  # Новичок, Сосед, Активист, Лидер
    
    # Для детекта шпионов
    spy_score = Column(Integer, default=0)  # 0-100
    spy_flags = Column(Text, nullable=True)  # JSON список флагов

    # Для анти-спама
    spam_warning_count = Column(Integer, default=0)  # Количество предупреждений за спам

    # Для анти-спам лимитов
    is_muted = Column(Boolean, default=False)  # Замучен ли
    mute_until = Column(DateTime, nullable=True)  # До когда мут
    rate_limit_warnings = Column(Integer, default=0)  # Предупреждения за лимиты

    # Для детекта мультиаккаунтов
    multicount_score = Column(Integer, default=0)  # Баллы подозрительности
    suspected_device_id = Column(String(100), nullable=True)  # ID устройства (если есть)
    suspected_alt_accounts = Column(Text, nullable=True)  # JSON список подозрительных аккаунтов

    # Для рейтинга токсичности
    toxicity_score = Column(Integer, default=0)  # Средний балл токсичности
    toxic_messages_count = Column(Integer, default=0)  # Количество токсичных сообщений
    complaints_count = Column(Integer, default=0)  # Количество жалоб

    # Связи
    messages = relationship('Message', back_populates='user', lazy='dynamic')
    
    __table_args__ = (
        Index('ix_users_apartment', 'apartment'),
        Index('ix_users_verified', 'verified'),
        Index('ix_users_spy_score', 'spy_score'),
        Index('ix_users_rating', 'rating'),
    )
    
    def __repr__(self):
        return f"<User {self.user_id} ({self.apartment})>"
    
    @property
    def full_name(self):
        parts = [self.first_name, self.last_name]
        return ' '.join(filter(None, parts)) or self.username or f'user{self.user_id}'
    
    def update_level(self):
        """Обновить уровень на основе рейтинга"""
        self.level = get_level_by_rating(self.rating)


class Message(Base):
    """Сообщения в чате"""
    __tablename__ = 'messages'
    
    id = Column(Integer, primary_key=True, autoincrement=True)
    message_id = Column(BigInteger)
    user_id = Column(BigInteger, ForeignKey('users.user_id'))
    chat_id = Column(BigInteger)
    text = Column(Text, nullable=True)
    timestamp = Column(DateTime, default=datetime.utcnow)
    reply_to_message_id = Column(BigInteger, nullable=True)
    forward_from = Column(String(255), nullable=True)
    topic = Column(String(50), nullable=True)  # Тема сообщения (лифты, парковка, уборка...)

    # Связи
    user = relationship('User', back_populates='messages')

    __table_args__ = (
        Index('ix_messages_chat_time', 'chat_id', 'timestamp'),
        Index('ix_messages_user_time', 'user_id', 'timestamp'),
        Index('ix_messages_topic', 'topic'),
    )
    
    def __repr__(self):
        return f"<Message {self.message_id} by {self.user_id}>"


class Service(Base):
    """Контакты служб и мастеров"""
    __tablename__ = 'services'

    service_id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(255), nullable=False)
    category = Column(String(100), nullable=False)  # emergency, plumber, electrician, etc.
    phone = Column(String(20), nullable=False)
    description = Column(Text, nullable=True)
    image_path = Column(String(500), nullable=True)  # Путь к картинке
    rating = Column(Float, default=0.0)
    reviews_count = Column(Integer, default=0)
    verified_by_admin = Column(Boolean, default=False)
    created_at = Column(DateTime, default=datetime.utcnow)

    __table_args__ = (
        Index('ix_services_category', 'category'),
    )

    def __repr__(self):
        return f"<Service {self.name} ({self.category})>"


class VerificationRequest(Base):
    """Заявки на верификацию"""
    __tablename__ = 'verification_requests'
    
    id = Column(Integer, primary_key=True, autoincrement=True)
    user_id = Column(BigInteger, ForeignKey('users.user_id'), nullable=False)
    apartment = Column(String(10), nullable=False)
    photo_file_id = Column(String(255), nullable=True)  # Фото квитанции
    comment = Column(Text, nullable=True)
    status = Column(String(50), default='pending')  # pending, approved, rejected
    created_at = Column(DateTime, default=datetime.utcnow)
    reviewed_at = Column(DateTime, nullable=True)
    reviewed_by = Column(BigInteger, nullable=True)  # Admin ID
    reject_reason = Column(Text, nullable=True)
    
    __table_args__ = (
        Index('ix_verification_status', 'status'),
    )
    
    def __repr__(self):
        return f"<VerificationRequest {self.user_id} apt={self.apartment}>"


class SpyLog(Base):
    """Логи детекта шпионов"""
    __tablename__ = 'spy_logs'
    
    id = Column(Integer, primary_key=True, autoincrement=True)
    user_id = Column(BigInteger, ForeignKey('users.user_id'), nullable=False)
    spy_score = Column(Integer, nullable=False)
    flags = Column(Text, nullable=False)  # JSON список
    detected_at = Column(DateTime, default=datetime.utcnow)
    action_taken = Column(String(50), nullable=True)  # alerted, warned, banned
    
    __table_args__ = (
        Index('ix_spy_logs_user_time', 'user_id', 'detected_at'),
    )
    
    def __repr__(self):
        return f"<SpyLog {self.user_id} score={self.spy_score}>"


class Announcement(Base):
    """Объявления для жильцов"""
    __tablename__ = 'announcements'

    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(255), nullable=False)
    text = Column(Text, nullable=False)
    category = Column(String(50), default='general')  # general, emergency, utility
    created_by = Column(BigInteger, nullable=True)
    created_at = Column(DateTime, default=datetime.utcnow)
    is_pinned = Column(Boolean, default=False)
    is_active = Column(Boolean, default=True)

    __table_args__ = (
        Index('ix_announcements_category', 'category'),
        Index('ix_announcements_active', 'is_active'),
    )

    def __repr__(self):
        return f"<Announcement {self.title}>"


class Poll(Base):
    """Опросы/голосования жильцов"""
    __tablename__ = 'polls'

    poll_id = Column(Integer, primary_key=True, autoincrement=True)
    message_id = Column(BigInteger, nullable=False)  # ID сообщения с опросом в чате
    chat_id = Column(BigInteger, nullable=False)  # ID чата
    question = Column(Text, nullable=False)  # Вопрос опроса
    options = Column(Text, nullable=False)  # JSON: ["Вариант 1", "Вариант 2", ...]
    votes = Column(Text, nullable=True)  # JSON: {"0": [user_id1, user_id2], "1": [user_id3]}
    created_by = Column(BigInteger, ForeignKey('users.user_id'), nullable=False)
    created_at = Column(DateTime, default=datetime.utcnow)
    is_active = Column(Boolean, default=True)  # Активен ли опрос
    closed_at = Column(DateTime, nullable=True)  # Дата закрытия

    # Связи
    creator = relationship('User', backref='polls')

    __table_args__ = (
        Index('ix_polls_chat_active', 'chat_id', 'is_active'),
        Index('ix_polls_created_at', 'created_at'),
    )

    def __repr__(self):
        return f"<Poll {self.poll_id}: {self.question[:30]}>"

    @property
    def total_votes(self) -> int:
        """Общее количество голосов"""
        import json
        if not self.votes:
            return 0
        votes_data = json.loads(self.votes)
        return sum(len(v) for v in votes_data.values())

    def get_results(self) -> list:
        """Получить результаты в формате [(вариант, голоса, процент), ...]"""
        import json
        if not self.votes:
            options_list = json.loads(self.options)
            return [(opt, 0, 0.0) for opt in options_list]

        options_list = json.loads(self.options)
        votes_data = json.loads(self.votes)
        total = self.total_votes

        results = []
        for i, option in enumerate(options_list):
            vote_count = len(votes_data.get(str(i), []))
            percent = (vote_count / total * 100) if total > 0 else 0.0
            results.append((option, vote_count, round(percent, 1)))

        return results


class SpamWarning(Base):
    """Предупреждения за спам/запрещённые ссылки"""
    __tablename__ = 'spam_warnings'

    warning_id = Column(Integer, primary_key=True, autoincrement=True)
    user_id = Column(BigInteger, ForeignKey('users.user_id'), nullable=False)
    message_text = Column(Text, nullable=True)  # Текст сообщения
    reason = Column(Text, nullable=True)  # Причина предупреждения
    created_at = Column(DateTime, default=datetime.utcnow)
    is_active = Column(Boolean, default=True)  # Активно ли предупреждение

    # Связи
    user = relationship('User', backref='spam_warnings')

    __table_args__ = (
        Index('ix_spam_warnings_user', 'user_id'),
        Index('ix_spam_warnings_active', 'is_active'),
    )

    def __repr__(self):
        return f"<SpamWarning {self.user_id}: {self.reason[:30]}>"


class MessageRate(Base):
    """Счётчик сообщений для rate limiting"""
    __tablename__ = 'message_rates'

    id = Column(Integer, primary_key=True, autoincrement=True)
    user_id = Column(BigInteger, ForeignKey('users.user_id'), nullable=False)
    timestamp = Column(DateTime, default=datetime.utcnow)

    # Связи
    user = relationship('User', backref='message_rates')

    __table_args__ = (
        Index('ix_message_rates_user', 'user_id'),
        Index('ix_message_rates_time', 'timestamp'),
    )

    def __repr__(self):
        return f"<MessageRate {self.user_id} @ {self.timestamp}>"


class Schedule(Base):
    """Расписание отключений (вода, свет, отопление)"""
    __tablename__ = 'schedules'

    schedule_id = Column(Integer, primary_key=True, autoincrement=True)
    schedule_type = Column(String(50), nullable=False)  # water, electricity, heating, etc.
    title = Column(String(255), nullable=False)
    description = Column(Text, nullable=True)
    start_time = Column(DateTime, nullable=False)
    end_time = Column(DateTime, nullable=False)
    created_by = Column(BigInteger, ForeignKey('users.user_id'), nullable=True)
    created_at = Column(DateTime, default=datetime.utcnow)
    reminder_sent = Column(Boolean, default=False)  # Отправлено ли напоминание
    is_active = Column(Boolean, default=True)

    # Связи
    creator = relationship('User', backref='schedules')

    __table_args__ = (
        Index('ix_schedules_type', 'schedule_type'),
        Index('ix_schedules_time', 'start_time', 'end_time'),
        Index('ix_schedules_active', 'is_active'),
    )

    def __repr__(self):
        return f"<Schedule {self.title} ({self.start_time})>"

    @property
    def duration_hours(self) -> float:
        """Длительность отключения в часах"""
        if self.start_time and self.end_time:
            delta = self.end_time - self.start_time
            return round(delta.total_seconds() / 3600, 1)
        return 0

    def get_type_emoji(self) -> str:
        """Получить emoji типа отключения"""
        emojis = {
            'water': '💧',
            'electricity': '⚡',
            'heating': '🔥',
            'gas': '🔶',
            'elevator': '🛗',
            'general': '📋'
        }
        return emojis.get(self.schedule_type, '📋')


class Ad(Base):
    """Объявления жильцов (куплю, продам, отдам, найду)"""
    __tablename__ = 'ads'

    ad_id = Column(Integer, primary_key=True, autoincrement=True)
    user_id = Column(BigInteger, ForeignKey('users.user_id'), nullable=False)
    category = Column(String(50), nullable=False)  # sell, buy, give, lost, found, service
    title = Column(String(255), nullable=False)
    description = Column(Text, nullable=True)
    price = Column(Integer, nullable=True)  # Цена в рублях
    phone = Column(String(50), nullable=True)  # Контактный телефон
    message_id = Column(BigInteger, nullable=True)  # ID сообщения в чате
    created_at = Column(DateTime, default=datetime.utcnow)
    expires_at = Column(DateTime, nullable=True)  # Дата истечения (через 7 дней)
    is_active = Column(Boolean, default=True)
    is_moderated = Column(Boolean, default=False)  # Проверено админом

    # Связи
    user = relationship('User', backref='ads')

    __table_args__ = (
        Index('ix_ads_category', 'category'),
        Index('ix_ads_active', 'is_active'),
        Index('ix_ads_created_at', 'created_at'),
    )

    def __repr__(self):
        return f"<Ad {self.title} by {self.user_id}>"

    @property
    def days_left(self) -> int:
        """Осталось дней до истечения"""
        if self.expires_at:
            delta = self.expires_at - datetime.utcnow()
            return max(0, delta.days)
        return 7

    def get_category_emoji(self) -> str:
        """Получить emoji категории"""
        emojis = {
            'sell': '💰',
            'buy': '🛒',
            'give': '🎁',
            'lost': '😿',
            'found': '😺',
            'service': '🔧'
        }
        return emojis.get(self.category, '📋')

    def get_category_name(self) -> str:
        """Получить название категории"""
        names = {
            'sell': 'Продам',
            'buy': 'Куплю',
            'give': 'Отдам',
            'lost': 'Потеряно',
            'found': 'Нашлось',
            'service': 'Услуга'
        }
        return names.get(self.category, 'Общее')


class PaymentReminder(Base):
    """Напоминания о платежах ЖКХ"""
    __tablename__ = 'payment_reminders'

    reminder_id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(255), nullable=False)  # Название платежа
    amount = Column(Integer, nullable=True)  # Сумма в рублях
    due_date = Column(DateTime, nullable=False)  # Дата оплаты (число месяца)
    description = Column(Text, nullable=True)  # Описание
    payment_link = Column(String(500), nullable=True)  # Ссылка на оплату
    is_recurring = Column(Boolean, default=True)  # Ежемесячный платёж
    created_by = Column(BigInteger, ForeignKey('users.user_id'), nullable=True)
    created_at = Column(DateTime, default=datetime.utcnow)
    is_active = Column(Boolean, default=True)
    last_reminder_sent = Column(DateTime, nullable=True)  # Последнее напоминание

    # Связи
    creator = relationship('User', backref='payment_reminders')

    __table_args__ = (
        Index('ix_payment_reminders_due_date', 'due_date'),
        Index('ix_payment_reminders_active', 'is_active'),
    )

    def __repr__(self):
        return f"<PaymentReminder {self.title} (due: {self.due_date})>"

    def get_days_until_due(self, current_day: int = None) -> int:
        """Сколько дней до срока оплаты"""
        from datetime import datetime
        if current_day is None:
            current_day = datetime.utcnow().day

        due_day = self.due_date.day if hasattr(self.due_date, 'day') else self.due_date

        if due_day >= current_day:
            return due_day - current_day
        else:
            return (30 - current_day) + due_day


class ProfileHistory(Base):
    """История изменений профиля пользователя"""
    __tablename__ = 'profile_history'

    id = Column(Integer, primary_key=True, autoincrement=True)
    user_id = Column(BigInteger, ForeignKey('users.user_id'), nullable=False)
    field_name = Column(String(50), nullable=False)  # username, first_name, last_name, apartment
    old_value = Column(Text, nullable=True)  # Старое значение
    new_value = Column(Text, nullable=True)  # Новое значение
    changed_at = Column(DateTime, default=datetime.utcnow)

    # Связи
    user = relationship('User', backref='profile_history')

    __table_args__ = (
        Index('ix_profile_history_user', 'user_id'),
        Index('ix_profile_history_field', 'field_name'),
        Index('ix_profile_history_time', 'changed_at'),
    )

    def __repr__(self):
        return f"<ProfileHistory {self.user_id}: {self.field_name}>"


class Achievement(Base):
    """Достижения пользователей"""
    __tablename__ = 'achievements'

    id = Column(Integer, primary_key=True, autoincrement=True)
    user_id = Column(BigInteger, ForeignKey('users.user_id'), nullable=False)
    achievement_type = Column(String(50), nullable=False)  # Тип достижения
    earned_at = Column(DateTime, default=datetime.utcnow)  # Когда получено
    achievement_data = Column(Text, nullable=True)  # JSON с доп. данными

    # Связи
    user = relationship('User', backref='achievements_list')

    __table_args__ = (
        Index('ix_achievements_user', 'user_id'),
        Index('ix_achievements_type', 'achievement_type'),
    )

    def __repr__(self):
        return f"<Achievement {self.user_id}: {self.achievement_type}>"


class Thank(Base):
    """Благодарности пользователей"""
    __tablename__ = 'thanks'

    id = Column(Integer, primary_key=True, autoincrement=True)
    from_user_id = Column(BigInteger, ForeignKey('users.user_id'), nullable=False)  # Кто поблагодарил
    to_user_id = Column(BigInteger, ForeignKey('users.user_id'), nullable=False)  # Кого поблагодарили
    message = Column(Text, nullable=True)  # Текст благодарности
    created_at = Column(DateTime, default=datetime.utcnow)

    # Связи
    from_user = relationship('User', foreign_keys=[from_user_id], backref='thanks_given')
    to_user = relationship('User', foreign_keys=[to_user_id], backref='thanks_received')

    __table_args__ = (
        Index('ix_thanks_from', 'from_user_id'),
        Index('ix_thanks_to', 'to_user_id'),
        Index('ix_thanks_created', 'created_at'),
    )

    def __repr__(self):
        return f"<Thank {self.from_user_id} → {self.to_user_id}>"


class Event(Base):
    """События дома (собрания, субботники, праздники)"""
    __tablename__ = 'events'

    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(255), nullable=False)  # Название события
    description = Column(Text, nullable=True)  # Описание
    event_type = Column(String(50), default='general')  # Тип: meeting, subbotnik, holiday
    event_date = Column(DateTime, nullable=False)  # Дата и время события
    location = Column(String(255), nullable=True)  # Место проведения
    created_by = Column(BigInteger, ForeignKey('users.user_id'), nullable=True)
    created_at = Column(DateTime, default=datetime.utcnow)
    is_active = Column(Boolean, default=True)
    reminder_sent = Column(Boolean, default=False)  # Напоминание отправлено

    # Связи
    creator = relationship('User', backref='created_events')

    __table_args__ = (
        Index('ix_events_date', 'event_date'),
        Index('ix_events_type', 'event_type'),
        Index('ix_events_active', 'is_active'),
    )

    def __repr__(self):
        return f"<Event {self.title} ({self.event_date})>"


class EventParticipant(Base):
    """Участники событий"""
    __tablename__ = 'event_participants'

    id = Column(Integer, primary_key=True, autoincrement=True)
    event_id = Column(Integer, ForeignKey('events.id'), nullable=False)
    user_id = Column(BigInteger, ForeignKey('users.user_id'), nullable=False)
    joined_at = Column(DateTime, default=datetime.utcnow)

    # Связи
    event = relationship('Event', backref='participants_list')
    user = relationship('User', backref='events_participating')

    __table_args__ = (
        Index('ix_event_participants_event', 'event_id'),
        Index('ix_event_participants_user', 'user_id'),
        Index('ix_event_participants_unique', 'event_id', 'user_id', unique=True),
    )

    def __repr__(self):
        return f"<EventParticipant event={self.event_id} user={self.user_id}>"


class InitiativeGroup(Base):
    """Участники инициативной группы"""
    __tablename__ = 'initiative_group'

    id = Column(Integer, primary_key=True, autoincrement=True)
    user_id = Column(BigInteger, ForeignKey('users.user_id'), nullable=False, unique=True)
    role = Column(String(50), default='member')  # admin, member, coordinator
    joined_at = Column(DateTime, default=datetime.utcnow)
    is_active = Column(Boolean, default=True)
    notes = Column(Text, nullable=True)  # Заметки о роли

    # Связи
    user = relationship('User', backref='initiative_membership')

    __table_args__ = (
        Index('ix_initiative_group_user', 'user_id'),
        Index('ix_initiative_group_active', 'is_active'),
    )

    def __repr__(self):
        return f"<InitiativeGroup user={self.user_id} role={self.role}>"
