import math
import arrow

from datetime import datetime, timedelta
from decimal import Decimal
from typing import List, Any
from fastapi import HTTPException, status

from sqlalchemy import (
    String,
    ForeignKey,
    Index,
    SmallInteger,
    Boolean,
    TIMESTAMP,
    Text,
    Numeric,
    Integer,
)
from sqlalchemy.orm import Mapped, mapped_column, relationship

from Controllers.Postgres.mixin import CrudCollection


class BuildDecisionBook(CrudCollection):
    """
    Builds class based on declarative_base and BaseMixin via session
    The start dates of the decision log periods are determined from the 'decision_period_date' field in the decision log table within the building information.
    decision_period_date = Her yıl yapılan karar toplantısı + 365 gün her yıl tekrar eden
    decision_book_pdf_path: Karar defteri pdf dosyasının yolu
    resp_company_fix_wage: Karar defterinin oluşmasını sağlayan dışardaki danışmanlık ücreti
    is_out_sourced: Karar defterinin dışardan alınan hizmetle oluşturulup oluşturulmadığı
    contact_agreement_path: Karar defterinin oluşmasını sağlayan dışardaki danışmanlık anlaşması dosyasının yolu
    contact_agreement_date: Karar defterinin oluşmasını sağlayan dışardaki danışmanlık anlaşma tarihi
    meeting_date: Karar defterinin oluşmasını sağlayan toplantı tarihi
    decision_type: Karar defterinin tipi (Bina Yönetim Toplantısı (BYT), Yıllık Acil Toplantı (YAT)
    """

    __tablename__ = "build_decision_book"
    __exclude__fields__ = []

    decision_book_pdf_path: Mapped[str] = mapped_column(
        String, server_default="", nullable=True
    )
    resp_company_fix_wage: Mapped[float] = mapped_column(
        Numeric(10, 2), server_default="0"
    )  #
    is_out_sourced: Mapped[bool] = mapped_column(Boolean, server_default="0")
    meeting_date: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True), server_default="1900-01-01"
    )
    decision_type: Mapped[str] = mapped_column(String(3), server_default="RBM")
    meeting_is_completed: Mapped[bool] = mapped_column(Boolean, server_default="0")
    meeting_completed_date: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True), nullable=True, comment="Meeting Completed Date"
    )

    build_id: Mapped[int] = mapped_column(ForeignKey("build.id"), nullable=False)
    build_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Build UUID"
    )
    resp_company_id: Mapped[int] = mapped_column(ForeignKey("companies.id"))
    resp_company_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Company UUID"
    )
    contact_id: Mapped[int] = mapped_column(
        ForeignKey("contracts.id"), nullable=True, comment="Contract id"
    )
    contact_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Contract UUID"
    )

    buildings: Mapped["Build"] = relationship(
        "Build",
        back_populates="decision_books",
        foreign_keys=build_id,
    )
    decision_book_items: Mapped[List["BuildDecisionBookItems"]] = relationship(
        "BuildDecisionBookItems",
        back_populates="decision_books",
        foreign_keys="BuildDecisionBookItems.build_decision_book_id",
    )

    __table_args__ = (
        Index("build_decision_book_ndx_011", meeting_date, build_id),
        Index("build_decision_book_ndx_011", build_id, "expiry_starts", "expiry_ends"),
        {
            "comment": "Decision Book objects that are related to decision taken at building meetings"
        },
    )

    @classmethod
    def retrieve_active_rbm(cls):
        from Schemas.building.build import Build

        with cls.new_session() as db_session:
            related_build = Build.find_one(id=cls.build_id)
            related_date = arrow.get(related_build.build_date)
            date_processed = related_date.replace(
                year=arrow.now().date().year, month=related_date.month, day=1
            )
            if arrow.now().date() <= date_processed:
                book = cls.filter_one(
                    cls.expiry_ends <= date_processed,
                    cls.decision_type == "RBM",
                    cls.build_id == related_build.id,
                    db=db_session,
                ).data
                if not book:
                    cls.raise_http_exception(
                        status_code="HTTP_404_NOT_FOUND",
                        error_case="NOTFOUND",
                        message=f"Decision Book is not found for {related_build.build_name}-RBM",
                        data=dict(
                            build_id=str(related_build.uu_id),
                            build_name=related_build.build_name,
                            decision_type="RBM",
                        ),
                    )
                return book
            return

    @property
    def semester(self):
        start_format = "".join(
            [str(self.expiry_starts.year), "-", str(self.expiry_starts.month)]
        )
        end_format = "".join(
            [str(self.expiry_ends.year), "-", str(self.expiry_ends.month)]
        )
        return "".join([start_format, " ", end_format])

    def check_book_is_valid(self, bank_date: str):
        if all(
            [True if letter in str(bank_date) else False for letter in ["-", " ", ":"]]
        ):
            bank_date = datetime.strptime(str(bank_date), "%Y-%m-%d %H:%M:%S")
        date_valid = (
            arrow.get(self.expiry_starts)
            < arrow.get(bank_date)
            < arrow.get(self.expiry_ends)
        )
        return date_valid and self.active and not self.deleted

    # @classmethod
    # def retrieve_valid_book(cls, bank_date, iban):
    #     from Schemas import (
    #         BuildIbans,
    #     )
    #     with cls.new_session() as db_session:
    #         if all(
    #             [True if letter in str(bank_date) else False for letter in ["-", " ", ":"]]
    #         ):
    #             bank_date = datetime.strptime(str(bank_date), "%Y-%m-%d %H:%M:%S")
    #             build_iban = BuildIbans.find_one(iban=iban)
    #             decision_book: cls = cls.filter_one(
    #                 cls.build_id == build_iban.build_id,
    #                 cls.expiry_starts < bank_date,
    #                 cls.expiry_ends > bank_date,
    #                 cls.active == True,
    #                 cls.deleted == False,
    #                 db=db_session
    #             ).data
    #             decision_book.check_book_is_valid(bank_date.__str__())
    #             return decision_book
    #         return


