#!/usr/bin/env python3
"""
Confluence CLI Tool
Unified tool for syncing documents to Confluence.
Supports push, pull, tree view, and search operations.
"""
import os
import sys
import json
import argparse
from dotenv import load_dotenv

# Load environment variables
load_dotenv()

# Get configuration
CONFLUENCE_SERVER = os.getenv('CONFLUENCE_SERVER', '')
DEFAULT_SPACE = os.getenv('DEFAULT_SPACE', '')

# Load agent config
AGENT_CONFIG = {}
AGENT_CONFIG_PATHS = ['agent_config.json', '../agent_config.json']
for config_path in AGENT_CONFIG_PATHS:
    if os.path.exists(config_path):
        try:
            with open(config_path, 'r') as f:
                AGENT_CONFIG = json.load(f)
            break
        except Exception:
            pass

# Get Confluence config
CONFLUENCE_CONFIG = AGENT_CONFIG.get('confluence', {})
if not CONFLUENCE_SERVER:
    CONFLUENCE_SERVER = CONFLUENCE_CONFIG.get('server', '')
if not DEFAULT_SPACE:
    DEFAULT_SPACE = CONFLUENCE_CONFIG.get('default_space', '')


def connect_confluence():
    """Connect to Confluence."""
    from confluence_core import connect_confluence as core_connect
    return core_connect()


# ============================================================
# PUSH COMMAND
# ============================================================

def push_command(args):
    """Push markdown file to Confluence."""
    import frontmatter
    from confluence_core import push_document, print_page_tree
    
    file_path = args.file
    if not os.path.exists(file_path):
        print(f"❌ File not found: {file_path}")
        return
    
    # Check if file is new (no confluence_id) and needs parent selection
    parent_title = None
    parent_id = args.parent_id
    
    # Resolve parent (supports number from tree cache, title, or ID)
    if args.parent:
        parent_title, resolved_id = resolve_parent(args.parent, args.space or DEFAULT_SPACE)
        if resolved_id and not parent_id:
            parent_id = resolved_id
    
    with open(file_path, 'r', encoding='utf-8') as f:
        post = frontmatter.load(f)
    
    is_new_file = not post.metadata.get('confluence_id')
    space = args.space or post.metadata.get('confluence_space') or DEFAULT_SPACE
    
    # Interactive parent selection for new files
    if is_new_file and not parent_title and not parent_id and getattr(args, 'interactive', False):
        print(f"\n📄 New file detected: {file_path}")
        print(f"   Space: {space}")
        print(f"\n🌳 Select parent page from tree:\n")
        
        flat_list = print_page_tree(space_key=space, depth=5)
        
        if flat_list:
            save_tree_cache(flat_list)
            print("\nEnter page number for parent (or press Enter for root): ", end="")
            try:
                choice = input().strip()
                if choice:
                    num = int(choice)
                    selected = next((p for p in flat_list if p.get('num') == num), None)
                    if selected:
                        parent_title = selected['title']
                        parent_id = selected['id']
                        print(f"\n📌 Selected parent: {parent_title}")
                    else:
                        print(f"⚠️ Invalid selection, creating at root")
                else:
                    print("\n📌 Creating at root level")
            except (ValueError, EOFError):
                print("\n📌 Creating at root level")
    
    try:
        page_id, page_url, is_new = push_document(
            file_path=file_path,
            space_key=space,
            parent_title=parent_title,
            parent_id=parent_id,
            ai_title=getattr(args, 'ai_title', False)
        )
        
        action = "Created" if is_new else "Updated"
        print(f"\n✅ {action} successfully!")
        
    except Exception as e:
        print(f"❌ Error: {e}")
        if hasattr(args, 'verbose') and args.verbose:
            import traceback
            traceback.print_exc()


# ============================================================
# PULL COMMAND
# ============================================================

def pull_command(args):
    """Pull Confluence page to local markdown file."""
    from confluence_core import pull_document
    
    try:
        output_path = pull_document(
            output_path=args.output,
            page_id=args.page_id,
            space_key=args.space,
            title=args.title
        )
        
        print(f"\n✅ Pulled successfully!")
        
    except Exception as e:
        print(f"❌ Error: {e}")
        if hasattr(args, 'verbose') and args.verbose:
            import traceback
            traceback.print_exc()


# ============================================================
# TREE COMMAND
# ============================================================

