from __future__ import annotations
import json
import os
from datetime import datetime
from typing import Any, Optional

DASH = "-" * 70

class Log:
    _log_file = None
    # Use absolute path relative to this file's location to ensure logs always go to homebook/logs
    _base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))  # Go up from services/ to homebook/
    _log_file_path = os.path.join(_base_dir, "logs", "voicebot.log")
    
    @staticmethod
    def _ensure_log_directory():
        """Ensure the logs directory exists."""
        log_dir = os.path.dirname(Log._log_file_path)
        if not os.path.exists(log_dir):
            os.makedirs(log_dir)
    
    @staticmethod
    def _get_log_file():
        """Get or create the log file handle."""
        if Log._log_file is None:
            Log._ensure_log_directory()
            Log._log_file = open(Log._log_file_path, "a", encoding="utf-8")
        return Log._log_file
    
    @staticmethod
    def _write_to_file(message: str) -> None:
        """Write message to log file."""
        try:
            log_file = Log._get_log_file()
            log_file.write(message + "\n")
            log_file.flush()  # Ensure it's written immediately
        except Exception as e:
            print(f"Error writing to log file: {e}")
    
    @staticmethod
    def _ts() -> str:
        return datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    @staticmethod
    def line() -> None:
        message = DASH
        print(message)
        Log._write_to_file(message)

    @staticmethod
    def header(title: str) -> None:
        message = f"\n{DASH}\n[{Log._ts()}] {title}\n{DASH}"
        print(message)
        Log._write_to_file(message)

    @staticmethod
    def subheader(title: str) -> None:
        message = f"\n[{Log._ts()}] {title}\n{DASH}"
        print(message)
        Log._write_to_file(message)

    @staticmethod
    def info(msg: str) -> None:
        message = f"[{Log._ts()}] {msg}"
        try:
            print(message)
        except UnicodeEncodeError:
            # Fallback for Windows console encoding issues
            safe_message = message.encode('ascii', 'replace').decode('ascii')
            print(safe_message)
        Log._write_to_file(message)

    @staticmethod
    def error(msg: str) -> None:
        message = f"[{Log._ts()}] ERROR: {msg}"
        try:
            print(message)
        except UnicodeEncodeError:
            # Fallback for Windows console encoding issues
            safe_message = message.encode('ascii', 'replace').decode('ascii')
            print(safe_message)
        Log._write_to_file(message)

    @staticmethod
    def warning(msg: str) -> None:
        message = f"[{Log._ts()}] WARNING: {msg}"
        try:
            print(message)
        except UnicodeEncodeError:
            # Fallback for Windows console encoding issues
            safe_message = message.encode('ascii', 'replace').decode('ascii')
            print(safe_message)
        Log._write_to_file(message)

    @staticmethod
    def debug(msg: str) -> None:
        message = f"[{Log._ts()}] DEBUG: {msg}"
        try:
            print(message)
        except UnicodeEncodeError:
            # Fallback for Windows console encoding issues
            safe_message = message.encode('ascii', 'replace').decode('ascii')
            print(safe_message)
        Log._write_to_file(message)

    @staticmethod
    def event(title: str, details: Optional[dict[str, Any]] = None) -> None:
        Log.header(title)
        if details is not None:
            try:
                details_str = json.dumps(details, indent=2, ensure_ascii=False)
                print(details_str)
                Log._write_to_file(details_str)
            except Exception:
                details_str = str(details)
                print(details_str)
                Log._write_to_file(details_str)
        Log.line()

    @staticmethod
    def json(label: str, data: Any) -> None:
        Log.subheader(label)
        try:
            data_str = json.dumps(data, indent=2, ensure_ascii=False)
            print(data_str)
            Log._write_to_file(data_str)
        except Exception:
            data_str = str(data)
            print(data_str)
            Log._write_to_file(data_str)
        Log.line()
    
    @staticmethod
    def close_log_file() -> None:
        """Close the log file handle."""
        if Log._log_file:
            Log._log_file.close()
            Log._log_file = None