class BuildDecisionBookInvitations(CrudCollection):
    """
    Builds class based on declarative_base and BaseMixin via session
    """

    __tablename__ = "build_decision_book_invitations"
    __exclude__fields__ = []

    build_id: Mapped[int] = mapped_column(Integer, nullable=False)
    build_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Build UUID"
    )
    decision_book_id: Mapped[int] = mapped_column(
        ForeignKey("build_decision_book.id"), nullable=False
    )
    decision_book_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Decision Book UUID"
    )

    invitation_type: Mapped[str] = mapped_column(
        String, nullable=False, comment="Invite Type"
    )
    invitation_attempt: Mapped[int] = mapped_column(SmallInteger, server_default="1")
    living_part_count: Mapped[int] = mapped_column(SmallInteger, server_default="1")
    living_part_percentage: Mapped[float] = mapped_column(
        Numeric(10, 2), server_default="0.51"
    )

    message: Mapped[str] = mapped_column(
        Text, nullable=True, comment="Invitation Message"
    )
    planned_date: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True), nullable=False, comment="Planned Meeting Date"
    )
    planned_date_expires: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True), nullable=False, comment="Planned Meeting Date Expires"
    )

    __table_args__ = (
        Index(
            "_build_decision_book_invitations_ndx_01",
            invitation_type,
            planned_date,
            invitation_attempt,
            unique=True,
        ),
        {"comment": "People that are invited to building meetings."},
    )

    @classmethod
    def check_invites_are_ready_for_meeting(cls, selected_decision_book, token_dict):
        with cls.new_session() as db_session:
            first_book_invitation = BuildDecisionBookInvitations.filter_one(
                BuildDecisionBookInvitations.build_id
                == token_dict.selected_occupant.build_id,
                BuildDecisionBookInvitations.decision_book_id
                == selected_decision_book.id,
                BuildDecisionBookInvitations.invitation_attempt == 1,
                db=db_session,
            ).data
            if not first_book_invitation:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail=f"First Meeting Invitation is not found for Decision Book UUID : {selected_decision_book.uu_id}",
                )
            need_attend_count = int(first_book_invitation.living_part_count) * Decimal(
                first_book_invitation.living_part_percentage
            )
            valid_invite_count = (
                BuildDecisionBookPerson.filter_all_system(
                    BuildDecisionBookPerson.invite_id == first_book_invitation.id,
                    BuildDecisionBookPerson.build_decision_book_id
                    == selected_decision_book.id,
                    BuildDecisionBookPerson.is_attending == True,
                    db=db_session,
                )
                .query.distinct(BuildDecisionBookPerson.person_id)
                .count()
            )

            second_book_invitation = BuildDecisionBookInvitations.filter_one_system(
                BuildDecisionBookInvitations.build_id
                == token_dict.selected_occupant.build_id,
                BuildDecisionBookInvitations.decision_book_id
                == selected_decision_book.id,
                BuildDecisionBookInvitations.invitation_attempt == 2,
                db=db_session,
            ).data
            if (
                not valid_invite_count >= need_attend_count
                and not second_book_invitation
            ):
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail=f"In order meeting to be held, {math.ceil(need_attend_count)} people must attend "
                    f"to the meeting. Only {valid_invite_count} people are attending to the meeting.",
                )
            return first_book_invitation or second_book_invitation


