from functools import cached_property
from pathlib import Path
import sys
from wizlib.app import WizApp
from wizlib.ui_handler import UIHandler
from wizlib.config_handler import ConfigHandler
from wizlib.command import WizHelpCommand

from busy.command import BusyCommand
from busy.storage.file_storage import FileStorage
from busy.util.identifier import Identifier


class BusyApp(WizApp):

    base = BusyCommand
    name = 'busy'
    handlers = [UIHandler, ConfigHandler]

    @cached_property
    def directory(self):
        return self.config.get('busy-storage-directory') \
            or Path.home() / '.busy'

    @cached_property
    def identifier(self):
        identifier_address = self.config.get('busy-identifier-address') \
            or '0'
        return Identifier(identifier_address, self.directory)

    @cached_property
    def storage(self):
        return FileStorage(self.directory, self.identifier)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._validate_configuration()

    def _validate_configuration(self):
        """Validate the configuration for hierarchical tags"""
        from busy.error import BusyError
        queues_config = self.config.get('busy-queues')
        if not queues_config:
            return

        for queue_name, queue_config in queues_config.items():
            if isinstance(queue_config, dict) and 'tags' in queue_config:
                self._validate_unique_tag_definitions_for_queue(
                    queue_name, queue_config['tags'])

    def _validate_unique_tag_definitions_for_queue(
            self, queue_name, tags_config):
        """Validate that tags are not defined in multiple places within a
        queue"""
        from busy.error import BusyError
        all_tags = set()

        def collect_tags(config_dict):
            if not isinstance(config_dict, dict):
                return

            for tag_name, tag_config in config_dict.items():
                if tag_name in all_tags:
                    raise BusyError(
                        f"Duplicate tag definition: '{tag_name}' is defined " +
                        f"in multiple places within queue '{queue_name}'")
                all_tags.add(tag_name)

                # Process nested tags
                if isinstance(tag_config, dict) and 'tags' in tag_config:
                    collect_tags(tag_config['tags'])

        collect_tags(tags_config)

    def run(self, **vals):
        super().run(**vals)

    # For MCP server. Probably belongs in WizLib.
    def do(self, command_string) -> dict:
        args = command_string.split(' ')
        ns = self.parser.parse_args(args)
        vals = vars(ns)
        if 'help' in vals:
            ccls = WizHelpCommand
        else:
            c = 'command'
            cname = (vals.pop(c) if c in vals else None) or self.base.default
            ccls = self.base.family_member('name', cname)
            if not ccls:
                raise Exception(f"Unknown command {cname}")
        command = ccls(self, **vals)
        result = command.execute()
        return {'result': result, 'status': command.status}
