from schemas.base_imports import (
    CrudCollection,
    String,
    Integer,
    Boolean,
    ForeignKey,
    Index,
    TIMESTAMP,
    Numeric,
    SmallInteger,
    mapped_column,
    Mapped,
)


class AccountBooks(CrudCollection):

    __tablename__ = "account_books"
    __exclude__fields__ = []

    country: Mapped[str] = mapped_column(String, nullable=False)
    branch_type: Mapped[int] = mapped_column(SmallInteger, server_default="0")

    company_id: Mapped[int] = mapped_column(ForeignKey("companies.id"), nullable=False)
    company_uu_id: Mapped[str] = mapped_column(String, nullable=False)
    branch_id: Mapped[int] = mapped_column(ForeignKey("companies.id"))
    branch_uu_id: Mapped[str] = mapped_column(String, comment="Branch UU ID")

    __table_args__ = (
        Index("account_companies_book_ndx_00", company_id, "expiry_starts"),
        {"comment": "Account Book Information"},
    )


class AccountCodes(CrudCollection):

    __tablename__ = "account_codes"
    __exclude__fields__ = []

    account_code: Mapped[str] = mapped_column(
        String(48), nullable=False, comment="Account Code"
    )
    comment_line: Mapped[str] = mapped_column(
        String(128), nullable=False, comment="Comment Line"
    )

    is_receive_or_debit: Mapped[bool] = mapped_column(Boolean)
    product_id: Mapped[int] = mapped_column(Integer, server_default="0")
    nvi_id: Mapped[str] = mapped_column(String(48), server_default="")
    status_id: Mapped[int] = mapped_column(SmallInteger, server_default="0")
    account_code_seperator: Mapped[str] = mapped_column(String(1), server_default=".")

    system_id: Mapped[int] = mapped_column(SmallInteger, server_default="0")
    locked: Mapped[int] = mapped_column(SmallInteger, server_default="0")

    company_id: Mapped[int] = mapped_column(ForeignKey("companies.id"))
    company_uu_id: Mapped[str] = mapped_column(
        String, nullable=False, comment="Company UU ID"
    )
    customer_id: Mapped[int] = mapped_column(ForeignKey("companies.id"))
    customer_uu_id: Mapped[str] = mapped_column(
        String, nullable=False, comment="Customer UU ID"
    )
    person_id: Mapped[int] = mapped_column(ForeignKey("people.id"))
    person_uu_id: Mapped[str] = mapped_column(
        String, nullable=False, comment="Person UU ID"
    )

    __table_args__ = ({"comment": "Account Code Information"},)


class AccountCodeParser(CrudCollection):

    __tablename__ = "account_code_parser"
    __exclude__fields__ = []

    account_code_1: Mapped[str] = mapped_column(String, nullable=False, comment="Order")
    account_code_2: Mapped[str] = mapped_column(String, nullable=False, comment="Order")
    account_code_3: Mapped[str] = mapped_column(String, nullable=False, comment="Order")
    account_code_4: Mapped[str] = mapped_column(String, server_default="")
    account_code_5: Mapped[str] = mapped_column(String, server_default="")
    account_code_6: Mapped[str] = mapped_column(String, server_default="")

    account_code_id: Mapped[int] = mapped_column(
        ForeignKey("account_codes.id"), nullable=False
    )
    account_code_uu_id: Mapped[str] = mapped_column(
        String, nullable=False, comment="Account Code UU ID"
    )

    __table_args__ = (
        Index("_account_code_parser_ndx_00", account_code_id),
        {"comment": "Account Code Parser Information"},
    )

    @property
    def get_account_code(self):
        return f"{self.account_codes.account_code_seperator}".join(
            [
                getattr(self, f"account_code_{i}")
                for i in range(1, 7)
                if getattr(self, f"account_code_{i}")
            ]
        )