class BuildDecisionBookPerson(CrudCollection):
    """
    Builds class based on declarative_base and BaseMixin via session
    Karar Defteri toplantılarına katılan kişiler veya yetkililer
    dues_percent_discount: Katılımcının aidat indirim oranı  Aidatdan yüzde indirim alır
    dues_fix_discount: Katılımcının aidat sabit miktarı  Aidatdan sabit bir miktar indirim alır
    dues_discount_approval_date: Bu kişinin indiriminin onayladığı tarih
    management_typecode: Kişinin toplantı görevi
    """

    __tablename__ = "build_decision_book_person"
    __exclude__fields__ = []
    __enum_list__ = [("management_typecode", "BuildManagementType", "bm")]

    dues_percent_discount: Mapped[int] = mapped_column(SmallInteger, server_default="0")
    dues_fix_discount: Mapped[float] = mapped_column(Numeric(10, 2), server_default="0")
    dues_discount_approval_date: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True), server_default="1900-01-01 00:00:00"
    )
    send_date: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True), nullable=False, comment="Confirmation Date"
    )
    is_attending: Mapped[bool] = mapped_column(
        Boolean, server_default="0", comment="Occupant is Attending to invitation"
    )
    confirmed_date: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True), nullable=True, comment="Confirmation Date"
    )
    token: Mapped[str] = mapped_column(
        String, server_default="", comment="Invitation Token"
    )

    vicarious_person_id: Mapped[int] = mapped_column(
        ForeignKey("people.id"), nullable=True, comment="Vicarious Person ID"
    )
    vicarious_person_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Vicarious Person UUID"
    )

    invite_id: Mapped[int] = mapped_column(
        ForeignKey("build_decision_book_invitations.id"), nullable=False
    )
    invite_uu_id: Mapped[str] = mapped_column(
        String, nullable=False, comment="Invite UUID"
    )

    build_decision_book_id: Mapped[int] = mapped_column(
        ForeignKey("build_decision_book.id"), nullable=False
    )
    build_decision_book_uu_id: Mapped[str] = mapped_column(
        String, nullable=False, comment="Decision Book UUID"
    )
    build_living_space_id: Mapped[int] = mapped_column(
        ForeignKey("build_living_space.id"), nullable=False
    )
    build_living_space_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Living Space UUID"
    )
    person_id: Mapped[int] = mapped_column(ForeignKey("people.id"), nullable=False)
    # person_uu_id: Mapped[str] = mapped_column(String, nullable=False, comment="Person UUID")

    __table_args__ = (
        Index(
            "_build_decision_book_person_ndx_01",
            build_decision_book_id,
            invite_id,
            build_living_space_id,
            unique=True,
        ),
        {"comment": "People that are attended to building meetings."},
    )

    def retrieve_all_occupant_types(self):
        with self.new_session() as db_session:
            all_decision_book_people = self.filter_all_system(
                BuildDecisionBookPersonOccupants.invite_id == self.invite_id,
                db=db_session,
            )
            BuildDecisionBookPersonOccupants.pre_query = all_decision_book_people.query
            return BuildDecisionBookPersonOccupants.filter_all_system(
                db=db_session
            ).data

    def get_occupant_types(self):
        with self.new_session() as db_session:
            if occupants := BuildDecisionBookPersonOccupants.filter_all(
                BuildDecisionBookPersonOccupants.build_decision_book_person_id
                == self.id,
                db=db_session,
            ).data:
                return occupants
            return

    def check_occupant_type(self, occupant_type):
        with self.new_session() as db_session:
            book_person_occupant_type = BuildDecisionBookPersonOccupants.filter_one(
                BuildDecisionBookPersonOccupants.build_decision_book_person_id
                == self.id,
                BuildDecisionBookPersonOccupants.occupant_type_id == occupant_type.id,
                BuildDecisionBookPersonOccupants.active == True,
                BuildDecisionBookPersonOccupants.is_confirmed == True,
                db=db_session,
            ).data
            if not book_person_occupant_type:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail=f"Occupant Type : {occupant_type.occupant_code} is not found in "
                    f"Decision Book Person UUID {self.uu_id}",
                )


