import sys
import shutil
import glob
import io
import copy
import subprocess
import pathlib
import logging
import enum
import argparse
import dataclasses

from typing import (Optional, override,)

from online.fxreader.pr34.commands_typed.logging import setup as logging_setup

from online.fxreader.pr34.commands_typed import cli as _cli

from online.fxreader.pr34.commands_typed import cli_bootstrap

logging_setup()

logger = logging.getLogger(__name__)


class Command(enum.StrEnum):
    mypy = 'mypy'
    deploy_wheel = 'deploy:wheel'
    tests = 'tests'

@dataclasses.dataclass
class Settings(
    _cli.DistSettings,
):
    base_dir: pathlib.Path = pathlib.Path(__file__).parent.parent
    build_dir: pathlib.Path = base_dir / 'tmp' / 'build'
    wheel_dir: pathlib.Path = base_dir / 'deps' / 'dist'
    env_path: pathlib.Path = cli_bootstrap.BootstrapSettings.get(base_dir).env_path
    python_path: pathlib.Path = cli_bootstrap.BootstrapSettings.get(base_dir).python_path


class CLI(_cli.CLI):
    def __init__(self) -> None:
        self.settings = Settings()
        self._projects: dict[str, _cli.Project] = {
            'online.fxreader.pr34': _cli.Project(
                source_dir=self.settings.base_dir / 'python',
                build_dir=self.settings.base_dir / 'tmp' / 'online' / 'fxreader' / 'pr34' / 'build',
                dest_dir=self.settings.base_dir / 'tmp' / 'online' / 'fxreader' / 'pr34' / 'install',
            )
        }

        self._dependencies : dict[str, _cli.Dependency] = dict()

    @override
    @property
    def dist_settings(self) -> _cli.DistSettings:
        return self.settings

    @override
    @property
    def projects(self) -> dict[str, _cli.Project]:
        return self._projects

    def mypy(
        self,
        argv: list[str],
    ) -> None:
        import online.fxreader.pr34.commands_typed.mypy as _mypy

        project = self._projects['online.fxreader.pr34']

        _mypy.run(
            argv,
            settings=_mypy.MypySettings(
                paths=[
                    #Settings.settings().project_root / 'dotfiles/.local/bin/commands',
                    # project.source_dir / 'm.py',
                    project.source_dir / '_m.py',
                    project.source_dir / 'online',
                    project.source_dir / 'cli.py',
                    self.settings.base_dir / 'm.py',
                    # Settings.settings().project_root / 'deps/com.github.aiortc.aiortc/src',
                    #Settings.settings().project_root / 'm.py',
                ],
                max_errors={
                    'python/online/fxreader/pr34/commands_typed': 0,
                    'python/cli.py': 0,
                    'm.py': 0,
                    'deps/com.github.aiortc.aiortc/src/online_fxreader': 0,
                    'deps/com.github.aiortc.aiortc/src/aiortc/contrib/signaling': 0
                }
            ),
        )

    @override
    @property
    def dependencies(self) -> dict[str, _cli.Dependency]:
        return self._dependencies

    def run(self, argv: Optional[list[str]] = None) -> None:
        if argv is None:
            argv = copy.deepcopy(sys.argv)

        parser = argparse.ArgumentParser()
        parser.add_argument(
            'command',
            choices=[
                o.value
                for o in Command
            ]
        )
        parser.add_argument(
            '-p', '--project',
            choices=[
                o
                for o in self.projects
            ]
        )
        parser.add_argument(
            '-o', '--output_dir',
            default=None,
            help='wheel output dir for deploy:wheel',
        )
        parser.add_argument(
            '-f', '--force',
            default=False,
            action='store_true',
            help='remove install dir, before installing, default = false',
        )

        options, args = parser.parse_known_args(argv[1:])

        options.command = Command(options.command)

        if options.command is Command.deploy_wheel:
            assert not options.project is None

            self.deploy_wheel(
                project_name=options.project,
                argv=args,
                output_dir=options.output_dir,
                mypy=True,
            )
        elif options.command is Command.mypy:
            self.mypy(
                argv=args,
            )
        elif options.command is Command.tests:
            for k, v in self.projects.items():
                subprocess.check_call([
                    sys.executable,
                    '-m',
                    'unittest',
                    'online.fxreader.pr34.tests.test_crypto',
                    *args,
                ], cwd=str(v.source_dir))
        else:
            raise NotImplementedError

if __name__ == '__main__':
    CLI().run()