class AccountMaster(CrudCollection):
    """
    AccountCodes class based on declarative_base and CrudCollection via session
    """

    __tablename__ = "account_master"
    __exclude__fields__ = []

    doc_date: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True), nullable=False, comment="Document Date"
    )
    plug_type: Mapped[str] = mapped_column(String, nullable=False, comment="Plug Type")
    plug_number: Mapped[int] = mapped_column(
        Integer, nullable=False, comment="Plug Number"
    )

    special_code: Mapped[str] = mapped_column(String(12), server_default="")
    authorization_code: Mapped[str] = mapped_column(String(12), server_default="")

    doc_code: Mapped[str] = mapped_column(String(12), server_default="")
    doc_type: Mapped[int] = mapped_column(SmallInteger, server_default="0")

    comment_line1: Mapped[str] = mapped_column(String, server_default="")
    comment_line2: Mapped[str] = mapped_column(String, server_default="")
    comment_line3: Mapped[str] = mapped_column(String, server_default="")
    comment_line4: Mapped[str] = mapped_column(String, server_default="")
    comment_line5: Mapped[str] = mapped_column(String, server_default="")
    comment_line6: Mapped[str] = mapped_column(String, server_default="")
    project_code: Mapped[str] = mapped_column(String(12), server_default="")
    module_no: Mapped[str] = mapped_column(String, server_default="")
    journal_no: Mapped[int] = mapped_column(Integer, server_default="0")

    status_id: Mapped[int] = mapped_column(SmallInteger, server_default="0")
    canceled: Mapped[bool] = mapped_column(Boolean, server_default="0")
    print_count: Mapped[int] = mapped_column(SmallInteger, server_default="0")
    total_active: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
    total_passive: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
    total_active_1: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
    total_passive_1: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
    total_active_2: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
    total_passive_2: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
    total_active_3: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
    total_passive_3: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
    total_active_4: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
    total_passive_4: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
    cross_ref: Mapped[int] = mapped_column(Integer, server_default="0")
    data_center_id: Mapped[str] = mapped_column(String, server_default="")
    data_center_rec_num: Mapped[int] = mapped_column(Integer, server_default="0")

    account_header_id: Mapped[int] = mapped_column(
        ForeignKey("account_books.id"), nullable=False
    )
    account_header_uu_id: Mapped[str] = mapped_column(
        String, nullable=False, comment="Account Header UU ID"
    )
    project_item_id: Mapped[int] = mapped_column(
        ForeignKey("build_decision_book_projects.id")
    )
    project_item_uu_id: Mapped[str] = mapped_column(
        String, comment="Project Item UU ID"
    )
    department_id: Mapped[int] = mapped_column(ForeignKey("departments.id"))
    department_uu_id: Mapped[str] = mapped_column(String, comment="Department UU ID")

    __table_args__ = (
        Index("_account_master_ndx_00", doc_date, account_header_id),
        {"comment": "Account Master Information"},
    )


class AccountDetail(CrudCollection):
    """
    AccountCodes class based on declarative_base and CrudCollection via session
    """

    __tablename__ = "account_detail"
    __exclude__fields__ = []
    __enum_list__ = [("plug_type", "AccountingReceiptTypes", "M")]

    doc_date: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True), nullable=False, comment="Document Date"
    )
    line_no: Mapped[int] = mapped_column(
        SmallInteger, nullable=False, comment="Line Number"
    )
    receive_debit: Mapped[str] = mapped_column(
        String(1), nullable=False, comment="Receive Debit"
    )
    debit: Mapped[float] = mapped_column(
        Numeric(20, 6), nullable=False, comment="Debit"
    )

    department: Mapped[str] = mapped_column(String(24), server_default="")
    special_code: Mapped[str] = mapped_column(String(12), server_default="")
    account_ref: Mapped[int] = mapped_column(Integer, server_default="0")
    account_fiche_ref: Mapped[int] = mapped_column(Integer, server_default="0")
    center_ref: Mapped[int] = mapped_column(Integer, server_default="0")
    general_code: Mapped[str] = mapped_column(String(32), server_default="")
    credit: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
    currency_type: Mapped[str] = mapped_column(String(4), server_default="TL")
    exchange_rate: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
    debit_cur: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
    credit_cur: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
    discount_cur: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
    amount: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
    cross_account_code: Mapped[float] = mapped_column(String(32), server_default="")
    inf_index: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
    not_inflated: Mapped[int] = mapped_column(SmallInteger, server_default="0")
    not_calculated: Mapped[int] = mapped_column(SmallInteger, server_default="0")
    comment_line1: Mapped[str] = mapped_column(String(64), server_default="")
    comment_line2: Mapped[str] = mapped_column(String(64), server_default="")
    comment_line3: Mapped[str] = mapped_column(String(64), server_default="")
    comment_line4: Mapped[str] = mapped_column(String(64), server_default="")
    comment_line5: Mapped[str] = mapped_column(String(64), server_default="")
    comment_line6: Mapped[str] = mapped_column(String(64), server_default="")
    owner_acc_ref: Mapped[int] = mapped_column(Integer, server_default="0")
    from_where: Mapped[int] = mapped_column(Integer, server_default="0")
    orj_eid: Mapped[int] = mapped_column(Integer, server_default="0")
    canceled: Mapped[int] = mapped_column(SmallInteger, server_default="0")
    cross_ref: Mapped[int] = mapped_column(Integer, server_default="0")
    data_center_id: Mapped[str] = mapped_column(String, server_default="")
    data_center_rec_num: Mapped[int] = mapped_column(Integer, server_default="0")
    status_id: Mapped[int] = mapped_column(SmallInteger, server_default="0")

    plug_type_id: Mapped[int] = mapped_column(
        ForeignKey("api_enum_dropdown.id"), nullable=True
    )
    plug_type_uu_id = mapped_column(String, nullable=False, comment="Plug Type UU ID")
    account_header_id: Mapped[int] = mapped_column(
        ForeignKey("account_books.id"), nullable=False
    )
    account_header_uu_id: Mapped[str] = mapped_column(
        String, nullable=False, comment="Account Header UU ID"
    )
    account_code_id: Mapped[int] = mapped_column(
        ForeignKey("account_codes.id"), nullable=False
    )
    account_code_uu_id: Mapped[str] = mapped_column(
        String, nullable=False, comment="Account Code UU ID"
    )
    account_master_id: Mapped[int] = mapped_column(
        ForeignKey("account_master.id"), nullable=False
    )
    account_master_uu_id: Mapped[str] = mapped_column(
        String, nullable=False, comment="Account Master UU ID"
    )
    project_id: Mapped[int] = mapped_column(
        ForeignKey("build_decision_book_projects.id")
    )
    project_uu_id: Mapped[str] = mapped_column(String, comment="Project UU ID")

    __table_args__ = (
        Index(
            "_account_detail_ndx_00",
            account_master_id,
            doc_date,
            line_no,
            account_header_id,
            unique=True,
        ),
        {"comment": "Account Detail Information"},
    )


