#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Secure credential and configuration management using OS keyring"""
import json, os, logging, keyring
from pathlib import Path

log = logging.getLogger("bunny2fmc")
SERVICE_NAME = "bunny2fmc"
CONFIG_DIR = Path.home() / ".local" / "share" / "bunny2fmc"
CONFIG_FILE = CONFIG_DIR / "config.json"
LOG_DIR = CONFIG_DIR / "logs"

class CredentialManager:
    @staticmethod
    def set_credentials(fmc_base_url: str, fmc_username: str, fmc_password: str, sync_interval_minutes: int):
        try:
            keyring.set_password(SERVICE_NAME, "fmc_base_url", fmc_base_url)
            keyring.set_password(SERVICE_NAME, "fmc_username", fmc_username)
            keyring.set_password(SERVICE_NAME, "fmc_password", fmc_password)
            keyring.set_password(SERVICE_NAME, "sync_interval_minutes", str(sync_interval_minutes))
            log.info("Credentials and interval stored in OS keyring")
            return True
        except Exception as e:
            log.error("Failed to store credentials: %s", e)
            raise

    @staticmethod
    def get_credentials() -> dict:
        try:
            fmc_base_url = keyring.get_password(SERVICE_NAME, "fmc_base_url")
            fmc_username = keyring.get_password(SERVICE_NAME, "fmc_username")
            fmc_password = keyring.get_password(SERVICE_NAME, "fmc_password")
            sync_interval_str = keyring.get_password(SERVICE_NAME, "sync_interval_minutes")
            if not all([fmc_base_url, fmc_username, fmc_password, sync_interval_str]):
                log.info("Credentials not found in keyring")
                return None
            return {"fmc_base_url": fmc_base_url, "fmc_username": fmc_username, "fmc_password": fmc_password, "sync_interval_minutes": int(sync_interval_str)}
        except Exception as e:
            log.error("Failed to retrieve credentials: %s", e)
            return None

    @staticmethod
    def clear_credentials():
        try:
            for key in ["fmc_base_url", "fmc_username", "fmc_password", "sync_interval_minutes"]:
                try:
                    keyring.delete_password(SERVICE_NAME, key)
                except keyring.errors.PasswordDeleteError:
                    pass
            log.info("Credentials cleared from keyring")
            return True
        except Exception as e:
            log.error("Failed to clear credentials: %s", e)
            raise

class ConfigManager:
    @staticmethod
    def ensure_directories():
        CONFIG_DIR.mkdir(parents=True, exist_ok=True)
        LOG_DIR.mkdir(parents=True, exist_ok=True)

    @staticmethod
    def get_config_dir() -> Path:
        ConfigManager.ensure_directories()
        return CONFIG_DIR

    @staticmethod
    def get_log_dir() -> Path:
        ConfigManager.ensure_directories()
        return LOG_DIR

    @staticmethod
    def get_log_file() -> Path:
        return ConfigManager.get_log_dir() / "bunny2fmc.log"

    @staticmethod
    def load_dynamic_object_name() -> str:
        try:
            if CONFIG_FILE.exists():
                with open(CONFIG_FILE, "r") as f:
                    data = json.load(f)
                    return data.get("fmc_dynamic_name")
        except Exception as e:
            log.warning("Failed to load config: %s", e)
        return None

    @staticmethod
    def save_dynamic_object_name(name: str):
        try:
            ConfigManager.ensure_directories()
            data = {}
            if CONFIG_FILE.exists():
                with open(CONFIG_FILE, "r") as f:
                    data = json.load(f)
            data["fmc_dynamic_name"] = name
            with open(CONFIG_FILE, "w") as f:
                json.dump(data, f, indent=2)
            log.info("Dynamic Object name saved")
        except Exception as e:
            log.error("Failed to save config: %s", e)
            raise

    @staticmethod
    def save_include_ipv6(include: bool):
        try:
            ConfigManager.ensure_directories()
            data = {}
            if CONFIG_FILE.exists():
                with open(CONFIG_FILE, "r") as f:
                    data = json.load(f)
            data["include_ipv6"] = include
            with open(CONFIG_FILE, "w") as f:
                json.dump(data, f, indent=2)
            log.info("IPv6 preference saved")
        except Exception as e:
            log.error("Failed to save config: %s", e)
            raise

    @staticmethod
    def load_include_ipv6() -> bool:
        try:
            if CONFIG_FILE.exists():
                with open(CONFIG_FILE, "r") as f:
                    data = json.load(f)
                    return data.get("include_ipv6", False)
        except Exception as e:
            log.warning("Failed to load config: %s", e)
        return False

    @staticmethod
    def load_fmc_base_url() -> str:
        """Load FMC base URL from config file"""
        try:
            if CONFIG_FILE.exists():
                with open(CONFIG_FILE, "r") as f:
                    data = json.load(f)
                    return data.get("fmc_base_url")
        except Exception as e:
            log.warning("Failed to load config: %s", e)
        return None

    @staticmethod
    def save_fmc_base_url(url: str):
        """Save FMC base URL to config file"""
        try:
            ConfigManager.ensure_directories()
            data = {}
            if CONFIG_FILE.exists():
                with open(CONFIG_FILE, "r") as f:
                    data = json.load(f)
            data["fmc_base_url"] = url
            with open(CONFIG_FILE, "w") as f:
                json.dump(data, f, indent=2)
            log.info("FMC base URL saved")
        except Exception as e:
            log.error("Failed to save config: %s", e)
            raise

    @staticmethod
    def load_fmc_username() -> str:
        """Load FMC username from config file"""
        try:
            if CONFIG_FILE.exists():
                with open(CONFIG_FILE, "r") as f:
                    data = json.load(f)
                    return data.get("fmc_username")
        except Exception as e:
            log.warning("Failed to load config: %s", e)
        return None

    @staticmethod
    def save_fmc_username(username: str):
        """Save FMC username to config file"""
        try:
            ConfigManager.ensure_directories()
            data = {}
            if CONFIG_FILE.exists():
                with open(CONFIG_FILE, "r") as f:
                    data = json.load(f)
            data["fmc_username"] = username
            with open(CONFIG_FILE, "w") as f:
                json.dump(data, f, indent=2)
            log.info("FMC username saved")
        except Exception as e:
            log.error("Failed to save config: %s", e)
            raise

    @staticmethod
    def load_sync_interval_minutes() -> int:
        """Load sync interval from config file"""
        try:
            if CONFIG_FILE.exists():
                with open(CONFIG_FILE, "r") as f:
                    data = json.load(f)
                    interval = data.get("sync_interval_minutes")
                    return int(interval) if interval else None
        except Exception as e:
            log.warning("Failed to load config: %s", e)
        return None

    @staticmethod
    def save_sync_interval_minutes(minutes: int):
        """Save sync interval to config file"""
        try:
            ConfigManager.ensure_directories()
            data = {}
            if CONFIG_FILE.exists():
                with open(CONFIG_FILE, "r") as f:
                    data = json.load(f)
            data["sync_interval_minutes"] = minutes
            with open(CONFIG_FILE, "w") as f:
                json.dump(data, f, indent=2)
            log.info("Sync interval saved")
        except Exception as e:
            log.error("Failed to save config: %s", e)
            raise