class BuildDecisionBookPersonOccupants(CrudCollection):
    """
    Builds class based on declarative_base and BaseMixin via session
    """

    __tablename__ = "build_decision_book_person_occupants"
    __exclude__fields__ = []

    build_decision_book_person_id: Mapped[int] = mapped_column(
        ForeignKey("build_decision_book_person.id"), nullable=False
    )
    build_decision_book_person_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Decision Book Person UUID"
    )
    invite_id: Mapped[int] = mapped_column(
        ForeignKey("build_decision_book_invitations.id"), nullable=True
    )
    invite_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Invite UUID"
    )

    occupant_type_id: Mapped[int] = mapped_column(
        ForeignKey("occupant_types.id"), nullable=False
    )
    occupant_type_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Occupant UUID"
    )

    __table_args__ = (
        Index(
            "_build_decision_book_person_occupants_ndx_01",
            build_decision_book_person_id,
            occupant_type_id,
            unique=True,
        ),
        {"comment": "Occupant Types of People that are attended to building meetings."},
    )


class BuildDecisionBookItems(CrudCollection):
    """
    Builds class based on declarative_base and BaseMixin via session
    item_commentary = metine itiraz şerh maddesi için
    item_order = maddelerin sıralanma numarası
    item_objection = maddelerin itiraz şerhi Text şeklinde
    """

    __tablename__ = "build_decision_book_items"
    __exclude__fields__ = []

    item_order: Mapped[int] = mapped_column(
        SmallInteger, nullable=False, comment="Order Number of Item"
    )
    item_comment: Mapped[str] = mapped_column(
        Text, nullable=False, comment="Comment Content"
    )
    item_objection: Mapped[str] = mapped_column(
        Text, nullable=True, comment="Objection Content"
    )
    info_is_completed: Mapped[bool] = mapped_column(
        Boolean, server_default="0", comment="Info process is Completed"
    )
    is_payment_created: Mapped[bool] = mapped_column(
        Boolean, server_default="0", comment="Are payment Records Created"
    )

    info_type_id: Mapped[int] = mapped_column(
        ForeignKey("api_enum_dropdown.id"), nullable=True
    )
    info_type_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Info Type UUID"
    )

    build_decision_book_id: Mapped[int] = mapped_column(
        ForeignKey("build_decision_book.id"), nullable=False
    )
    build_decision_book_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Decision Book UUID"
    )
    item_short_comment: Mapped[str] = mapped_column(
        String(24),
        nullable=True,
        comment="This field is reserved for use in grouping data or in the pivot heading.",
    )

    decision_books: Mapped["BuildDecisionBook"] = relationship(
        "BuildDecisionBook",
        back_populates="decision_book_items",
        foreign_keys=[build_decision_book_id],
    )
    decision_book_project: Mapped["BuildDecisionBookProjects"] = relationship(
        "BuildDecisionBookProjects",
        back_populates="build_decision_book_item",
        foreign_keys="BuildDecisionBookProjects.build_decision_book_item_id",
    )

    __table_args__ = (
        Index("_build_decision_book_item_ndx_01", build_decision_book_id),
        Index(
            "_build_decision_book_item_ndx_02",
            build_decision_book_id,
            item_order,
            unique=True,
        ),
        {
            "comment": "Decision Book Items that are related to decision taken at building meetings"
        },
    )


class BuildDecisionBookItemsUnapproved(CrudCollection):
    """
    Builds class based on declarative_base and BaseMixin via session unapproved personnel
    """

    __tablename__ = "build_decision_book_items_unapproved"
    __exclude__fields__ = []

    item_objection: Mapped[str] = mapped_column(
        Text, nullable=False, comment="Objection Content"
    )
    item_order: Mapped[int] = mapped_column(
        SmallInteger, nullable=False, comment="Order Number"
    )

    decision_book_item_id: Mapped[int] = mapped_column(
        ForeignKey("build_decision_book_items.id"), nullable=False
    )
    decision_book_item_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Decision Book Item"
    )
    person_id: Mapped[int] = mapped_column(ForeignKey("people.id"), nullable=False)
    person_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Person UUID"
    )
    build_decision_book_item: Mapped[int] = mapped_column(
        ForeignKey("build_decision_book_items.id"), nullable=False
    )
    build_decision_book_item_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Decision Book Item UUID"
    )

    __table_args__ = (
        Index("_build_decision_book_item_unapproved_ndx_01", build_decision_book_item),
        {
            "comment": "People that are unapproved partially or completely in decision book items"
        },
    )