class AccountRecordExchanges(CrudCollection):

    __tablename__ = "account_record_exchanges"
    __exclude__fields__ = []

    are_currency: Mapped[str] = mapped_column(
        String(5), nullable=False, comment="Unit of Currency"
    )
    are_exchange_rate: Mapped[float] = mapped_column(
        Numeric(18, 6), nullable=False, server_default="1"
    )
    usd_exchange_rate_value: Mapped[float] = mapped_column(
        Numeric(18, 6),
        nullable=True,
        server_default="0",
        comment="It will be written by multiplying the usd exchange rate with the current value result.",
    )
    eur_exchange_rate_value: Mapped[float] = mapped_column(
        Numeric(18, 6),
        nullable=True,
        server_default="0",
        comment="It will be written by multiplying the eur exchange rate with the current value result.",
    )
    gbp_exchange_rate_value: Mapped[float] = mapped_column(
        Numeric(18, 6),
        nullable=True,
        server_default="0",
        comment="It will be written by multiplying the gpd exchange rate with the current value result.",
    )
    cny_exchange_rate_value: Mapped[float] = mapped_column(
        Numeric(18, 6),
        nullable=True,
        server_default="0",
        comment="It will be written by multiplying the cny exchange rate with the current value result.",
    )

    account_records_id: Mapped[int] = mapped_column(ForeignKey("account_records.id"))
    account_records_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Account Record UU ID"
    )

    __table_args__ = (
        Index("_account_record_exchanges_ndx_00", account_records_id),
        {"comment": "Account Record Exchanges Information"},
    )