def tree_command(args):
    """Display page tree for parent selection."""
    from confluence_core import print_page_tree
    
    try:
        space = args.space or DEFAULT_SPACE
        if not space and not args.parent and not args.parent_id:
            print("❌ Space key required. Use --space SPACE_KEY")
            return
        
        flat_list = print_page_tree(
            space_key=space,
            parent_id=args.parent_id,
            parent_title=args.parent,
            depth=99 if args.all else (args.depth or 5)  # Default 5 levels, --all for unlimited
        )
        
        # Save cache for quick parent selection
        if flat_list:
            save_tree_cache(flat_list)
            print(f"💡 Use --parent NUMBER to select by number (e.g., --parent 12)")
        
        # Interactive mode
        if args.interactive and flat_list:
            print("\nEnter page number to select as parent (or 'q' to quit): ", end="")
            try:
                choice = input().strip()
                if choice.lower() == 'q':
                    return
                
                num = int(choice)
                selected = next((p for p in flat_list if p['num'] == num), None)
                if selected:
                    print(f"\n✅ Selected: {selected['title']}")
                    print(f"   ID: {selected['id']}")
                    print(f"   Use: --parent {num}")
                else:
                    print(f"❌ Invalid selection: {num}")
            except (ValueError, EOFError):
                pass
        
    except Exception as e:
        print(f"❌ Error: {e}")
        if hasattr(args, 'verbose') and args.verbose:
            import traceback
            traceback.print_exc()


# ============================================================
# SEARCH COMMAND
# ============================================================

def search_command(args):
    """Search Confluence pages."""
    try:
        conf = connect_confluence()
        
        space = args.space or DEFAULT_SPACE
        results = conf.search_by_text(args.query, space_key=space, limit=args.limit or 20)
        
        print(f"\n🔍 Search results for '{args.query}'")
        if space:
            print(f"   Space: {space}")
        print(f"   Found: {len(results)} pages\n")
        
        for i, page in enumerate(results, 1):
            print(f"  {i}. {page.title}")
            print(f"     ID: {page.id}")
            print(f"     🔗 {page.get_url()}")
            print()
        
        conf.close()
        
    except Exception as e:
        print(f"❌ Error: {e}")
        if hasattr(args, 'verbose') and args.verbose:
            import traceback
            traceback.print_exc()


# ============================================================
# LIST SPACES COMMAND
# ============================================================

def list_spaces_command(args):
    """List available Confluence spaces."""
    try:
        conf = connect_confluence()
        spaces = conf.get_spaces(limit=args.limit or 50)
        
        print(f"\n📁 Confluence Spaces\n")
        for space in spaces:
            print(f"  [{space.key}] {space.name}")
        
        print(f"\n📊 Total: {len(spaces)} spaces")
        
        conf.close()
        
    except Exception as e:
        print(f"❌ Error: {e}")


# ============================================================
# CONFIG COMMAND
# ============================================================

def config_check():
    """Display current configuration status."""
    from rich.table import Table
    from rich.console import Console
    console = Console()
    
    table = Table(title="📋 Confluence Configuration Status")
    table.add_column("Item", style="cyan")
    table.add_column("Status", style="green")
    table.add_column("Value")
    
    # Check .env
    env_path = os.path.join(os.getcwd(), '.env')
    if os.path.exists(env_path):
        table.add_row(".env file", "✅ Found", env_path)
    else:
        table.add_row(".env file", "❌ Missing", "Create .env with CONFLUENCE_SERVER, credentials")
    
    # Check environment variables
    if CONFLUENCE_SERVER:
        table.add_row("CONFLUENCE_SERVER", "✅", CONFLUENCE_SERVER[:50] + "..." if len(CONFLUENCE_SERVER) > 50 else CONFLUENCE_SERVER)
    else:
        table.add_row("CONFLUENCE_SERVER", "❌ Missing", "Set in .env or agent_config.json")
    
    pat = os.getenv('CONFLUENCE_PAT', '')
    if pat:
        table.add_row("CONFLUENCE_PAT", "✅", "***" + pat[-4:] if len(pat) > 4 else "***")
    else:
        email = os.getenv('CONFLUENCE_EMAIL', '')
        token = os.getenv('CONFLUENCE_TOKEN', '')
        if email and token:
            table.add_row("CONFLUENCE_EMAIL", "✅", email)
            table.add_row("CONFLUENCE_TOKEN", "✅", "****")
        else:
            table.add_row("Credentials", "❌ Missing", "Set CONFLUENCE_PAT or CONFLUENCE_EMAIL+CONFLUENCE_TOKEN")
    
    table.add_row("DEFAULT_SPACE", "✅" if DEFAULT_SPACE else "⚠️", DEFAULT_SPACE or "Not set")
    
    # Check agent_config.json
    if CONFLUENCE_CONFIG:
        table.add_row("agent_config.json", "✅", "confluence section found")
        if CONFLUENCE_CONFIG.get('default_parent'):
            table.add_row("  default_parent", "✅", CONFLUENCE_CONFIG['default_parent'])
    else:
        table.add_row("agent_config.json", "⚠️", "No confluence section")
    
    console.print(table)


