from sqlalchemy.orm import Session
from sqlalchemy.sql import text, literal_column
from sqlalchemy.ext.asyncio import AsyncSession
from typing import Annotated
from fastapi import Depends
from sqlalchemy import select, or_, and_
import datetime

from . import auth_utils, orm_models, pydantic_schemas


# Загружаем стихи
async def add_poems_to_db(async_db: AsyncSession):
    f1 = open('poems.txt', encoding='utf-8', mode='r')#открыть фаил для чтения на русском
    for a in range(1, 110):
        f1.seek(0)#перейти к началу
        i=0
        str1 = ""
        stixi = ""
        author = ""
        flag = False
        while str1 != f"стих {a}\n":
            str1=f1.readline()
        name=f1.readline()
        # Цикл для склеивания стихотворения
        while str1 != f"стих {a+1}\n":
            str1=f1.readline()
            if str1 != f"стих {a + 1}\n":
              if (str1 != f"Автор:\n" and flag == False):
                  stixi += str1  # удаление /n и заключение в список
              else:
                  if str1 == f"Автор:\n":#чтобы не записывать слово "автор"
                      flag = True
                  else:
                      author += str1
        poem = orm_models.Poems(title=name, text=stixi, author=author)
        # В конце каждой итерации добавляем в базу данных
        async_db.add(poem)
        async_db.commit()

    # close the file
    f1.close()

async def filter_ann(schema: pydantic_schemas.SortAnnouncements, db: AsyncSession):
    """Функция для последовательного применения различных фильтров (через схему SortAnnouncements)"""
    fields = schema.__dict__ # параметры передоваемой схемы SortAnnouncements (ключи и значения)
    # проходим по названиям фильтров и их значениям
    # выбираем все строки
    query = await db.execute(select(orm_models.Announcement))
    res = set(query.scalars().all())
    for name, filt_val in fields.items():
        # res = await db.execute(statement)
        # если фильтр задан
        if filt_val is not None:
            if name == "obsolete":
                filt_val = bool(filt_val)
            filter_query = await db.execute(select(orm_models.Announcement).where(literal_column(f"announcements.{name}") == filt_val))
            filtered = set(filter_query.scalars().all())
            res = res.intersection(filtered)
    # # отфильтровываем подходящие объявления
    # res = await db.execute(
    #     select(orm_models.Announcement).where(
    #      ((schema.obsolete == None) | ((schema.obsolete != None) & (orm_models.Announcement.obsolete == schema.obsolete))) 
    #    & ((schema.user_id == None) | ((schema.user_id != None) & (orm_models.Announcement.user_id == schema.user_id))) 
    #    & ((schema.metro == None) | ((schema.metro != None) & (orm_models.Announcement.metro == schema.metro))) 
    #    & ((schema.category == None) | ((schema.category != None) & (orm_models.Announcement.category == schema.category)))
    #   ) 
    # )


    # .where(schema.user_id != None and orm_models.Announcement.user_id == schema.user_id)
    # .where(schema.metro != None and orm_models.Announcement.metro == schema.metro)
    # .where(schema.category != None and orm_models.Announcement.category == schema.category)
    # statement = text("SELECT * FROM announcements "
    #                 "WHERE announcements.obsolete = :obsolete "
    #                 "INTERSECT"
    #                 "SELECT * FROM announcements "
    #                 "WHERE announcements.user_id == :user_id "
    #                 "INTERSECT"
    #                 "SELECT * FROM announcements "
    #                 "WHERE announcements.metro == :metro "
    #                 "INTERSECT"
    #                 "SELECT * FROM announcements "
    #                 "WHERE announcements.category == :category")
    
    # res = await db.execute(statement, 
    # {"obsolete": schema.obsolete,
    #  "user_id": schema.user_id, 
    #  "metro": schema.metro, 
    #  "category": schema.category}
    # )

    # возвращаем все подходящие объявления
    return res


async def check_obsolete(db: AsyncSession, current_date: datetime.date):
    """
    Функция участвует в процессе обновления поля obsolete у всех объявлений раз в сутки
    """
    # обращаемся ко всем объявлениям бд
    query_announcements = await db.execute(select(orm_models.Announcement))
    announcements = query_announcements.scalars().all()
    # для каждого объявления
    for ann in announcements:
        # если просрочено
        if ann.best_by < current_date:
            ann.obsolete = True
            await db.commit()
            await db.refresh(ann)  # обновляем состояние объекта