class BuildDecisionBookPayments(CrudCollection):
    """
    Builds class based on declarative_base and BaseMixin via session
    period_time = to_char(NEW.process_date, 'YYYY-MM');
    """

    __tablename__ = "build_decision_book_payments"
    __exclude__fields__ = []
    __enum_list__ = [("receive_debit", "DebitTypes", "D")]

    payment_plan_time_periods: Mapped[str] = mapped_column(
        String(10), nullable=False, comment="Payment Plan Time Periods"
    )
    process_date: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True), nullable=False, comment="Payment Due Date"
    )
    payment_amount: Mapped[float] = mapped_column(
        Numeric(16, 2), nullable=False, comment="Payment Amount"
    )
    currency: Mapped[str] = mapped_column(String(8), server_default="TRY")

    payment_types_id: Mapped[int] = mapped_column(
        ForeignKey("api_enum_dropdown.id"), nullable=True
    )
    payment_types_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Dues Type UUID"
    )

    period_time: Mapped[str] = mapped_column(String(12))
    process_date_y: Mapped[int] = mapped_column(SmallInteger)
    process_date_m: Mapped[int] = mapped_column(SmallInteger)

    build_decision_book_item_id: Mapped[int] = mapped_column(
        ForeignKey("build_decision_book_items.id"),
        nullable=False,
        comment="Build Decision Book Item ID",
    )
    build_decision_book_item_uu_id: Mapped[str] = mapped_column(
        String, nullable=False, comment="Decision Book Item UUID"
    )
    # build_decision_book_id: Mapped[int] = mapped_column(
    #     ForeignKey("build_decision_book.id"), nullable=True
    # )
    # build_decision_book_uu_id: Mapped[str] = mapped_column(
    #     String, nullable=True, comment="Decision Book UUID"
    # )
    build_parts_id: Mapped[int] = mapped_column(
        ForeignKey("build_parts.id"), nullable=False
    )
    build_parts_uu_id: Mapped[str] = mapped_column(
        String, nullable=False, comment="Build Part UUID"
    )
    decision_book_project_id: Mapped[int] = mapped_column(
        ForeignKey("build_decision_book_projects.id"),
        nullable=True,
        comment="Decision Book Project ID",
    )
    decision_book_project_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Decision Book Project UUID"
    )
    account_records_id: Mapped[int] = mapped_column(
        ForeignKey("account_records.id"), nullable=True
    )
    account_records_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Account Record UU ID"
    )

    # budget_records_id: Mapped[int] = mapped_column(ForeignKey("account_records.id"), nullable=True)
    # budget_records_uu_id: Mapped[str] = mapped_column(
    #     String, nullable=True, comment="Budget UUID"
    # )
    # accounting_id: Mapped[int] = mapped_column(ForeignKey("account_detail.id"), nullable=True)
    # accounting_uu_id: Mapped[str] = mapped_column(
    #     String, nullable=True, comment="Accounting UUID"
    # )
    # receive_debit_id: Mapped[int] = mapped_column(ForeignKey("api_enum_dropdown.id"), nullable=True)
    # receive_debit_uu_id: Mapped[str] = mapped_column(String, nullable=True, comment="Debit UUID")

    # accounting: Mapped["AccountDetail"] = relationship(
    #     "AccountDetail",
    #     back_populates="decision_book_payment_detail",
    #     foreign_keys=[accounting_id],
    # )
    #
    # decision_book_master: Mapped["BuildDecisionBookPaymentsMaster"] = relationship(
    #     "BuildDecisionBookPaymentsMaster",
    #     back_populates="decision_book_payment_detail",
    #     foreign_keys=[build_decision_book_payments_master_id],
    # )
    # budget_records: Mapped["CompanyBudgetRecords"] = relationship(
    #     "CompanyBudgetRecords",
    #     back_populates="decision_book_payment_detail",
    #     foreign_keys=[budget_records_id],
    # )

    __table_args__ = (
        Index(
            "build_decision_book_payments_detail_ndx_00",
            build_decision_book_item_id,
            build_parts_id,
            payment_plan_time_periods,
            process_date,
            payment_types_id,
            account_records_id,
            unique=True,
        ),
        Index("build_decision_book_payments_detail_ndx_01", account_records_id),
        {"comment": "Payment Details of Decision Book Payments"},
    )


