import json
import os

from wurker.settings import conf
from wurker.cli.base import BaseCommand
from wurker.cli.commands.admin.seed import SeedCommand
from wurker.cli.commands.admin.status import StatusCommand
from wurker.cli.commands.admin.stinger import StingerCommand
from wurker.db import schema_exists
from wurker.models import Base


class InitCommand(BaseCommand):
    """Encapsulate first-run initialization."""

    def __init__(
            self,
            only:str='',
            drop:bool=False,
            status:bool=True,
            root:str='',
            slug:str='default',
            node:str='queen',
            env:str='local',
            username:str='',
            password:str='',
            logger=None
    ):
        BaseCommand.__init__(self, logger=logger)

        self.only = only
        self.drop = drop
        self.status = status
        self.root = root
        self.slug = slug
        self.node = node
        self.env = env
        self.username = username
        self.password = password

    def _update_user_json(self):
        """Update the UI user.json file if username/password provided."""

        if not self.username and not self.password:
            return None

        if not self.username or not self.password:
            return "Both --username and --password are required"

        user_path = os.path.join(conf.data_root, "user.json")
        users = []
        if os.path.exists(user_path):
            with open(user_path, "r") as fh:
                try:
                    users = json.load(fh)
                except json.JSONDecodeError as ex:
                    return f"Invalid JSON in '{user_path}': {ex}"

        if isinstance(users, dict):
            users = [users]
        elif not isinstance(users, list):
            return f"Invalid data in '{user_path}': expected list of users"

        updated = False
        for user in users:
            if user.get("username") == self.username:
                user["password"] = self.password
                updated = True
                break

        if not updated:
            users.append({"username": self.username, "password": self.password})

        with open(user_path, "w") as fh:
            json.dump(users, fh, indent=2)
            fh.write("\n")

        return None

    def run(self):
        """Initialize schema/data and optionally print status."""

        root = self.root or os.path.join(conf.etc_root, "stingers")
        stinger_cmd = StingerCommand(logger=self.logger)
        stinger_cmd.run("sting", root=root, slug=self.slug, node=self.node, env=self.env)

        error = self._update_user_json()
        if error:
            return error

        seed_cmd = SeedCommand(only=self.only, drop=self.drop, logger=self.logger)
        error = seed_cmd.run()
        if error:
            return error

        if self.only in ["", "wurker"] and not schema_exists(self.remote_db_conf, Base, return_bool=True):
            return "Remote database schema was not created"

        if self.status:
            status_cmd = StatusCommand(logger=self.logger)
            status_cmd.run()

        return None