def config_test_connection():
    """Test Confluence connection."""
    from rich.console import Console
    from rich.panel import Panel
    console = Console()
    
    console.print("\n🔌 Testing Confluence connection...\n")
    
    try:
        conf = connect_confluence()
        
        # Get current user
        myself = conf.myself()
        user_name = myself.get('displayName', myself.get('username', 'Unknown'))
        
        console.print(Panel(
            f"👤 **User**: {user_name}\n"
            f"🌐 **Server**: {CONFLUENCE_SERVER}",
            title="✅ Connection Successful",
            border_style="green"
        ))
        
        # Test space access
        if DEFAULT_SPACE:
            try:
                space = conf.get_space(DEFAULT_SPACE)
                console.print(f"\n📁 Space: {space.name} ({space.key})")
            except Exception:
                console.print(f"\n⚠️ Could not access space {DEFAULT_SPACE}")
        
        conf.close()
        
    except Exception as e:
        console.print(f"[red]❌ Connection failed: {e}[/red]")


def config_command(args):
    """Handle config subcommand."""
    if args.check:
        config_check()
    elif args.test_connection:
        config_test_connection()
    else:
        # Default: show check
        config_check()
        print("\n💡 Use --test-connection to verify Confluence access")


# ============================================================
# CREATE COMMAND (Document Templates)
# ============================================================

# Tree cache file for quick parent selection
TREE_CACHE_FILE = '.confluence_tree_cache.json'

def save_tree_cache(flat_list: list):
    """Save tree listing to cache file for quick selection."""
    try:
        with open(TREE_CACHE_FILE, 'w', encoding='utf-8') as f:
            json.dump(flat_list, f, ensure_ascii=False, indent=2)
    except Exception:
        pass

def load_tree_cache() -> list:
    """Load tree cache."""
    try:
        if os.path.exists(TREE_CACHE_FILE):
            with open(TREE_CACHE_FILE, 'r', encoding='utf-8') as f:
                return json.load(f)
    except Exception:
        pass
    return []

def resolve_parent(parent_arg: str, space_key: str = None) -> tuple:
    """
    Resolve parent argument to (parent_title, parent_id).
    Supports: number (from tree cache), title string, or page ID.
    """
    if not parent_arg:
        return None, None
    
    # Check if it's a number (tree selection)
    if parent_arg.isdigit():
        num = int(parent_arg)
        cache = load_tree_cache()
        if cache:
            selected = next((p for p in cache if p.get('num') == num), None)
            if selected:
                print(f"📌 Selected parent: {selected['title']} (#{num})")
                return selected['title'], selected['id']
        print(f"⚠️ No cached tree. Run 'uv run sync_confluence.py tree' first")
        return None, None
    
    # Check if it looks like a page ID (long number)
    if len(parent_arg) > 6 and parent_arg.isdigit():
        return None, parent_arg
    
    # Otherwise it's a title
    return parent_arg, None


# Template metadata only - content loaded from files
TEMPLATES = {
    'blank': 'Empty document with frontmatter only',
    'brd': 'Business Requirements Document',
    'spec': 'Technical Specification',
    'meeting': 'Meeting Notes'
}

def get_template_path(template_name: str) -> str:
    """Get path to template file."""
    # Try multiple locations
    locations = [
        os.path.join(os.path.dirname(__file__), 'confluence_core', 'templates', f'{template_name}.md'),
        os.path.join(os.path.dirname(__file__), 'templates', f'{template_name}.md'),
    ]
    for loc in locations:
        if os.path.exists(loc):
            return loc
    return None


def load_template(template_name: str) -> str:
    """Load template content from file."""
    path = get_template_path(template_name)
    if path and os.path.exists(path):
        with open(path, 'r', encoding='utf-8') as f:
            return f.read()
    return '# {title}\n\nWrite your content here...\n'