class BuildDecisionBookLegal(CrudCollection):
    """
    Builds class based on declarative_base and BaseMixin via session
    lawsuits_type C:Court Mehkeme M: mediator arabulucu
    """

    __tablename__ = "build_decision_book_legal"
    __exclude__fields__ = []

    period_start_date: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True), nullable=False, comment="Start Date of Legal Period"
    )
    lawsuits_decision_number: Mapped[str] = mapped_column(
        String, nullable=False, comment="Lawsuits Decision Number"
    )
    lawsuits_decision_date: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True), nullable=False, comment="Lawsuits Decision Date"
    )

    period_stop_date: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True), server_default="2099-12-31 23:59:59"
    )
    decision_book_pdf_path: Mapped[str] = mapped_column(
        String, server_default="", nullable=True
    )
    resp_company_total_wage: Mapped[float] = mapped_column(
        Numeric(10, 2), server_default="0", nullable=True
    )
    contact_agreement_path: Mapped[str] = mapped_column(
        String, server_default="", nullable=True
    )
    contact_agreement_date: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True), server_default="1900-01-01 00:00:00", nullable=True
    )
    meeting_date: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True), server_default="1900-01-01 00:00:00"
    )
    lawsuits_type: Mapped[str] = mapped_column(String(1), server_default="C")
    lawsuits_name: Mapped[str] = mapped_column(String(128))
    lawsuits_note: Mapped[str] = mapped_column(String(512))
    lawyer_cost: Mapped[float] = mapped_column(Numeric(20, 2))
    mediator_lawyer_cost: Mapped[float] = mapped_column(Numeric(20, 2))
    other_cost: Mapped[float] = mapped_column(Numeric(20, 2))
    legal_cost: Mapped[float] = mapped_column(Numeric(20, 2))
    approved_cost: Mapped[float] = mapped_column(Numeric(20, 2))
    total_price: Mapped[float] = mapped_column(Numeric(20, 2))

    build_db_item_id: Mapped[int] = mapped_column(
        ForeignKey("build_decision_book_items.id"), nullable=False
    )
    build_db_item_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Decision Book Item UUID"
    )
    resp_attorney_id: Mapped[int] = mapped_column(
        ForeignKey("people.id"), nullable=False
    )
    resp_attorney_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Attorney UUID"
    )
    resp_attorney_company_id: Mapped[int] = mapped_column(ForeignKey("companies.id"))
    resp_attorney_company_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Company UUID"
    )
    mediator_lawyer_person_id: Mapped[int] = mapped_column(ForeignKey("people.id"))
    mediator_lawyer_person_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Mediator Lawyer UUID"
    )

    __table_args__ = (
        Index("_build_decision_book_legal_ndx_00", meeting_date),
        {
            "comment": "Legal items related to decision book items recoreded at building meetings"
        },
    )


