"""
CARL Cleanup Operations
Handles disable, uninstall, and full cleanup of CARL installations.

Three levels of removal:
1. Disable - Remove hooks from settings.json (can re-enable easily)
2. Uninstall - Delete hook script files (need to re-add from control panel)
3. Cleanup - Full removal: .carl folder, hook files, DB entries (destructive)
"""
import json
import shutil
from pathlib import Path
from typing import Optional

from . import database
from .hooks import HOOK_FILES, OPTIONAL_HOOK_FILES


def disable_carl_hooks(workspace_path: Path) -> dict:
    """
    Disable CARL by removing hooks from settings.json.

    This unhooks CARL but keeps all files intact for easy re-enable.
    User can re-enable by running setup flow again.

    Args:
        workspace_path: Path to the workspace root

    Returns:
        Dict with success status and details of what was removed
    """
    settings_path = workspace_path / '.claude' / 'settings.json'

    if not settings_path.exists():
        return {
            'success': True,
            'message': 'No settings.json found - hooks already disabled',
            'removed_hooks': []
        }

    try:
        with open(settings_path, 'r') as f:
            settings = json.load(f)

        removed_hooks = []
        hooks_config = settings.get('hooks', {})
        user_prompt = hooks_config.get('UserPromptSubmit', [])

        # Track what we're removing
        new_user_prompt = []

        for item in user_prompt:
            if isinstance(item, dict) and 'hooks' in item:
                # Complex format with hooks array
                original_hooks = item.get('hooks', [])
                filtered_hooks = []

                for hook in original_hooks:
                    if isinstance(hook, dict):
                        command = hook.get('command', '')
                        # Check if this is a CARL hook
                        is_carl_hook = any(hf in command for hf in HOOK_FILES + OPTIONAL_HOOK_FILES)
                        if is_carl_hook:
                            removed_hooks.append(command)
                        else:
                            filtered_hooks.append(hook)
                    else:
                        filtered_hooks.append(hook)

                # Keep the item if it still has hooks or has a matcher
                if filtered_hooks or item.get('matcher'):
                    item['hooks'] = filtered_hooks
                    new_user_prompt.append(item)

            elif isinstance(item, dict) and 'command' in item:
                # Simple format
                command = item.get('command', '')
                is_carl_hook = any(hf in command for hf in HOOK_FILES + OPTIONAL_HOOK_FILES)
                if is_carl_hook:
                    removed_hooks.append(command)
                else:
                    new_user_prompt.append(item)
            else:
                new_user_prompt.append(item)

        # Update settings
        if removed_hooks:
            settings['hooks']['UserPromptSubmit'] = new_user_prompt
            with open(settings_path, 'w') as f:
                json.dump(settings, f, indent=2)

        return {
            'success': True,
            'removed_hooks': removed_hooks,
            'message': f'Disabled {len(removed_hooks)} hook(s) from settings.json'
        }

    except Exception as e:
        return {'success': False, 'error': str(e)}


def uninstall_carl_hooks(workspace_path: Path) -> dict:
    """
    Uninstall CARL hook files from .claude/hooks/.

    This deletes the hook script files. User must re-add from control panel.
    Does NOT remove from settings.json (call disable_carl_hooks first if needed).

    Args:
        workspace_path: Path to the workspace root

    Returns:
        Dict with success status and details of what was deleted
    """
    hooks_dir = workspace_path / '.claude' / 'hooks'

    if not hooks_dir.exists():
        return {
            'success': True,
            'message': 'No .claude/hooks directory found',
            'deleted_files': []
        }

    deleted_files = []
    errors = []

    # Delete core CARL hooks
    for hook_file in HOOK_FILES:
        hook_path = hooks_dir / hook_file
        if hook_path.exists():
            try:
                hook_path.unlink()
                deleted_files.append(str(hook_path))
            except Exception as e:
                errors.append(f'{hook_file}: {str(e)}')

    # Delete optional hooks
    for hook_file in OPTIONAL_HOOK_FILES:
        hook_path = hooks_dir / hook_file
        if hook_path.exists():
            try:
                hook_path.unlink()
                deleted_files.append(str(hook_path))
            except Exception as e:
                errors.append(f'{hook_file}: {str(e)}')

    return {
        'success': len(errors) == 0,
        'deleted_files': deleted_files,
        'errors': errors if errors else None,
        'message': f'Deleted {len(deleted_files)} hook file(s)'
    }