def generate_with_llm(prompt: str, context: str = "") -> str:
    """Generate content using LLM (Gemini API)."""
    import google.generativeai as genai
    
    api_key = os.getenv('GEMINI_API_KEY', '')
    model_name = os.getenv('GEMINI_MODEL', 'gemini-2.0-flash')
    
    if not api_key:
        print("⚠️ GEMINI_API_KEY not set, using template without AI enhancement")
        return None
    
    try:
        genai.configure(api_key=api_key)
        model = genai.GenerativeModel(model_name)
        
        full_prompt = f"""{context}

{prompt}

Respond in markdown format only. Do not include code fences around the entire response."""
        
        response = model.generate_content(full_prompt)
        return response.text
    except Exception as e:
        print(f"⚠️ LLM generation failed: {e}")
        return None


def create_command(args):
    """Create a new document from template."""
    from datetime import datetime
    
    title = args.title
    template_name = args.template or 'blank'
    output_path = args.output
    use_ai = getattr(args, 'ai', False)
    ai_context = getattr(args, 'context', '') or ''
    
    # Check template exists
    if template_name not in TEMPLATES:
        print(f"❌ Unknown template: {template_name}")
        print(f"   Available: {', '.join(TEMPLATES.keys())}")
        return
    
    # Generate output path if not specified
    if not output_path:
        filename = title.lower().replace(' ', '-').replace('/', '-')
        filename = ''.join(c for c in filename if c.isalnum() or c == '-')
        output_path = f"docs/{filename}.md"
    
    # Check if file exists
    if os.path.exists(output_path) and not args.force:
        print(f"❌ File already exists: {output_path}")
        print(f"   Use --force to overwrite")
        return
    
    # Resolve parent (supports number from tree cache, title, or ID)
    parent_title, parent_id = resolve_parent(args.parent, args.space or DEFAULT_SPACE)
    
    # Build frontmatter
    frontmatter = f'''---
title: "{title}"
confluence_space: "{args.space or DEFAULT_SPACE}"
'''
    if parent_title:
        frontmatter += f'confluence_parent: "{parent_title}"\n'
    frontmatter += '---\n\n'
    
    # Load template
    template_content = load_template(template_name)
    
    # Generate content
    if use_ai:
        print(f"🤖 Generating content with AI...")
        prompt = f"""You are creating a document titled "{title}" using a {TEMPLATES[template_name]} template.

Based on the template structure below, fill in appropriate content for each section.
Make the content professional, detailed, and relevant to the title.

Template structure:
{template_content}

Additional context: {ai_context if ai_context else 'None provided - use your best judgment based on the title.'}

Generate the complete document content in markdown format."""
        
        ai_content = generate_with_llm(prompt)
        if ai_content:
            content = ai_content
            print(f"✅ AI generated content successfully")
        else:
            # Fallback to template
            content = template_content.format(
                title=title,
                date=datetime.now().strftime('%Y-%m-%d')
            )
    else:
        content = template_content.format(
            title=title,
            date=datetime.now().strftime('%Y-%m-%d')
        )
    
    # Ensure directory exists
    os.makedirs(os.path.dirname(output_path) or '.', exist_ok=True)
    
    # Write file
    with open(output_path, 'w', encoding='utf-8') as f:
        f.write(frontmatter + content)
    
    print(f"✅ Created: {output_path}")
    print(f"   Template: {template_name} - {TEMPLATES[template_name]}")
    if use_ai:
        print(f"   🤖 Content generated by AI")
    print(f"\n📝 Next steps:")
    print(f"   1. Review the document: {output_path}")
    print(f"   2. Push to Confluence: uv run sync_confluence.py push --file {output_path}")


def list_templates():
    """List available templates."""
    print("\n📄 Available Templates:\n")
    for name, description in TEMPLATES.items():
        path = get_template_path(name)
        status = "✅" if path else "⚠️"
        print(f"  {status} [{name}] {description}")
    print(f"\n💡 Usage: uv run sync_confluence.py create --title \"My Doc\" --template brd")



# ============================================================
# CLI
# ============================================================