class BuildDecisionBookProjects(CrudCollection):
    """
    Builds class based on declarative_base and BaseMixin via session
    project_type = C:Court Mehkeme M: mediator arabulucu
    """

    __tablename__ = "build_decision_book_projects"
    __exclude__fields__ = []

    project_no: Mapped[str] = mapped_column(
        String(12), nullable=True, comment="Project Number of Decision Book"
    )
    project_name: Mapped[str] = mapped_column(
        String, nullable=False, comment="Project Name"
    )
    project_start_date: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True), nullable=False, comment="Project Start Date"
    )
    project_stop_date: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True), server_default="2099-12-31 23:59:59"
    )
    project_type: Mapped[str] = mapped_column(String, server_default="C")
    project_note: Mapped[str] = mapped_column(Text)

    decision_book_pdf_path: Mapped[str] = mapped_column(
        String, server_default="", nullable=True
    )
    is_completed: Mapped[bool] = mapped_column(
        Boolean, server_default="0", comment="Project is Completed"
    )
    status_code: Mapped[int] = mapped_column(SmallInteger, nullable=True)
    resp_company_fix_wage: Mapped[float] = mapped_column(
        Numeric(10, 2), server_default="0"
    )
    is_out_sourced: Mapped[bool] = mapped_column(Boolean, server_default="0")

    meeting_date: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True), server_default="1900-01-01 00:00:00", index=True
    )
    currency: Mapped[str] = mapped_column(String(8), server_default="TRY")
    bid_price: Mapped[float] = mapped_column(Numeric(16, 4), server_default="0")
    approved_price: Mapped[float] = mapped_column(Numeric(16, 4), server_default="0")
    final_price: Mapped[float] = mapped_column(Numeric(16, 4), server_default="0")

    contact_id: Mapped[int] = mapped_column(
        ForeignKey("contracts.id"), nullable=True, comment="Contract id"
    )
    contact_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Contract UUID"
    )
    build_decision_book_id: Mapped[int] = mapped_column(
        ForeignKey("build_decision_book.id"), nullable=False
    )
    build_decision_book_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Decision Book UUID"
    )
    build_decision_book_item_id: Mapped[int] = mapped_column(
        ForeignKey("build_decision_book_items.id"), nullable=False
    )
    build_decision_book_item_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Decision Book Item UUID"
    )
    project_response_living_space_id: Mapped[int] = mapped_column(
        ForeignKey("build_living_space.id"),
        nullable=True,
        comment="Project Response Person ID",
    )
    project_response_living_space_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Project Response Person UUID"
    )
    resp_company_id: Mapped[int] = mapped_column(
        ForeignKey("companies.id"), nullable=True
    )
    resp_company_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Company UUID"
    )

    build_decision_book_item: Mapped["BuildDecisionBookItems"] = relationship(
        "BuildDecisionBookItems",
        back_populates="decision_book_project",
        foreign_keys=[build_decision_book_item_id],
    )

    __table_args__ = (
        Index(
            "_build_decision_book_project_ndx_00",
            project_no,
            project_start_date,
            unique=True,
        ),
        {
            "comment": "Project related to decision taken at building meetings on book items"
        },
    )

    @property
    def get_project_year(self):
        return self.decision_book_items.decision_books.period_start_date.year

    @property
    def get_project_no(self):
        return f"{self.get_project_year}-{str(self.id)[-4:].zfill(4)}"


class BuildDecisionBookProjectPerson(CrudCollection):
    """
    Builds class based on declarative_base and BaseMixin via session
    """

    __tablename__ = "build_decision_book_project_person"
    __exclude__fields__ = []
    # __enum_list__ = [("management_typecode", "ProjectTeamTypes", "PTT-EMP")]

    dues_percent_discount: Mapped[int] = mapped_column(SmallInteger, server_default="0")
    job_fix_wage: Mapped[float] = mapped_column(Numeric(10, 2), server_default="0")
    bid_price: Mapped[float] = mapped_column(Numeric(10, 2), server_default="0")
    decision_price: Mapped[float] = mapped_column(Numeric(10, 2), server_default="0")

    build_decision_book_project_id: Mapped[int] = mapped_column(
        ForeignKey("build_decision_book_projects.id"), nullable=False
    )
    build_decision_book_project_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Decision Book Project UUID"
    )
    living_space_id: Mapped[int] = mapped_column(
        ForeignKey("build_living_space.id"), nullable=False
    )
    living_space_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Living Space UUID"
    )

    __table_args__ = (
        {"comment": "People that are attended to building project meetings."},
    )


class BuildDecisionBookProjectItems(CrudCollection):
    """
    Builds class based on declarative_base and BaseMixin via session
    """

    __tablename__ = "build_decision_book_project_items"
    __exclude__fields__ = []

    item_header: Mapped[str] = mapped_column(
        String, nullable=False, comment="Item Header"
    )
    item_comment: Mapped[str] = mapped_column(
        Text, nullable=False, comment="Item Comment"
    )
    attachment_pdf_path: Mapped[str] = mapped_column(
        String, server_default="", nullable=True, comment="Attachment PDF Path"
    )
    item_estimated_cost: Mapped[float] = mapped_column(
        Numeric(16, 2), server_default="0", comment="Estimated Cost"
    )
    item_short_comment: Mapped[str] = mapped_column(
        String(24),
        nullable=True,
        comment="This field is reserved for use in grouping data or in the pivot heading.",
    )

    build_decision_book_project_id: Mapped[int] = mapped_column(
        ForeignKey("build_decision_book_projects.id"), nullable=False
    )
    build_decision_book_project_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Decision Book Project UUID"
    )

    __table_args__ = (
        {"comment": "Project Items related to decision taken at building meetings"},
    )
