from datetime import datetime, timedelta
from typing import List, Optional, Union

from fastapi import HTTPException, status
from sqlalchemy.orm import mapped_column, relationship, Mapped
from sqlalchemy import (
    String,
    Integer,
    Boolean,
    ForeignKey,
    Index,
    TIMESTAMP,
    func,
    Text,
    Numeric,
    or_,
)

from api_library.date_time_actions.date_functions import system_arrow
from databases.sql_models.core_mixin import CrudCollection
from databases.extensions.selector_classes import SelectActionWithEmployee
from api_validations.validations_request import (
    InsertBuild,
    InsertBuildParts,
    InsertBuildLivingSpace,
    UpdateBuild,
)
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from databases.language_models.building.build import (
    BuildTypesLanguageModel,
    Part2EmployeeLanguageModel,
    BuildPartsLanguageModel,
    BuildSitesLanguageModel,
    RelationshipEmployee2BuildLanguageModel,
    BuildLanguageModel,
    BuildPartsLanguageModel,
    BuildLivingSpaceLanguageModel,
    BuildManagementLanguageModel,
    BuildAreaLanguageModel,
    BuildCompaniesProvidingLanguageModel,
    BuildPersonProvidingLanguageModel,
)


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

    """

    __tablename__ = "build_types"
    __exclude__fields__ = []
    __language_model__ = BuildTypesLanguageModel
    __include__fields__ = []

    function_code: Mapped[str] = mapped_column(
        String(12), server_default="", nullable=False, comment="Function Code"
    )
    type_code: Mapped[str] = mapped_column(
        String(12), server_default="", nullable=False, comment="Structure Type Code"
    )
    lang: Mapped[str] = mapped_column(
        String(4), server_default="TR", nullable=False, comment="Language"
    )
    type_name: Mapped[str] = mapped_column(
        String(48), server_default="", nullable=False, comment="Type Name"
    )

    __table_args__ = (
        Index("_build_types_ndx_00", type_code, function_code, lang, unique=True),
        {"comment": "Function group of building types with their language information"},
    )


class Part2Employee(CrudCollection):
    """
    Employee2Parts class based on declarative_base and BaseMixin via session
    In between start and end date, a part can be assigned to only one employee
    """

    __tablename__ = "part2employee"
    __exclude__fields__ = []
    __language_model__ = Part2EmployeeLanguageModel
    __include__fields__ = []

    build_id: Mapped[int] = mapped_column(Integer, comment="Building ID")
    part_id: Mapped[int] = mapped_column(
        ForeignKey("build_parts.id"), nullable=False, comment="Part ID"
    )
    employee_id: Mapped[int] = mapped_column(
        ForeignKey("employees.id"), nullable=False, comment="Employee ID"
    )

    __table_args__ = (
        Index("_part2employee_ndx_00", employee_id, part_id, unique=True),
        {"comment": "Employee2Parts Information"},
    )


class RelationshipEmployee2Build(CrudCollection):
    """
    CompanyRelationship class based on declarative_base and CrudCollection via session
    Company -> Sub Company -> Sub-Sub Company

    """

    __tablename__ = "relationship_employee2build"
    __exclude__fields__ = []
    __language_model__ = RelationshipEmployee2BuildLanguageModel

    company_id: Mapped[int] = mapped_column(
        ForeignKey("companies.id"), nullable=False
    )  # 1, 2, 3
    employee_id: Mapped[int] = mapped_column(
        ForeignKey("employees.id"), nullable=False
    )  # employee -> (n)person Evyos LTD
    member_id: Mapped[int] = mapped_column(
        ForeignKey("build.id"), nullable=False
    )  # 2, 3, 4

    relationship_type: Mapped[str] = mapped_column(
        String, nullable=True, server_default="Employee"
    )  # Commercial
    show_only: Mapped[bool] = mapped_column(Boolean, server_default="False")

    __table_args__ = (
        Index(
            "relationship_build_employee_ndx_00",
            company_id,
            employee_id,
            member_id,
            relationship_type,
            unique=True,
        ),
        {"comment": "Build & Employee Relationship Information"},
    )


class Build(CrudCollection, SelectActionWithEmployee):
    """
    Builds class based on declarative_base and BaseMixin via session
    """

    __tablename__ = "build"
    __exclude__fields__ = []
    __language_model__ = BuildLanguageModel
    __include__fields__ = []
    __access_by__ = []
    __many__table__ = RelationshipEmployee2Build
    # __explain__ = AbstractBuild()

    gov_address_code: Mapped[str] = mapped_column(
        String, server_default="", unique=True
    )
    build_name: Mapped[str] = mapped_column(
        String, nullable=False, comment="Building Name"
    )
    build_no: Mapped[str] = mapped_column(
        String(8), nullable=False, comment="Building Number"
    )

    max_floor: Mapped[int] = mapped_column(
        Integer, server_default="1", nullable=False, comment="Max Floor"
    )
    underground_floor: Mapped[int] = mapped_column(
        Integer, server_default="0", nullable=False, comment="Underground Floor"
    )
    build_date: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True), server_default="1900-01-01"
    )
    decision_period_date: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True),
        server_default="1900-01-01",
        comment="Building annual ordinary meeting period",
    )
    tax_no: Mapped[str] = mapped_column(String(24), server_default="")
    lift_count: Mapped[int] = mapped_column(Integer, server_default="0")
    heating_system: Mapped[bool] = mapped_column(Boolean, server_default="True")
    cooling_system: Mapped[bool] = mapped_column(Boolean, server_default="False")
    hot_water_system: Mapped[bool] = mapped_column(Boolean, server_default="False")
    block_service_man_count: Mapped[int] = mapped_column(Integer, server_default="0")
    security_service_man_count: Mapped[int] = mapped_column(Integer, server_default="0")
    garage_count: Mapped[int] = mapped_column(
        Integer, server_default="0", comment="Garage Count"
    )
    management_room_id: Mapped[int] = mapped_column(
        Integer, nullable=True, comment="Management Room ID"
    )

    site_id: Mapped[int] = mapped_column(ForeignKey("build_sites.id"), nullable=True)
    site_uu_id: Mapped[str] = mapped_column(String, comment="Site UUID", nullable=True)
    address_id: Mapped[int] = mapped_column(ForeignKey("addresses.id"), nullable=False)
    address_uu_id: Mapped[str] = mapped_column(
        String, comment="Address UUID", nullable=False
    )
    build_types_id: Mapped[int] = mapped_column(
        ForeignKey("build_types.id"), nullable=False, comment="Building Type"
    )
    build_types_uu_id: Mapped[str] = mapped_column(String, comment="Building Type UUID")

    parts: Mapped[List["BuildParts"]] = relationship(
        "BuildParts", back_populates="buildings", foreign_keys="BuildParts.build_id"
    )
    decision_books: Mapped[List["BuildDecisionBook"]] = relationship(
        "BuildDecisionBook",
        back_populates="buildings",
        foreign_keys="BuildDecisionBook.build_id",
    )

    # build_ibans: Mapped["BuildIbans"] = relationship(
    #     "BuildIbans", back_populates="building", foreign_keys="BuildIbans.build_id"
    # )
    # areas: Mapped["BuildArea"] = relationship(
    #     "BuildArea", back_populates="buildings", foreign_keys="BuildArea.build_id"
    # )
    # response_companies: Mapped["Companies"] = relationship(
    #     "Companies",
    #     back_populates="response_buildings",
    #     foreign_keys=[response_company_id],
    # )
    # addresses: Mapped[List["Address"]] = relationship(
    #     "Address", back_populates="buildings", foreign_keys=[address_id]
    # )
    # peoples: Mapped["People"] = relationship(
    #     "People", back_populates="buildings", foreign_keys=[people_id]
    # )
    # sites: Mapped["BuildSites"] = relationship(
    #     "BuildSites", back_populates="buildings", foreign_keys=[site_id]
    # )

    __table_args__ = (
        Index("_builds_ndx_00", gov_address_code),
        Index("_builds_ndx_01", build_name, build_no),
        {
            "comment": "Build objects are building that are created for living and store purposes"
        },
    )

    @property
    def management_room(self):
        if management_room := BuildParts.filter_by_one(
            system=True, id=self.management_room_id, build_id=self.id
        ).data:
            return management_room
        return None

    @classmethod
    def create_action(cls, data: InsertBuild, token):
        from databases import Addresses

        data_dict = data.excluded_dump()
        data_dict["address_id"] = None
        if data.address_uu_id:
            official_address = Addresses.filter_one(
                Addresses.uu_id == data.address_uu_id,
            ).data
            data_dict["address_id"] = official_address.id
            data_dict["build_no"] = str(official_address.build_number)
        if not data_dict["address_id"]:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Address is not found in database. Re-enter address record then try again.",
            )
        build_type = BuildTypes.filter_by_one(
            system=True, uu_id=str(data.build_types_uu_id)
        ).data
        data_dict["build_types_id"] = build_type.id
        build_created = cls.find_or_create(**data_dict)
        created_build_relation = cls.__many__table__.find_or_create(
            company_id=token.selected_company.company_id,
            employee_id=token.selected_company.employee_id,
            member_id=build_created.id,
        )
        build_created.save()
        build_created.update(is_confirmed=True)
        build_created.save()
        created_build_relation.update(is_confirmed=True)
        created_build_relation.save()
        return build_created

    @classmethod
    def update_action(cls, data: UpdateBuild, build_uu_id: str, token):
        from databases import Addresses

        print("data_dict", data.dump())
        data_dict = data.excluded_dump()
        if data.address_uu_id:
            official_address = Addresses.filter_one(
                Addresses.uu_id == data.address_uu_id
            ).data
            data_dict["address_id"] = official_address.id if official_address else None
        print("data_dict", data_dict)
        if build_to_update := cls.filter_one(cls.uu_id == build_uu_id).data:
            print("build_to_update", build_to_update.get_dict())
            updated_build = build_to_update.update(**data_dict)
            updated_build.save()
            print("updated_build", updated_build.get_dict())
            return updated_build

    @property
    def top_flat(self):
        max_flat_no = 0
        for part in self.parts:
            if part.part_no > self.max_floor:
                max_flat_no = part.part_no
        return max_flat_no

    @property
    def bottom_flat(self):
        min_flat_no = 0
        for part in self.parts:
            if part.part_no < self.max_floor:
                min_flat_no = part.part_no
        return min_flat_no

    @property
    def human_livable_parts(self) -> tuple:
        parts = list(part for part in self.parts if part.human_livable)
        return parts, len(parts)

    @property
    def livable_part_count(self):
        livable_parts = BuildParts.filter_all(
            BuildParts.build_id == self.id,
            BuildParts.human_livable == True,
        )
        if not livable_parts.data:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="There is no livable part in this building.",
            )
        return livable_parts.count

    @property
    def part_type_count(self):
        building_types = None
        for part in self.parts:
            building_types = {}
            build_type = BuildTypes.filter_by_one(
                system=True, id=part.build_part_type_id
            ).data
            if build_type.type_code in building_types:
                building_types[build_type.type_code]["list"].append(part.part_no)
            else:
                building_types[build_type.type_code] = {"list": [part.part_no]}

            # for key, val in building_types.items():
            #     list_parts = val["list"]
            #     building_types[key] = {
            #         "list": list_parts,
            #         "min": min(list_parts),
            #         "max": max(list_parts),
            #         "count": len(list_parts),
            #     }
        return building_types


class BuildParts(CrudCollection):
    """
    BuildParts class based on declarative_base and BaseMixin via session
    Attentions: Part_no is unique for each building and Every building must have a management section.!!! default no 0
    """

    __tablename__ = "build_parts"
    __exclude__fields__ = []
    __language_model__ = BuildPartsLanguageModel
    __include__fields__ = []
    __enum_list__ = [("part_direction", "Directions", "NN")]

    # https://adres.nvi.gov.tr/VatandasIslemleri/AdresSorgu
    address_gov_code: Mapped[str] = mapped_column(
        String, nullable=False, comment="Goverment Door Code"
    )
    # part_name: Mapped[str] = mapped_column(String(24), server_default="", nullable=False, comment="Part Name")
    part_no: Mapped[int] = mapped_column(
        Integer, server_default="0", nullable=False, comment="Part Number"
    )
    part_level: Mapped[int] = mapped_column(
        Integer, server_default="0", comment="Building Part Level"
    )
    part_code: Mapped[str] = mapped_column(
        String, server_default="", nullable=False, comment="Part Code"
    )
    part_gross_size: Mapped[int] = mapped_column(
        Integer, server_default="0", comment="Part Gross Size"
    )
    part_net_size: Mapped[int] = mapped_column(
        Integer, server_default="0", comment="Part Net Size"
    )
    default_accessory: Mapped[str] = mapped_column(
        Text, server_default="0", comment="Default Accessory"
    )
    human_livable: Mapped[bool] = mapped_column(
        Boolean, server_default="1", comment="Human Livable"
    )
    due_part_key: Mapped[str] = mapped_column(
        String, server_default="", nullable=False, comment="Constant Payment Group"
    )

    build_id: Mapped[int] = mapped_column(
        ForeignKey("build.id"), nullable=False, comment="Building ID"
    )
    build_uu_id: Mapped[str] = mapped_column(
        String, nullable=False, comment="Building UUID"
    )
    part_direction_id: Mapped[int] = mapped_column(
        ForeignKey("api_enum_dropdown.id"), nullable=True
    )
    part_direction_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Part Direction UUID"
    )
    part_type_id: Mapped[int] = mapped_column(
        ForeignKey("build_types.id"), nullable=False, comment="Building Part Type"
    )
    part_type_uu_id: Mapped[str] = mapped_column(
        String, nullable=False, comment="Building Part Type UUID"
    )

    buildings: Mapped["Build"] = relationship(
        "Build", back_populates="parts", foreign_keys=[build_id]
    )

    __table_args__ = (
        Index("build_parts_ndx_01", build_id, part_no, unique=True),
        {"comment": "Part objects that are belong to building objects"},
    )

    @classmethod
    def create_action(cls, data: InsertBuildParts, token):
        from databases import ApiEnumDropdown

        data_dict = data.dump()
        build_from_duty = Build.select_action(
            employee_id=token.selected_company.employee_id,
            filter_expr=[Build.uu_id == data.build_uu_id],
        )
        building = build_from_duty.first()
        if not building:
            raise HTTPException(
                status_code=status.HTTP_406_NOT_ACCEPTABLE,
                detail="This Employee can not reach this building or building uu-id not found in database. "
                "Check with your supervisor.",
            )

        if build_types := BuildTypes.filter_one(
            BuildTypes.uu_id == data.build_part_type_uu_id,
        ).data:
            part_direction = ApiEnumDropdown.get_by_uuid(
                uuid=str(data.part_direction_uu_id)
            )

            data_dict["part_gross_size"] = data.part_gross_size
            data_dict["part_net_size"] = data.part_net_size
            data_dict["part_type_id"] = build_types.id
            data_dict["part_level"] = data.part_level
            data_dict["build_id"] = building.id
            data_dict["part_no"] = data.part_no
            data_dict["part_code"] = (
                f"{build_types.type_code}:{str(data_dict['part_no']).zfill(2)}"
            )
            data_dict["address_gov_code"] = data.address_gov_code
            data_dict["default_accessory"] = data.default_accessory
            data_dict["human_livable"] = bool(data.human_livable)

            data_dict["build_uu_id"] = str(data.build_uu_id)
            data_dict["part_type_id"] = build_types.id
            data_dict["part_type_uu_id"] = str(build_types.uu_id)
            data_dict["part_direction_id"] = part_direction.id
            data_dict["part_direction_uu_id"] = str(part_direction.uu_id)
            # data_dict["part_direction"] = str(data.part_direction_uu_id)

            if not data_dict["part_gross_size"]:
                raise HTTPException(
                    status_code=status.HTTP_406_NOT_ACCEPTABLE,
                    detail="Part Gross Size can not be empty.",
                )

            if not data_dict["part_net_size"]:
                raise HTTPException(
                    status_code=status.HTTP_406_NOT_ACCEPTABLE,
                    detail="Part Net Size can not be empty.",
                )
            pt = int(data_dict["part_net_size"])
            data_dict["due_part_key"] = str(pt + (5 - (pt % 5))) + "M2"
            del data_dict["build_part_type_uu_id"]
            return cls.find_or_create(**data_dict)

        raise HTTPException(
            status_code=status.HTTP_418_IM_A_TEAPOT,
            detail="Build Part can not be created.",
        )

    @property
    def part_name(self):
        if build_type := BuildTypes.filter_by_one(
            system=True, id=self.part_type_id
        ).data:
            return f"{str(build_type.type_name).upper()} : {str(self.part_no).upper()}"
        return f"Undefined:{str(build_type.type_name).upper()}"


class BuildLivingSpace(CrudCollection):
    """
    LivingSpace class based on declarative_base and BaseMixin via session
    Owner or live person = Occupant of the build part
    + Query OR(owner_person_id == person_id, life_person_id == person_id) AND (now(date))
    """

    __tablename__ = "build_living_space"
    __exclude__fields__ = []
    __language_model__ = BuildLivingSpaceLanguageModel
    __include__fields__ = []

    fix_value: Mapped[float] = mapped_column(
        Numeric(20, 6),
        server_default="0",
        comment="Fixed value is deducted from debit.",
    )
    fix_percent: Mapped[float] = mapped_column(
        Numeric(6, 2),
        server_default="0",
        comment="Fixed percent is deducted from debit.",
    )

    agreement_no: Mapped[str] = mapped_column(
        String, server_default="", comment="Agreement No"
    )
    marketing_process: Mapped[bool] = mapped_column(Boolean, server_default="False")
    marketing_layer: Mapped[int] = mapped_column(Integer, server_default="0")

    build_parts_id: Mapped[int] = mapped_column(
        ForeignKey("build_parts.id"),
        nullable=False,
        index=True,
        comment="Build Part ID",
    )
    build_parts_uu_id: Mapped[str] = mapped_column(
        String, nullable=False, comment="Build Part UUID"
    )
    person_id: Mapped[int] = mapped_column(
        ForeignKey("people.id"),
        nullable=False,
        index=True,
        comment="Responsible People ID",
    )
    person_uu_id: Mapped[str] = mapped_column(
        String, nullable=False, comment="Responsible People UUID"
    )
    occupant_type: Mapped[int] = mapped_column(
        ForeignKey("occupant_types.id"),
        nullable=False,
        comment="Occupant Type",
    )
    occupant_type_uu_id: Mapped[str] = mapped_column(
        String, nullable=False, comment="Occupant Type UUID"
    )

    __table_args__ = (
        {"comment": "Living Space inside building parts that are related to people"},
    )

    @classmethod
    def create_action(
        cls,
        data: dict,
        token_dict: Union[EmployeeTokenObject, OccupantTokenObject],
    ):
        from databases import Services, OccupantTypes
        from api_events.events.events.events_bind_modules import (
            ModulesBindOccupantEventMethods,
        )

        if data.get("expiry_starts"):
            data["expiry_starts"] = str(system_arrow.get(data["expiry_starts"]))
        if data.get("expiry_ends"):
            data["expiry_ends"] = str(system_arrow.get(data["expiry_ends"]))
        created_living_space = BuildLivingSpace.find_or_create(**data)
        occupant_type = OccupantTypes.filter_by_one(
            system=True, uu_id=created_living_space.occupant_type_uu_id
        ).data
        related_service = Services.filter_by_one(
            related_responsibility=occupant_type.occupant_code,
        ).data
        if not related_service:
            raise HTTPException(
                status_code=status.HTTP_418_IM_A_TEAPOT,
                detail="Service is not found in database. Re-enter service record then try again.",
            )
        ModulesBindOccupantEventMethods.bind_default_module_for_first_init_occupant(
            build_living_space_id=created_living_space.id,
        )
        created_living_space.save_and_confirm()
        return created_living_space

    @classmethod
    def find_living_from_customer_id(
        cls, customer_id, process_date, add_days: int = 32
    ):
        from api_library.date_time_actions.date_functions import system_arrow

        formatted_date = system_arrow.get(str(process_date))
        living_spaces = cls.filter_all(
            or_(
                cls.owner_person_id == customer_id,
                cls.life_person_id == customer_id,
            ),
            cls.start_date < formatted_date - timedelta(days=add_days),
            cls.stop_date > formatted_date + timedelta(days=add_days),
        )
        return living_spaces.data, living_spaces.count


class BuildManagement(CrudCollection):

    __tablename__ = "build_management"
    __exclude__fields__ = []
    __language_model__ = BuildManagementLanguageModel

    discounted_percentage: Mapped[float] = mapped_column(
        Numeric(6, 2), server_default="0.00"
    )  # %22
    discounted_price: Mapped[float] = mapped_column(
        Numeric(20, 2), server_default="0.00"
    )  # Normal: 78.00 TL
    calculated_price: Mapped[float] = mapped_column(
        Numeric(20, 2), server_default="0.00"
    )  # sana düz 75.00 TL yapar

    occupant_type: Mapped[int] = mapped_column(
        ForeignKey("occupant_types.id"),
        nullable=False,
        comment="Occupant Type",
    )
    occupant_type_uu_id: Mapped[str] = mapped_column(
        String, nullable=False, comment="Occupant Type UUID"
    )
    build_id: Mapped[int] = mapped_column(
        ForeignKey("build.id"), nullable=False, comment="Building ID"
    )
    build_uu_id: Mapped[str] = mapped_column(
        String, nullable=False, comment="Building UUID"
    )
    build_parts_id: Mapped[int] = mapped_column(
        ForeignKey("build_parts.id"),
        nullable=False,
        index=True,
        comment="Build Part ID",
    )
    build_parts_uu_id: Mapped[str] = mapped_column(
        String, nullable=False, comment="Build Part UUID"
    )

    __table_args__ = (
        Index(
            "build_management_ndx_00",
            build_parts_id,
            occupant_type,
            "expiry_starts",
            unique=True,
        ),
        {"comment": "Management of the building parts that are related to people"},
    )


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

    __tablename__ = "build_area"
    __exclude__fields__ = []
    __language_model__ = BuildAreaLanguageModel

    area_name: Mapped[str] = mapped_column(String, server_default="")
    area_code: Mapped[str] = mapped_column(String, server_default="")
    area_type: Mapped[str] = mapped_column(String, server_default="GREEN")
    area_direction: Mapped[str] = mapped_column(String(2), server_default="NN")
    area_gross_size: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
    area_net_size: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
    width = mapped_column(Integer, server_default="0")
    size = mapped_column(Integer, server_default="0")

    build_id: Mapped[int] = mapped_column(ForeignKey("build.id"))
    build_uu_id: Mapped[str] = mapped_column(String, comment="Building UUID")
    part_type_id: Mapped[int] = mapped_column(
        ForeignKey("build_types.id"), nullable=True, comment="Building Part Type"
    )
    part_type_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Building Part Type UUID"
    )

    # buildings: Mapped["Build"] = relationship(
    #     "Build", back_populates="areas", foreign_keys=[build_id]
    # )

    _table_args_ = (
        Index("_edm_build_parts_area_ndx_00", build_id, area_code, unique=True),
    )


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

    __tablename__ = "build_sites"
    __exclude__fields__ = []
    __language_model__ = BuildSitesLanguageModel
    __include__fields__ = []

    site_name: Mapped[str] = mapped_column(String(24), nullable=False)
    site_no: Mapped[str] = mapped_column(String(8), nullable=False)

    address_id: Mapped[int] = mapped_column(ForeignKey("addresses.id"))
    address_uu_id: Mapped[str] = mapped_column(String, comment="Address UUID")

    # addresses: Mapped["Address"] = relationship(
    #     "Address", back_populates="site", foreign_keys=[address_id]
    # )
    # buildings: Mapped["Build"] = relationship(
    #     "Build", back_populates="sites", foreign_keys="Build.site_id"
    # )

    __table_args__ = (
        Index("_sites_ndx_01", site_no, site_name),
        {"comment": "Sites that groups building objets"},
    )


class BuildCompaniesProviding(CrudCollection):
    """ """

    __tablename__ = "build_companies_providing"
    __exclude__fields__ = []
    __language_model__ = BuildCompaniesProvidingLanguageModel
    __include__fields__ = []

    build_id = mapped_column(
        ForeignKey("build.id"), nullable=False, comment="Building ID"
    )
    build_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Providing UUID"
    )
    company_id: Mapped[int] = mapped_column(ForeignKey("companies.id"))
    company_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Providing UUID"
    )
    provide_id: Mapped[int] = mapped_column(
        ForeignKey("api_enum_dropdown.id"), nullable=True
    )
    provide_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Providing UUID"
    )
    contract_id: Mapped[int] = mapped_column(
        Integer, ForeignKey("companies.id"), nullable=True
    )

    __table_args__ = (
        Index(
            "_build_companies_providing_ndx_00",
            build_id,
            company_id,
            provide_id,
            unique=True,
        ),
        {"comment": "Companies providing services for building"},
    )


class BuildPersonProviding(CrudCollection):
    """ """

    __tablename__ = "build_person_providing"
    __exclude__fields__ = []
    __language_model__ = BuildPersonProvidingLanguageModel
    __include__fields__ = []

    build_id = mapped_column(
        ForeignKey("build.id"), nullable=False, comment="Building ID"
    )
    build_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Providing UUID"
    )
    people_id: Mapped[int] = mapped_column(ForeignKey("people.id"))
    people_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="People UUID"
    )
    provide_id: Mapped[int] = mapped_column(
        ForeignKey("api_enum_dropdown.id"), nullable=True
    )
    provide_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Providing UUID"
    )
    contract_id: Mapped[int] = mapped_column(
        Integer, ForeignKey("companies.id"), nullable=True
    )

    __table_args__ = (
        Index(
            "_build_person_providing_ndx_00",
            build_id,
            people_id,
            provide_id,
            unique=True,
        ),
        {"comment": "People providing services for building"},
    )