if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description='Confluence CLI Tool',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  # Push markdown to Confluence
  python sync_confluence.py push --file docs/story.md --space AGENTVISTA
  python sync_confluence.py push --file docs/story.md --parent "Internal Document"
  
  # Pull page to local file
  python sync_confluence.py pull --page-id 789275032 --output docs/story.md
  python sync_confluence.py pull --title "Gitflow" --space AGENTVISTA --output docs/gitflow.md
  
  # View page tree
  python sync_confluence.py tree --space AGENTVISTA
  python sync_confluence.py tree --parent "Management" -i  # Interactive selection
  
  # Search pages
  python sync_confluence.py search "gitflow" --space AGENTVISTA
  
  # List spaces
  python sync_confluence.py list-spaces
  
  # Config
  python sync_confluence.py config --check
  python sync_confluence.py config --test-connection
        """
    )
    
    parser.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
    
    subparsers = parser.add_subparsers(dest='action', help='Action to perform')
    
    # === PUSH ===
    push_parser = subparsers.add_parser('push', help='Push markdown to Confluence')
    push_parser.add_argument('--file', '-f', required=True, help='Markdown file path')
    push_parser.add_argument('--space', '-s', help='Confluence space key')
    push_parser.add_argument('--parent', '-p', help='Parent page title or number from tree cache')
    push_parser.add_argument('--parent-id', help='Parent page ID')
    push_parser.add_argument('-i', '--interactive', action='store_true', 
                             help='Interactive parent selection for new files')
    push_parser.add_argument('--ai-title', action='store_true',
                             help='Use AI to generate better page title')
    
    # === PULL ===
    pull_parser = subparsers.add_parser('pull', help='Pull page to markdown')
    pull_parser.add_argument('--output', '-o', required=True, help='Output file path')
    pull_parser.add_argument('--page-id', help='Confluence page ID')
    pull_parser.add_argument('--space', '-s', help='Space key (required with --title)')
    pull_parser.add_argument('--title', '-t', help='Page title (alternative to --page-id)')
    
    # === TREE ===
    tree_parser = subparsers.add_parser('tree', help='View page tree')
    tree_parser.add_argument('--space', '-s', help='Space key')
    tree_parser.add_argument('--parent', '-p', help='Parent page title to show children')
    tree_parser.add_argument('--parent-id', help='Parent page ID')
    tree_parser.add_argument('--depth', '-d', type=int, default=5, help='Tree depth (default: 5)')
    tree_parser.add_argument('--all', '-a', action='store_true', help='Show all levels (unlimited depth)')
    tree_parser.add_argument('-i', '--interactive', action='store_true', help='Interactive selection')
    
    # === SEARCH ===
    search_parser = subparsers.add_parser('search', help='Search pages')
    search_parser.add_argument('query', help='Search query')
    search_parser.add_argument('--space', '-s', help='Limit to space')
    search_parser.add_argument('--limit', '-l', type=int, default=20, help='Max results')
    
    # === LIST SPACES ===
    list_spaces_parser = subparsers.add_parser('list-spaces', help='List spaces')
    list_spaces_parser.add_argument('--limit', '-l', type=int, default=50, help='Max results')
    
    # === CONFIG ===
    config_parser = subparsers.add_parser('config', help='Configuration')
    config_parser.add_argument('--check', action='store_true', help='Show config status')
    config_parser.add_argument('--test-connection', action='store_true', help='Test connection')
    
    # === CREATE ===
    create_parser = subparsers.add_parser('create', help='Create document from template')
    create_parser.add_argument('--title', '-t', required=True, help='Document title')
    create_parser.add_argument('--template', '-T', default='blank', 
                               choices=['blank', 'brd', 'spec', 'meeting'],
                               help='Template to use (default: blank)')
    create_parser.add_argument('--output', '-o', help='Output file path (auto-generated if not specified)')
    create_parser.add_argument('--space', '-s', help='Confluence space key')
    create_parser.add_argument('--parent', '-p', help='Parent page title')
    create_parser.add_argument('--force', '-f', action='store_true', help='Overwrite existing file')
    create_parser.add_argument('--ai', action='store_true', help='Use AI to generate content based on template')
    create_parser.add_argument('--context', '-c', help='Additional context for AI generation')
    
    # === TEMPLATES ===
    templates_parser = subparsers.add_parser('templates', help='List available templates')
    
    args = parser.parse_args()
    
    if args.action == 'push':
        push_command(args)
    elif args.action == 'pull':
        pull_command(args)
    elif args.action == 'tree':
        tree_command(args)
    elif args.action == 'search':
        search_command(args)
    elif args.action == 'list-spaces':
        list_spaces_command(args)
    elif args.action == 'config':
        config_command(args)
    elif args.action == 'create':
        create_command(args)
    elif args.action == 'templates':
        list_templates()
    else:
        parser.print_help()
