"""

    AUTHOR:

        Khushal P Soonderji

    DATE:

        Monday, 6th Jan., 2024.

    OBJECTIVE:

        To provide a data model for describing the instruments supported by Zerodha Kite.

    REFERENCES:

        N/A

    DOWNLOADS:

        N/A

"""


#   *****************************************************************************************************************
#  *****                                                                                                          ****
# ***                                                   IMPORT                                                      ***
#  *****                                                                                                          ****
#   *****************************************************************************************************************


# To make sibling directories accessible for imports:
import sys
sys.path.append(".")
sys.path.append("..")

# For system-level activities:
import io

# For making data behaviour_models:
from pydantic import BaseModel, Field, field_validator, model_validator, AwareDatetime
from typing import Optional, Literal, Union, Dict, List, Any

# Related to Google:
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials

# My utils:
from utils_v2.string import json
from utils_v2.string import regex
from utils_v2.date_time import date_time

# To work with date and time:
import datetime
import dateparser

# For working with tabulated data:
import pandas as pd

# To make API calls:
import httpx


#   *****************************************************************************************************************
#  *****                                                                                                          ****
# ***                                           MACROS / ONE-TIME INIT                                              ***
#  *****                                                                                                          ****
#   *****************************************************************************************************************


# --- Nothing Yet


#   *****************************************************************************************************************
#  *****                                                                                                          ****
# ***                                                VARIABLES                                                      ***
#  *****                                                                                                          ****
#   *****************************************************************************************************************


# --- Nothing Yet


#   *****************************************************************************************************************
#  *****                                                                                                          ****
# ***                                                  FUNCTIONS                                                    ***
#  *****                                                                                                          ****
#   *****************************************************************************************************************


class ZerodhaKiteInstrument(BaseModel):

    instrumentToken: int = Field(
        description = "The token by which Zerodha recognizes this instrument.",
        frozen = True,
        alias = "instrument_token"
    )

    exchangeToken: int | str = Field(
        description = "The way the exchange recognizes this instrument.",
        frozen = True,
        alias = "exchange_token"
    )

    symbol: str | None = Field(
        description = "The trading symbol pf this instrument.",
        frozen = True,
        alias = "tradingsymbol"
    )

    name: str | None = Field(
        description = "The name of the company (for stocks), or the trading symbol (for derivatives).",
        frozen = True,
        alias = "name"
    )

    ltp: float | int = Field(
        description = "The last price at which this instrument was traded.",
        frozen = True,
        alias = "last_price"
    )

    expiry: str | None = Field(
        description = "The expiry date (if derivative).",
        frozen = True,
        alias = "expiry"
    )

    strike: float | int | None = Field(
        description = "The strike price (if option).",
        frozen = True,
        alias = "strike"
    )

    tickSize: float | int = Field(
        description = "The minimum value by which the price must move to change.",
        frozen = True,
        alias = "tick_size"
    )

    lotSize: float | int = Field(
        description = "The minimum trading qty. (if derivative).",
        frozen = True,
        alias = "lot_size"
    )

    segment: str = Field(
        description = "The segment that the instrument belongs to.",
        frozen = True,
        alias = "segment"
    )

    instrumentType: str = Field(
        description = "the subtype of the 'segment'.",
        frozen = True,
        alias = "instrument_type"
    )

    exchange: str = Field(
        description = "The exchange on which this instrument is traded.",
        alias = "exchange"
    )

    # ┏┓    ┏•
    # ┃ ┏┓┏┓╋┓┏┓
    # ┗┛┗┛┛┗┛┗┗┫
    #          ┛

    class Config:
        extra = "ignore"
        populate_by_name = True

    # ┓┏  ┓• ┓   •
    # ┃┃┏┓┃┓┏┫┏┓╋┓┏┓┏┓
    # ┗┛┗┻┗┗┗┻┗┻┗┗┗┛┛┗

    pass

    # ┏┓           •
    # ┃┃┏┓┏┓┏┓┏┓┏┓╋┓┏┓┏
    # ┣┛┛ ┗┛┣┛┗ ┛ ┗┗┗ ┛
    #       ┛

    pass

    # ┏┓           ┏┓
    # ┃ ┓┏┏╋┏┓┏┳┓  ┣ ┓┏┏┓┏┏
    # ┗┛┗┻┛┗┗┛┛┗┗  ┻ ┗┻┛┗┗┛

    def __str__(self):
        return f"{self.exchange}:{self.symbol}"

    def __repr__(self):
        return str(self)

    @staticmethod
    def from_api_data(api_data: bytes | io.BytesIO | pd.DataFrame | List[dict] | dict) -> "ZerodhaKiteInstrument":

        # Convert the input to a list of dicts:
        if isinstance(api_data, bytes): api_data = io.BytesIO(api_data)
        if isinstance(api_data, io.BytesIO): api_data = pd.read_csv(api_data)
        if isinstance(api_data, pd.DataFrame):
            api_data = api_data.map(lambda x: None if pd.isna(x) else x)
            api_data = api_data.to_dict(orient = "records")
        if isinstance(api_data, dict): api_data = [api_data]

        # Model the records and return the values:
        modelled_instruments = [ZerodhaKiteInstrument(**instrument) for instrument in api_data]
        return modelled_instruments


#   *****************************************************************************************************************
#  *****                                                                                                          ****
# ***                                               MAIN PROGRAM                                                    ***
#  *****                                                                                                          ****
#   *****************************************************************************************************************


if __name__ == "__main__":

    pass