class AccountRecords(CrudCollection):
    """
    build_decision_book_id = kaydın sorumlu olduğu karar defteri
    send_company_id = kaydı gönderen firma, send_person_id = gönderen kişi
    customer_id = sorumlu kullanıcı bilgisi, company_id = sorumlu firma
    """

    __tablename__ = "account_records"
    __exclude__fields__ = []
    __enum_list__ = [
        ("receive_debit", "DebitTypes", "D"),
        ("budget_type", "BudgetType", "B"),
    ]

    iban: Mapped[str] = mapped_column(
        String(64), nullable=False, comment="IBAN Number of Bank"
    )
    bank_date: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True), nullable=False, comment="Bank Transaction Date"
    )

    currency_value: Mapped[float] = mapped_column(
        Numeric(20, 6), nullable=False, comment="Currency Value"
    )
    bank_balance: Mapped[float] = mapped_column(
        Numeric(20, 6), nullable=False, comment="Bank Balance"
    )
    currency: Mapped[str] = mapped_column(
        String(5), nullable=False, comment="Unit of Currency"
    )
    additional_balance: Mapped[float] = mapped_column(
        Numeric(20, 6), nullable=False, comment="Additional Balance"
    )
    channel_branch: Mapped[str] = mapped_column(
        String(120), nullable=False, comment="Branch Bank"
    )
    process_name: Mapped[str] = mapped_column(
        String, nullable=False, comment="Bank Process Type Name"
    )
    process_type: Mapped[str] = mapped_column(
        String, nullable=False, comment="Bank Process Type"
    )
    process_comment: Mapped[str] = mapped_column(
        String, nullable=False, comment="Transaction Record Comment"
    )
    process_garbage: Mapped[str] = mapped_column(
        String, nullable=True, comment="Transaction Record Garbage"
    )
    bank_reference_code: Mapped[str] = mapped_column(
        String, nullable=False, comment="Bank Reference Code"
    )

    add_comment_note: Mapped[str] = mapped_column(String, server_default="")
    is_receipt_mail_send: Mapped[bool] = mapped_column(Boolean, server_default="0")
    found_from = mapped_column(String, server_default="")
    similarity: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")
    remainder_balance: Mapped[float] = mapped_column(Numeric(20, 6), server_default="0")

    bank_date_y: Mapped[int] = mapped_column(Integer)
    bank_date_m: Mapped[int] = mapped_column(SmallInteger)
    bank_date_w: Mapped[int] = mapped_column(SmallInteger)
    bank_date_d: Mapped[int] = mapped_column(SmallInteger)

    approving_accounting_record: Mapped[bool] = mapped_column(
        Boolean, server_default="0"
    )
    accounting_receipt_date: Mapped[TIMESTAMP] = mapped_column(
        TIMESTAMP(timezone=True), server_default="1900-01-01 00:00:00"
    )
    accounting_receipt_number: Mapped[int] = mapped_column(Integer, server_default="0")
    status_id: Mapped[int] = mapped_column(SmallInteger, server_default="0")

    approved_record: Mapped[bool] = mapped_column(Boolean, server_default="0")
    import_file_name: Mapped[str] = mapped_column(
        String, nullable=True, comment="XLS Key"
    )

    receive_debit: Mapped[int] = mapped_column(
        ForeignKey("api_enum_dropdown.id"), nullable=True
    )
    receive_debit_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Debit UU ID"
    )
    budget_type: Mapped[int] = mapped_column(
        ForeignKey("api_enum_dropdown.id"), nullable=True
    )
    budget_type_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Budget Type UU ID"
    )
    company_id: Mapped[int] = mapped_column(ForeignKey("companies.id"), nullable=True)
    company_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Company UU ID"
    )
    send_company_id: Mapped[int] = mapped_column(
        ForeignKey("companies.id"), nullable=True
    )
    send_company_uu_id = mapped_column(
        String, nullable=True, comment="Send Company UU ID"
    )

    send_person_id: Mapped[int] = mapped_column(ForeignKey("people.id"), nullable=True)
    send_person_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Send Person UU ID"
    )
    approving_accounting_person: Mapped[int] = mapped_column(
        ForeignKey("people.id"), nullable=True
    )
    approving_accounting_person_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Approving Accounting Person UU ID"
    )

    living_space_id: Mapped[int] = mapped_column(
        ForeignKey("build_living_space.id"), nullable=True
    )
    living_space_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Living Space UU ID"
    )
    customer_id: Mapped[int] = mapped_column(ForeignKey("people.id"), nullable=True)
    customer_uu_id = mapped_column(String, nullable=True, comment="Customer UU ID")

    build_id: Mapped[int] = mapped_column(ForeignKey("build.id"), nullable=True)
    build_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Build UU ID"
    )
    build_parts_id: Mapped[int] = mapped_column(
        ForeignKey("build_parts.id"), nullable=True
    )
    build_parts_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Build Parts UU ID"
    )
    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="Build Decision Book UU ID"
    )

    __table_args__ = (
        Index("_budget_records_ndx_00", is_receipt_mail_send, bank_date),
        Index(
            "_budget_records_ndx_01",
            iban,
            bank_date,
            bank_reference_code,
            bank_balance,
            unique=True,
        ),
        Index("_budget_records_ndx_02", status_id, bank_date),
        {
            "comment": "Bank Records that are related to building and financial transactions"
        },
    )

    # def payment_budget_record_close(self):
    #     from database_sql_models import (
    #         DecisionBookProjectPaymentsMaster,
    #         ApiEnumDropdown,
    #         BuildDecisionBook,
    #         BuildDecisionBookPaymentsMaster,
    #     )
    #
    #     budget_record = self
    #     if self.receive_debit == ApiEnumDropdown.uuid_of_enum(
    #         enum_class="DebitTypes", key="R"
    #     ):
    #         print(
    #             "This record is not debit. Debit:",
    #             self.receive_debit,
    #             "DebitTypes.R.name",
    #             # str(DebitTypes.R.name),
    #         )
    #         return
    #     if abs(budget_record.currency_value + budget_record.remainder_balance) > 0:
    #         payment_dict = {
    #             "budget_records_id": self.id,
    #             "build_decision_book_id": budget_record.build_decision_book_id,
    #             "build_parts_id": budget_record.build_parts_id,
    #             "start_date": budget_record.bank_date,
    #             "paid_value": budget_record.currency_value
    #             - budget_record.remainder_balance,
    #             "is_all": False,
    #         }
    #         (paid_value, start_paid_value, balance) = (
    #             float(budget_record.currency_value - budget_record.remainder_balance),
    #             float(budget_record.currency_value - budget_record.remainder_balance),
    #             float(budget_record.remainder_balance),
    #         )
    #         print(
    #             "self.id",
    #             self.id,
    #             "paid_value",
    #             paid_value,
    #             "start_paid_value",
    #             start_paid_value,
    #             "balance",
    #             balance,
    #             self.receive_debit,
    #         )
    #
    #         if not BuildDecisionBook.find_one(
    #             id=payment_dict["build_decision_book_id"]
    #         ):
    #             return paid_value
    #
    #         if budget_record.replication_id == 55:
    #             if paid_value > 0:
    #                 payment_dict["dues_type"] = ApiEnumDropdown.uuid_of_enum(
    #                     enum_class="BuildDuesTypes", key="L"
    #                 )
    #                 paid_value = (
    #                     DecisionBookProjectPaymentsMaster.pay_law_and_ren_of_build_part(
    #                         **payment_dict
    #                     )
    #                 )
    #                 print("dues_type", payment_dict["dues_type"], paid_value)
    #             if paid_value > 0:
    #                 payment_dict.pop("dues_type", None)
    #                 paid_value = BuildDecisionBookPaymentsMaster.pay_dues_of_build_part(
    #                     **payment_dict
    #                 )
    #                 print("dues_type", None, paid_value)
    #             if paid_value > 0:
    #                 payment_dict["dues_type"] = ApiEnumDropdown.uuid_of_enum(
    #                     enum_class="BuildDuesTypes", key="R"
    #                 )
    #                 paid_value = (
    #                     DecisionBookProjectPaymentsMaster.pay_law_and_ren_of_build_part(
    #                         **payment_dict
    #                     )
    #                 )
    #                 print("dues_type", payment_dict["dues_type"], paid_value)
    #             payment_dict["is_all"] = True
    #             if paid_value > 0:
    #                 payment_dict["dues_type"] = ApiEnumDropdown.uuid_of_enum(
    #                     enum_class="BuildDuesTypes", key="L"
    #                 )
    #                 paid_value = (
    #                     DecisionBookProjectPaymentsMaster.pay_law_and_ren_of_build_part(
    #                         **payment_dict
    #                     )
    #                 )
    #                 print("is all dues_type", payment_dict["dues_type"], paid_value)
    #             if paid_value > 0:
    #                 payment_dict.pop("dues_type", None)
    #                 paid_value = BuildDecisionBookPaymentsMaster.pay_dues_of_build_part(
    #                     **payment_dict
    #                 )
    #                 print("is all dues_type", None, paid_value)
    #             if paid_value > 0:
    #                 payment_dict["dues_type"] = ApiEnumDropdown.uuid_of_enum(
    #                     enum_class="BuildDuesTypes", key="R"
    #                 )
    #                 paid_value = (
    #                     DecisionBookProjectPaymentsMaster.pay_law_and_ren_of_build_part(
    #                         **payment_dict
    #                     )
    #                 )
    #                 print("is all dues_type", payment_dict["dues_type"], paid_value)
