import os

from sadb.database import WritableDB
from sadb.source import SourceType
from sadb import InstalledApp, StillRating
import swai_inst.utils as swai_inst_utils
import swai_inst.updater as swai_inst_updater
import yaml

class SwaiType(SourceType):
    """Base class for SWAI source implementations."""
    type = "swai"
    title = "SWAI"
    config_folder = "swai"

    def __init__(self, yml: str, source_name: str):
        """Initialize the SWAI source.
        
        Args:
            yml: The YAML configuration for the source.
            source_name: The name of the source.
        """
        self.yml = yml
        self.source_name = source_name

    def generate_config(self) -> str:
        # Does not need config
        pass

    def write_config(self):
        # Does not need config
        pass

    def check_config(self):
        # Does not need config
        return True, None

    @staticmethod
    def _get_icon_path(app_id: str, desktop_dir: str, icon_dir: str):
        desktop_candidates = [
            os.path.join(desktop_dir, f"swai.{app_id}.desktop"),
            os.path.join(desktop_dir, f"{app_id}.desktop"),
            os.path.join(desktop_dir, f"io.stillhq.swai.{app_id}.desktop"),
        ]

        for desktop_file_path in desktop_candidates:
            if not os.path.exists(desktop_file_path):
                continue

            with open(desktop_file_path, "r", encoding="utf-8") as f:
                desktop_data = f.read()

            if "Icon=" not in desktop_data:
                continue

            icon_name = desktop_data.split("Icon=", 1)[1].split("\n", 1)[0].strip()
            if not icon_name:
                continue

            candidate_paths = [
                os.path.join(icon_dir, icon_name),
                os.path.join(icon_dir, f"{icon_name}.png"),
                os.path.join(icon_dir, f"{icon_name}.svg"),
            ]
            for icon_path in candidate_paths:
                if os.path.exists(icon_path):
                    return icon_path

            return icon_name

        return None

    @staticmethod
    def add_installed_to_db(db: WritableDB):
        """Add installed apps to database.
        
        Args:
            db: Database to add apps to.
        """

        updates_available = swai_inst_updater.check_for_updates()
        apps = []

        for app_id in swai_inst_utils.get_installed_app_ids():
            update_available = app_id in updates_available
            swai_dir, desktop_dir, icon_dir = swai_inst_utils.get_install_paths()
            swai_file_path = os.path.join(swai_dir, f"{app_id}.swai")
            if not os.path.exists(swai_file_path):
                continue

            with open(swai_file_path, "r", encoding="utf-8") as f:
                swai_data = yaml.safe_load(f)
            if not isinstance(swai_data, dict):
                continue

            # We mainly use sadb as our primary database for app data, so installed apps need to pull from there
            package_id = f"{app_id},{swai_data.get("update_url", "null")}"

            app = db.get_installed_app_from_main_db("swai", package_id)

            icon_path = SwaiType._get_icon_path(app_id, desktop_dir, icon_dir)

            if app is None:
                app_name = swai_data.get("app_name")
                app = InstalledApp(
                    update_available, f"swai-{app_id.replace(".", "-")}",
                    app_name, "swai", package_id, icon_path, "Unknown Author",
                    swai_data.get("comment", "Unknown app"), "This app does not contain a description",
                    swai_data.get("categories", []), None, None, None,
                    None, None, StillRating.SWAI, None, None, None, None,
                    None, None, None, None, None, None, app_name
                )
            else:
                app.icon_url = icon_path
                app.still_rating = StillRating.SWAI
                app.appstream_name = app.appstream_name or app.name

            apps.append(app)

        db.add_installed_apps(apps)