def cleanup_carl_full(workspace_path: Path, profile_id: Optional[str] = None) -> dict:
    """
    Full cleanup: remove .carl folder, hook files, settings.json entries, and DB records.

    This is the most destructive operation - complete removal of CARL.

    Args:
        workspace_path: Path to the workspace root
        profile_id: Optional profile ID to delete from database

    Returns:
        Dict with success status and details of what was removed
    """
    results = {
        'settings_cleaned': False,
        'hooks_deleted': [],
        'carl_folder_deleted': False,
        'db_profile_deleted': False,
        'db_snapshots_deleted': 0,
        'errors': []
    }

    # 1. Disable hooks in settings.json
    try:
        disable_result = disable_carl_hooks(workspace_path)
        results['settings_cleaned'] = disable_result.get('success', False)
        if not disable_result.get('success'):
            results['errors'].append(f"Settings: {disable_result.get('error', 'Unknown error')}")
    except Exception as e:
        results['errors'].append(f"Settings: {str(e)}")

    # 2. Delete hook files
    try:
        uninstall_result = uninstall_carl_hooks(workspace_path)
        results['hooks_deleted'] = uninstall_result.get('deleted_files', [])
        if uninstall_result.get('errors'):
            results['errors'].extend(uninstall_result['errors'])
    except Exception as e:
        results['errors'].append(f"Hooks: {str(e)}")

    # 3. Delete .carl folder
    carl_path = workspace_path / '.carl'
    if carl_path.exists():
        try:
            shutil.rmtree(carl_path)
            results['carl_folder_deleted'] = True
        except Exception as e:
            results['errors'].append(f".carl folder: {str(e)}")
    else:
        results['carl_folder_deleted'] = True  # Already gone

    # 4. Delete database entries
    if profile_id:
        try:
            conn = database.get_connection()
            cursor = conn.cursor()

            # Delete snapshots first (foreign key)
            cursor.execute('DELETE FROM snapshots WHERE profile_id = ?', (profile_id,))
            results['db_snapshots_deleted'] = cursor.rowcount

            # Delete profile
            cursor.execute('DELETE FROM profiles WHERE id = ?', (profile_id,))
            results['db_profile_deleted'] = cursor.rowcount > 0

            conn.commit()
            conn.close()
        except Exception as e:
            results['errors'].append(f"Database: {str(e)}")

    results['success'] = len(results['errors']) == 0
    return results


def get_cleanup_preview(workspace_path: Path, profile_id: Optional[str] = None) -> dict:
    """
    Preview what would be affected by a full cleanup.

    Args:
        workspace_path: Path to the workspace root
        profile_id: Optional profile ID to check

    Returns:
        Dict with details of what would be affected
    """
    preview = {
        'settings_json_exists': False,
        'carl_hooks_in_settings': [],
        'hook_files': [],
        'carl_folder_exists': False,
        'carl_folder_contents': [],
        'db_profile_exists': False,
        'db_snapshots_count': 0
    }

    # Check settings.json
    settings_path = workspace_path / '.claude' / 'settings.json'
    if settings_path.exists():
        preview['settings_json_exists'] = True
        try:
            with open(settings_path, 'r') as f:
                settings = json.load(f)

            hooks_config = settings.get('hooks', {})
            user_prompt = hooks_config.get('UserPromptSubmit', [])

            for item in user_prompt:
                if isinstance(item, dict) and 'hooks' in item:
                    for hook in item.get('hooks', []):
                        if isinstance(hook, dict):
                            command = hook.get('command', '')
                            if any(hf in command for hf in HOOK_FILES + OPTIONAL_HOOK_FILES):
                                preview['carl_hooks_in_settings'].append(command)
                elif isinstance(item, dict) and 'command' in item:
                    command = item.get('command', '')
                    if any(hf in command for hf in HOOK_FILES + OPTIONAL_HOOK_FILES):
                        preview['carl_hooks_in_settings'].append(command)
        except Exception:
            pass

    # Check hook files
    hooks_dir = workspace_path / '.claude' / 'hooks'
    if hooks_dir.exists():
        for hook_file in HOOK_FILES + OPTIONAL_HOOK_FILES:
            hook_path = hooks_dir / hook_file
            if hook_path.exists():
                preview['hook_files'].append(str(hook_path))

    # Check .carl folder
    carl_path = workspace_path / '.carl'
    if carl_path.exists():
        preview['carl_folder_exists'] = True
        try:
            for item in carl_path.iterdir():
                if item.is_file():
                    preview['carl_folder_contents'].append(item.name)
                elif item.is_dir():
                    preview['carl_folder_contents'].append(f"{item.name}/ ({len(list(item.iterdir()))} items)")
        except Exception:
            pass

    # Check database
    if profile_id:
        try:
            profile = database.get_profile_by_id(profile_id)
            preview['db_profile_exists'] = profile is not None

            if profile:
                conn = database.get_connection()
                cursor = conn.cursor()
                cursor.execute('SELECT COUNT(*) as count FROM snapshots WHERE profile_id = ?', (profile_id,))
                row = cursor.fetchone()
                preview['db_snapshots_count'] = row['count'] if row else 0
                conn.close()
        except Exception:
            pass

    return preview


