#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#

import os
import shlex
import sys
from dataclasses import dataclass
from typing import Optional
from cmd import Cmd

try:
    import readline
except ImportError:
    readline = None  # type: ignore[assignment]

from apache_polaris.cli.command import Command
from apache_polaris.cli.constants import (
    Commands,
    Arguments,
    REPL_HISTORY_LENGTH,
    REPL_HISTORY_FILE,
)
from apache_polaris.cli.exceptions import CliError
from apache_polaris.cli.options.option_tree import OptionTree
from apache_polaris.cli.options.parser import Parser
from apache_polaris.sdk.management import PolarisDefaultApi
from apache_polaris.sdk.management.exceptions import ApiException
from apache_polaris.cli.command.profiles import ProfilesCommand
from apache_polaris.cli.polaris_cli import PolarisCli
from urllib.parse import urlparse


@dataclass
class ReplCommand(Command):
    """
    A Command implementation to represent `polaris repl`. This command starts an interactive REPL session.

    Example commands:
        * polaris repl
    """

    profile: Optional[str] = None
    catalog: Optional[str] = None

    def validate(self) -> None:
        pass

    def execute(self, api: PolarisDefaultApi) -> None:
        repl = PolarisRepl(api, profile=self.profile, catalog=self.catalog)
        while True:
            try:
                repl.cmdloop()
                break
            except KeyboardInterrupt:
                sys.stdout.write("\n")
                repl.intro = ""


class PolarisRepl(Cmd):
    intro = "\n".join(
        [
            "Welcome to the Apache Polaris CLI REPL. Type 'help' for commands, 'exit' or Ctrl-D to quit.",
            "Note: global auth flags (--host, --port, --profile, --client-id, --client-secret, ...) are bound "
            "at session start and ignored when re-specified inside the REPL.",
        ]
    )

    def __init__(
        self,
        api: PolarisDefaultApi,
        profile: Optional[str] = None,
        catalog: Optional[str] = None,
    ):
        super().__init__()
        self.api = api
        self.catalog = catalog
        display_name = profile or urlparse(api.api_client.configuration.host).netloc
        if catalog:
            self.prompt = f"polaris@{display_name}/{catalog}> "
        else:
            self.prompt = f"polaris@{display_name}> "
        if readline is not None:
            try:
                readline.read_history_file(REPL_HISTORY_FILE)
            except (FileNotFoundError, OSError):
                pass
            readline.set_history_length(REPL_HISTORY_LENGTH)

    def default(self, line: str) -> None:
        if not line.strip():
            return
        try:
            args = shlex.split(line)
            options = Parser.parse(args)
            if options.command == Commands.REPL:
                sys.stderr.write("Already in REPL session.\n")
                return
            if (
                self.catalog
                and hasattr(options, Arguments.CATALOG)
                and getattr(options, Arguments.CATALOG) is None
            ):
                setattr(options, Arguments.CATALOG, self.catalog)
            command = Command.from_options(options)
            if isinstance(command, ProfilesCommand):
                command.execute()
            else:
                command.execute(self.api)
        except SystemExit:
            pass
        except KeyboardInterrupt:
            sys.stderr.write("Session interrupted. Type 'exit' to quit.\n")
        except ApiException as e:
            PolarisCli.print_api_exception(e)
        except CliError as e:
            sys.stderr.write(f"{e}\n")
        except NotImplementedError as e:
            sys.stderr.write(f"Internal error: {e}\n")
        except ValueError as e:
            sys.stderr.write(f"Syntax error: {e}\n")
        except Exception as e:
            sys.stderr.write(f"An unexpected error occurred: {e}\n")

    def do_help(self, arg: str) -> None:
        if arg:
            self.default(f"{arg} --help")
            return
        sys.stdout.write(f"Polaris commands:{os.linesep}")
        for option in OptionTree.get_tree():
            sys.stdout.write(f" {option.name:<15} {option.hint or ''}\n")
        sys.stdout.write(
            f"{os.linesep}".join(
                [
                    "REPL built-ins: exit, help, Ctrl-D\n",
                    "Use 'help <command>' or '<command --help>' for command details.\n",
                ]
            )
        )

    def do_exit(self, args: str) -> bool:
        return True

    do_EOF = do_exit

    def emptyline(self) -> bool:
        return False

    def postloop(self) -> None:
        if readline is not None:
            try:
                os.makedirs(os.path.dirname(REPL_HISTORY_FILE), exist_ok=True)
                readline.write_history_file(REPL_HISTORY_FILE)
            except OSError:
                pass
