text: """
  Utilities to mock MySQL record
  
  Database records added by fixtures should be removed after tests.
  """
  from abc import abstractmethod
  from typing import Protocol, Generator
  from datetime import datetime
  from collections import defaultdict
  
  import pytest
  from sqlalchemy.orm import Session
  
  from pol.db import sa
  from pol.db.const import Gender, BloodType, PersonType, SubjectType, CollectionType
  from pol.db.tables import (
      ChiiMember,
      ChiiPerson,
      ChiiSubject,
      ChiiPersonField,
      ChiiSubjectField,
      ChiiSubjectInterest,
      ChiiOauthAccessToken,
  )
  
  DBSession = sa.sync_session_maker()
  
  
  @pytest.fixture()
  def db_session():
      db_session = DBSession()
      try:
          yield db_session
      except Exception:  # pragma: no cover
          db_session.rollback()
          raise
      finally:
          db_session.close()
  
  
  @pytest.fixture()
  def mock_subject(db_session: Session):
      mock_subject_id = set()
      delete_query = defaultdict(list)
  
      def mock_id(
          subject_id: int,
          subject_name="",
          subject_type=SubjectType.anime,
          subject_name_cn="",
          subject_uid=1,
          subject_creator=1,
          subject_image="",
          field_infobox="",
          field_summary="",
          field_5="",
          subject_idx_cn="",
          subject_airtime=1,
          subject_nsfw=0,
          subject_ban=0,
          field_tags="",
          field_airtime=1,
          field_year=2007,
          field_mon=1,
          field_week_day=3,
          field_date=datetime.now().astimezone().date(),
      ):
          delete_query[ChiiSubject].append(ChiiSubject.subject_id == subject_id)
          delete_query[ChiiSubjectField].append(ChiiSubjectField.field_sid == subject_id)
  
          check_exist(db_session, delete_query)
          mock_subject_id.add(subject_id)
  
          db_session.add(
              ChiiSubject(
                  subject_id=subject_id,
                  subject_name=subject_name,
                  subject_name_cn=subject_name_cn,
                  subject_uid=subject_uid,
                  subject_type_id=subject_type,
                  subject_creator=subject_creator,
                  subject_image=subject_image,
                  field_infobox=field_infobox,
                  field_summary=field_summary,
                  field_5=field_5,
                  subject_idx_cn=subject_idx_cn,
                  subject_airtime=subject_airtime,
                  subject_nsfw=subject_nsfw,
                  subject_ban=subject_ban,
              )
          )
          db_session.add(
              ChiiSubjectField(
                  field_sid=subject_id,
                  field_tags=field_tags,
                  field_airtime=field_airtime,
                  field_year=field_year,
                  field_mon=field_mon,
                  field_week_day=field_week_day,
                  field_date=field_date,
              )
          )
          db_session.commit()
  
      try:
          yield mock_id
      finally:
          for table, where in delete_query.items():
              db_session.execute(sa.delete(table).where(sa.or_(*where)))
          db_session.commit()
  
  
  @pytest.fixture()
  def mock_person(db_session: Session):
      mock_person_id = set()
      delete_query = defaultdict(list)
  
      def mock_id(
          prsn_id: int,
          prsn_name="",
          prsn_type=PersonType.person,
          prsn_infobox="",
          prsn_producer=0,
          prsn_mangaka=0,
          prsn_artist=1,
          prsn_seiyu=0,
          prsn_writer=0,
          prsn_illustrator=0,
          prsn_actor=0,
          prsn_summary="",
          prsn_img="",
          prsn_img_anidb="",
          prsn_comment=0,
          prsn_collects=0,
          prsn_dateline=0,
          prsn_lastpost=0,
          prsn_lock=0,
          prsn_anidb_id=0,
          prsn_ban=0,
          prsn_redirect=0,
          prsn_nsfw=0,
          gender=Gender.male,
          bloodtype=BloodType.o,
          birth_year=2000,
          birth_mon=1,
          birth_day=1,
      ):
          delete_query[ChiiPerson].append(ChiiPerson.prsn_id == prsn_id)
          delete_query[ChiiPersonField].append(ChiiPersonField.prsn_id == prsn_id)
  
          check_exist(db_session, delete_query)
          mock_person_id.add(prsn_id)
  
          db_session.add(
              ChiiPerson(
                  prsn_id=prsn_id,
                  prsn_name=prsn_name,
                  prsn_type=prsn_type,
                  prsn_infobox=prsn_infobox,
                  prsn_producer=prsn_producer,
                  prsn_mangaka=prsn_mangaka,
                  prsn_artist=prsn_artist,
                  prsn_seiyu=prsn_seiyu,
                  prsn_writer=prsn_writer,
                  prsn_illustrator=prsn_illustrator,
                  prsn_actor=prsn_actor,
                  prsn_summary=prsn_summary,
                  prsn_img=prsn_img,
                  prsn_img_anidb=prsn_img_anidb,
                  prsn_comment=prsn_comment,
                  prsn_collects=prsn_collects,
                  prsn_dateline=prsn_dateline,
                  prsn_lastpost=prsn_lastpost,
                  prsn_lock=prsn_lock,
                  prsn_anidb_id=prsn_anidb_id,
                  prsn_ban=prsn_ban,
                  prsn_redirect=prsn_redirect,
                  prsn_nsfw=prsn_nsfw,
              )
          )
          db_session.add(
              ChiiPersonField(
                  prsn_cat="prsn",
                  prsn_id=prsn_id,
                  gender=gender,
                  bloodtype=bloodtype,
                  birth_year=birth_year,
                  birth_mon=birth_mon,
                  birth_day=birth_day,
              )
          )
          db_session.commit()
  
      try:
          yield mock_id
      finally:
          for table, where in delete_query.items():
              db_session.execute(sa.delete(table).where(sa.or_(*where)))
          db_session.commit()
  
  
  class MockUser(Protocol):
      @abstractmethod
      def __call__(
          self,
          user_id: int,
          access_token: str = "",
          username: str = "",
          expires: datetime = datetime.now(),
      ) -> None:
          pass
  
  
  @pytest.fixture()
  def mock_user(db_session: Session) -> Generator[MockUser, None, None]:
      mock_user_id = set()
      mock_token = set()
      delete_query = defaultdict(list)
  
      def mock_id(
          user_id: int,
          access_token: str = "",
          username: str = "",
          expires=datetime.now(),
      ):
          if user_id in mock_user_id and (not access_token or access_token in mock_token):
              return
          mock_user_id.add(user_id)
          mock_token.add(access_token)
          if access_token:
              delete_query[ChiiOauthAccessToken].append(
                  ChiiOauthAccessToken.access_token == access_token
              )
          delete_query[ChiiMember].append(ChiiMember.uid == user_id)
          check_exist(db_session, delete_query)
  
          if access_token:
              db_session.add(
                  ChiiOauthAccessToken(
                      access_token=access_token,
                      client_id="",
                      user_id=user_id,
                      expires=expires,
                      scope=None,
                  )
              )
  
          db_session.add(
              ChiiMember(
                  uid=user_id,
                  username=username or f"mock_{user_id}",
                  nickname="",
                  avatar="",
                  groupid=10,
                  sign="",
              )
          )
          db_session.commit()
  
      try:
          yield mock_id
      finally:
          for table, where in delete_query.items():
              db_session.execute(sa.delete(table).where(sa.or_(*where)))
          db_session.commit()
  
  
  @pytest.fixture()
  def mock_user_collection(db_session: Session):
      mock_ids = set()
      delete_query = defaultdict(list)
  
      def mock_collection(
          id: int,
          user_id: int,
          subject_id: int,
          subject_type=SubjectType.anime,
          type=CollectionType.doing,
          private=False,
      ):
          delete_query[ChiiSubjectInterest].append(ChiiSubjectInterest.id == id)
          check_exist(db_session, delete_query)
  
          mock_ids.add(id)
  
          db_session.add(
              ChiiSubjectInterest(
                  id=id,
                  user_id=user_id,
                  subject_id=subject_id,
                  subject_type=subject_type,
                  type=type,
                  private=private,
              )
          )
  
          db_session.commit()
  
      try:
          yield mock_collection
      finally:
          for table, where in delete_query.items():
              db_session.execute(sa.delete(table).where(sa.or_(*where)))
          db_session.commit()
  
  
  def check_exist(db_session: Session, quries):
      for Table, q in quries.items():
          query = q[-1]
          r = db_session.execute(sa.select(Table).where(query)).all()
          if r:  # pragma: no cover
              raise ValueError(
                  f"record {query.left.name} == {repr(query.right.value)}"
                  f" exists in table {Table}, can't mock it"
              )
  
      for Table, q in quries.items():
          db_session.execute(sa.delete(Table).where(q[-1]))
  