def disable_addon_hook(hook_name: str, workspace_path: Path) -> dict:
    """
    Disable a specific addon hook by removing from settings.json.

    Args:
        hook_name: Name of the hook file (e.g., 'claudemd-reinject.py')
        workspace_path: Path to the workspace root

    Returns:
        Dict with success status
    """
    if hook_name not in OPTIONAL_HOOK_FILES:
        return {'success': False, 'error': f'Unknown addon hook: {hook_name}'}

    settings_path = workspace_path / '.claude' / 'settings.json'

    if not settings_path.exists():
        return {'success': True, 'message': 'No settings.json found'}

    try:
        with open(settings_path, 'r') as f:
            settings = json.load(f)

        hooks_config = settings.get('hooks', {})
        user_prompt = hooks_config.get('UserPromptSubmit', [])

        removed = False
        for item in user_prompt:
            if isinstance(item, dict) and 'hooks' in item:
                original_len = len(item['hooks'])
                item['hooks'] = [
                    h for h in item['hooks']
                    if not (isinstance(h, dict) and hook_name in h.get('command', ''))
                ]
                if len(item['hooks']) < original_len:
                    removed = True

        if removed:
            with open(settings_path, 'w') as f:
                json.dump(settings, f, indent=2)

        return {'success': True, 'removed': removed}

    except Exception as e:
        return {'success': False, 'error': str(e)}


def uninstall_addon_hook(hook_name: str, workspace_path: Path) -> dict:
    """
    Uninstall a specific addon hook file.

    Args:
        hook_name: Name of the hook file
        workspace_path: Path to the workspace root

    Returns:
        Dict with success status
    """
    if hook_name not in OPTIONAL_HOOK_FILES:
        return {'success': False, 'error': f'Unknown addon hook: {hook_name}'}

    hook_path = workspace_path / '.claude' / 'hooks' / hook_name

    if not hook_path.exists():
        return {'success': True, 'message': 'Hook file not found'}

    try:
        hook_path.unlink()
        return {'success': True, 'deleted': str(hook_path)}
    except Exception as e:
        return {'success': False, 'error': str(e)}


def cleanup_addon_full(hook_name: str, workspace_path: Path, manifest_manager=None) -> dict:
    """
    Full cleanup of an addon hook: settings.json, file, and manifest entry.

    Args:
        hook_name: Name of the hook file
        workspace_path: Path to the workspace root
        manifest_manager: Optional ManifestManager to clean up manifest entries

    Returns:
        Dict with success status and details
    """
    results = {
        'settings_cleaned': False,
        'file_deleted': False,
        'manifest_cleaned': False,
        'errors': []
    }

    # 1. Remove from settings.json
    try:
        disable_result = disable_addon_hook(hook_name, workspace_path)
        results['settings_cleaned'] = disable_result.get('success', False)
        if not disable_result.get('success'):
            results['errors'].append(disable_result.get('error', 'Unknown error'))
    except Exception as e:
        results['errors'].append(str(e))

    # 2. Delete the file
    try:
        uninstall_result = uninstall_addon_hook(hook_name, workspace_path)
        results['file_deleted'] = uninstall_result.get('success', False)
        if not uninstall_result.get('success') and 'not found' not in uninstall_result.get('message', ''):
            results['errors'].append(uninstall_result.get('error', 'Unknown error'))
    except Exception as e:
        results['errors'].append(str(e))

    # 3. Clean up manifest entry (if manifest_manager provided)
    # The manifest key for addons follows pattern: ADDON_{NAME}_STATE
    # We don't delete from manifest as it's harmless and might be reinstalled
    results['manifest_cleaned'] = True  # No action needed

    results['success'] = len(results['errors']) == 0
    return results
