import logging
import random
import readline
import rlcompleter
from code import InteractiveConsole
from os.path import expanduser
from pathlib import Path
from typing import Dict, List

import click
import pandas as pd

from moneywiz_api.cli.helpers import ShellHelper
from moneywiz_api.moneywiz_api import MoneywizApi


def get_default_path() -> Path:
    return Path(
        expanduser(
            "~/Library/Containers/com.moneywiz.personalfinance/Data/Documents/.AppData/ipadMoneyWiz.sqlite"
        )
    )


@click.command()
@click.argument(
    "DB_FILE_PATH",
    type=click.Path(writable=False, readable=True, exists=True),
    default=get_default_path(),
)
@click.option(
    "-d",
    "--demo-dump",
    is_flag=True,
    help="Dumy some demo data",
)
@click.option(
    "--log-level",
    default="INFO",
    type=click.Choice(
        ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], case_sensitive=False
    ),
    help="Set the logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)",
)
def main(db_file_path, demo_dump, log_level):
    """
    Interactive shell to access MoneyWiz (Read-only)
    """

    # Configure logging level
    numeric_level = getattr(logging, log_level.upper(), None)
    if not isinstance(numeric_level, int):
        raise ValueError(f"Invalid log level: {log_level}")

    logging.basicConfig(level=numeric_level)

    root_logger = logging.getLogger()
    root_logger.setLevel(numeric_level)

    moneywiz_api = MoneywizApi(db_file_path)

    (
        accessor,
        account_manager,
        payee_manager,
        category_manager,
        transaction_manager,
        investment_holding_manager,
        tag_manager,
    ) = (
        moneywiz_api.accessor,
        moneywiz_api.account_manager,
        moneywiz_api.payee_manager,
        moneywiz_api.category_manager,
        moneywiz_api.transaction_manager,
        moneywiz_api.investment_holding_manager,
        moneywiz_api.tag_manager,
    )

    helper = ShellHelper(moneywiz_api)

    names: Dict[str, str] = {
        f"{moneywiz_api=}".split("=")[0]: "MoneyWiz API",
        f"{accessor=}".split("=")[0]: "MoneyWiz Database Accessor",
        f"{account_manager=}".split("=")[0]: "Account Manager",
        f"{payee_manager=}".split("=")[0]: "Payee Manager",
        f"{category_manager=}".split("=")[0]: "Category Manager",
        f"{transaction_manager=}".split("=")[0]: "Transaction Manager",
        f"{investment_holding_manager=}".split("=")[0]: "Investment Holding Manager",
        f"{tag_manager=}".split("=")[0]: "Tag Manager",
        f"{helper=}".split("=")[0]: "Shell Helper",
    }

    banner: List[str] = [
        f"Read-only MoneyWiz Shell on {db_file_path}",
        "",
        "Available components:",
        *[f"- {component:30}  {desc}" for component, desc in names.items()],
        "===================================================================",
    ]

    if demo_dump:
        _users_table = helper.users_table()
        click.secho("Users Table", fg="yellow")
        click.secho("--------------------------------", fg="yellow")
        click.secho(_users_table.to_string(index=False))
        click.secho("--------------------------------\n", fg="yellow")

        _userid_list = _users_table["id"].tolist()
        _userid_list.remove(1)
        _user_id = random.choice(_userid_list)

        _categories_table = helper.categories_table(_user_id)
        click.secho(f"Categories Table for User {_user_id}", fg="yellow")
        click.secho("--------------------------------", fg="yellow")
        click.secho(
            _categories_table[["id", "name", "type"]].sample(5).to_string(index=False)
        )
        click.secho("--------------------------------\n", fg="yellow")

        _accounts_table = helper.accounts_table(_user_id)
        click.secho(f"Accounts Table for User {_user_id}", fg="yellow")
        click.secho("--------------------------------", fg="yellow")
        click.secho(_accounts_table[["id", "name"]].sample(5).to_string(index=False))
        click.secho("--------------------------------\n", fg="yellow")

    _vars = globals()
    _vars.update(locals())

    pd.options.display.max_rows = None
    pd.options.display.max_colwidth = None

    readline.set_completer(rlcompleter.Completer(_vars).complete)
    readline.parse_and_bind("tab: complete")
    InteractiveConsole(_vars).interact(banner="\n".join(banner))


if __name__ == "__main__":
    main()  # pylint: disable=no-value-for-parameter
