"""Custom Indicator Models"""
__docformat__ = "numpy"

import logging
from typing import Any, Tuple

import pandas as pd

from openbb_terminal.decorators import log_start_end
from openbb_terminal.rich_config import console
from openbb_terminal.common.technical_analysis import ta_helpers

logger = logging.getLogger(__name__)


@log_start_end(log=logger)
def calculate_fib_levels(
    data: pd.DataFrame,
    limit: int = 120,
    start_date: Any = None,
    end_date: Any = None,
) -> Tuple[pd.DataFrame, pd.Timestamp, pd.Timestamp, float, float]:
    """Calculate Fibonacci levels

    Parameters
    ----------
    data : pd.DataFrame
        Dataframe of prices
    limit : int
        Days to look back for retracement
    start_date : Any
        Custom start date for retracement
    end_date : Any
        Custom end date for retracement

    Returns
    -------
    df : pd.DataFrame
        Dataframe of fib levels
    min_date: pd.Timestamp
        Date of min point
    max_date: pd.Timestamp:
        Date of max point
    min_pr: float
        Price at min point
    max_pr: float
        Price at max point
    """
    close_col = ta_helpers.check_columns(data, high=False, low=False)
    if close_col is None:
        return pd.DataFrame(), pd.Timestamp(), pd.Timestamp(), 0, 0
    if start_date and end_date:
        if start_date not in data.index:
            date0 = data.index[data.index.get_loc(start_date, method="nearest")]
            console.print(f"Start date not in data.  Using nearest: {date0}")
        else:
            date0 = start_date
        if end_date not in data.index:
            date1 = data.index[data.index.get_loc(end_date, method="nearest")]
            console.print(f"End date not in data.  Using nearest: {date1}")
        else:
            date1 = end_date

        data0 = data.loc[date0, close_col]
        data1 = data.loc[date1, close_col]

        min_pr = min(data0, data1)
        max_pr = max(data0, data1)

        if min_pr == data0:
            min_date = date0
            max_date = date1
        else:
            min_date = date1
            max_date = date0
    else:
        data_to_use = data.iloc[limit:][close_col]

        min_pr = data_to_use.min()
        min_date = data_to_use.idxmin()
        max_pr = data_to_use.max()
        max_date = data_to_use.idxmax()

    fib_levels = [0, 0.235, 0.382, 0.5, 0.618, 0.65, 1]
    price_dif = max_pr - min_pr

    levels = [round(max_pr - price_dif * f_lev, 2) for f_lev in fib_levels]

    df = pd.DataFrame()
    df["Level"] = fib_levels
    df["Level"] = df["Level"].apply(lambda x: str(x * 100) + "%")
    df["Price"] = levels

    return df, min_date, max_date, min_pr, max_pr
