from sqlalchemy import select, delete
from datetime import datetime
from .models import AutoInfo, SentPhones
from .engine import async_session


def _successful_sms_ad_ids_subquery():
    """ad_id, по которым была хотя бы одна успешная SMS."""
    return (
        select(SentPhones.ad_id)
        .where(
            SentPhones.is_successful.is_(True),
            SentPhones.ad_id.isnot(None),
            SentPhones.ad_id != "",
        )
        .distinct()
    )


async def add_autoinfo(ad_id: str, name: str, year: int, usd_price: int,
                        publish_time: str, all_phones: list, link: str,
                        spam: bool = False) -> AutoInfo:
    """
    Добавляет новую запись в таблицу autoinfo.
    """
    async with async_session() as session:
        async with session.begin():
            autoinfo = AutoInfo(
                ad_id=ad_id,
                name=name,
                year=year,
                usd_price=usd_price,
                publish_time=publish_time,
                all_phones=all_phones,
                link=link,
                spam=spam
            )
            session.add(autoinfo)
        # session.commit() вызывается автоматически при выходе из блока session.begin()
        return autoinfo


async def autoinfo_has_phones(ad_id: str) -> bool:
    """
    Проверяет, есть ли запись с данным ad_id и непустым all_phones.
    """
    phones = await get_autoinfo_phones(ad_id)
    return bool(phones)


async def get_autoinfo_phones(ad_id: str) -> list | None:
    """Телефоны объявления из autoinfo или None, если записи/номеров нет."""
    async with async_session() as session:
        result = await session.execute(
            select(AutoInfo.all_phones).where(AutoInfo.ad_id == ad_id)
        )
        row = result.scalars().first()
        if row is None:
            return None
        if isinstance(row, list) and len(row) > 0:
            return row
        return None


async def update_autoinfo_phones(ad_id: str, phones: list) -> bool:
    """
    Обновляет all_phones для существующей записи.
    Возвращает True если запись найдена и обновлена.
    """
    async with async_session() as session:
        async with session.begin():
            result = await session.execute(
                select(AutoInfo).where(AutoInfo.ad_id == ad_id)
            )
            record = result.scalars().first()
            if record:
                record.all_phones = phones
                return True
            return False


async def update_spam_status(ad_id: str, spam_status: bool) -> bool:
    """
    Обновляет значение поля spam для записи с заданным ad_id.
    Возвращает True, если запись найдена и обновлена, иначе False.
    """
    async with async_session() as session:
        async with session.begin():
            result = await session.execute(select(AutoInfo).where(AutoInfo.ad_id == ad_id))
            record = result.scalars().first()
            if record:
                record.spam = spam_status
                return True
            return False


async def get_all_autoinfo() -> list[AutoInfo]:
    """
    Возвращает список всех записей из таблицы autoinfo.
    """
    async with async_session() as session:
        result = await session.execute(select(AutoInfo))
        autoinfos = result.scalars().all()
        return autoinfos


async def list_autoinfo_with_successful_sms(
    start_dt: datetime | None = None,
    end_dt: datetime | None = None,
) -> list[AutoInfo]:
    """
    Объявления для статистики парсинга: только те, по которым SMS ушла успешно.
    """
    async with async_session() as session:
        stmt = select(AutoInfo).where(
            AutoInfo.ad_id.in_(_successful_sms_ad_ids_subquery())
        )
        if start_dt is not None:
            stmt = stmt.where(AutoInfo.created_at >= start_dt)
        if end_dt is not None:
            stmt = stmt.where(AutoInfo.created_at <= end_dt)
        stmt = stmt.order_by(AutoInfo.created_at.asc())
        result = await session.execute(stmt)
        return list(result.scalars().all())


async def delete_autoinfo_by_dates(dates: list[str]):
    """
    Удаляет записи AutoInfo за указанные даты.
    dates - список строк формата "dd.mm.yyyy"
    """
    if not dates:
        return
        
    async with async_session() as session:
        async with session.begin():
            for date_str in dates:
                target_date = datetime.strptime(date_str, "%d.%m.%Y").date()
                start_dt = datetime.combine(target_date, datetime.min.time())
                end_dt = datetime.combine(target_date, datetime.max.time())
                
                await session.execute(
                    delete(AutoInfo).where(
                        AutoInfo.created_at >= start_dt,
                        AutoInfo.created_at <= end_dt
                    )
                )
