#!/usr/bin/env python3
"""
Instagram Session Manager for Grabbit
Uses instagrapi to login, save sessions, and verify accounts.

Usage:
  python insta_session.py login <username> <password> <session_file>
  python insta_session.py verify <session_file>
  python insta_session.py info <session_file>

Returns JSON to stdout for parsing by Node.js.
"""

import sys
import json
import os
from pathlib import Path

def output_json(data: dict):
    """Print JSON to stdout and exit"""
    print(json.dumps(data))
    sys.exit(0 if data.get('success') else 1)

def output_error(message: str, error_type: str = 'error'):
    """Print error JSON and exit"""
    output_json({
        'success': False,
        'error': message,
        'error_type': error_type
    })

# Check instagrapi is installed
try:
    from instagrapi import Client
    from instagrapi.exceptions import (
        LoginRequired,
        ChallengeRequired,
        TwoFactorRequired,
        BadPassword,
        PleaseWaitFewMinutes,
        ClientError
    )
except ImportError:
    output_error('instagrapi not installed - run: pip install instagrapi', 'missing_dependency')


def login(username: str, password: str, session_file: str) -> dict:
    """
    Login to Instagram and save session to file.
    Returns account info on success.
    """
    cl = Client()

    # Set some settings to avoid detection
    cl.delay_range = [1, 3]

    try:
        # Try to login
        cl.login(username, password)

        # Get account info
        user_info = cl.account_info()

        # Save session
        session_path = Path(session_file)
        session_path.parent.mkdir(parents=True, exist_ok=True)
        cl.dump_settings(str(session_path))

        return {
            'success': True,
            'username': user_info.username,
            'display_name': user_info.full_name,
            'profile_pic_url': str(user_info.profile_pic_url) if user_info.profile_pic_url else None,
            'session_file': str(session_path.absolute())
        }

    except BadPassword:
        output_error('Invalid password', 'bad_password')
    except TwoFactorRequired:
        output_error('Two-factor authentication required - use the web to create a session file instead', 'two_factor')
    except ChallengeRequired as e:
        output_error(f'Instagram challenge required - verify your account in browser first: {e}', 'challenge')
    except PleaseWaitFewMinutes as e:
        output_error(f'Rate limited - please wait a few minutes: {e}', 'rate_limited')
    except LoginRequired:
        output_error('Login failed - credentials may be invalid', 'login_failed')
    except ClientError as e:
        output_error(f'Instagram error: {e}', 'client_error')
    except Exception as e:
        output_error(f'Unexpected error: {e}', 'unknown')


def verify(session_file: str) -> dict:
    """
    Load session from file and verify it's still valid.
    Returns account info on success.
    """
    session_path = Path(session_file)

    if not session_path.exists():
        output_error(f'Session file not found: {session_file}', 'file_not_found')

    cl = Client()

    try:
        # Load session
        cl.load_settings(str(session_path))

        # Try to get account info (will fail if session is invalid)
        cl.get_timeline_feed()  # Quick check that session works
        user_info = cl.account_info()

        return {
            'success': True,
            'valid': True,
            'username': user_info.username,
            'display_name': user_info.full_name,
            'profile_pic_url': str(user_info.profile_pic_url) if user_info.profile_pic_url else None,
            'session_file': str(session_path.absolute())
        }

    except LoginRequired:
        output_error('Session expired - please login again', 'session_expired')
    except PleaseWaitFewMinutes as e:
        output_error(f'Rate limited - please wait: {e}', 'rate_limited')
    except ChallengeRequired as e:
        output_error(f'Challenge required - verify account in browser: {e}', 'challenge')
    except ClientError as e:
        output_error(f'Instagram error: {e}', 'client_error')
    except Exception as e:
        output_error(f'Failed to verify session: {e}', 'unknown')


def get_info(session_file: str) -> dict:
    """
    Get account info from session without full verification.
    Faster than verify but may not detect all issues.
    """
    session_path = Path(session_file)

    if not session_path.exists():
        output_error(f'Session file not found: {session_file}', 'file_not_found')

    cl = Client()

    try:
        cl.load_settings(str(session_path))
        user_info = cl.account_info()

        return {
            'success': True,
            'username': user_info.username,
            'display_name': user_info.full_name,
            'profile_pic_url': str(user_info.profile_pic_url) if user_info.profile_pic_url else None,
            'follower_count': user_info.follower_count,
            'following_count': user_info.following_count,
            'media_count': user_info.media_count,
            'is_private': user_info.is_private,
            'session_file': str(session_path.absolute())
        }

    except Exception as e:
        output_error(f'Failed to get info: {e}', 'unknown')


def main():
    if len(sys.argv) < 2:
        output_error('Usage: insta_session.py <command> [args]', 'usage')

    command = sys.argv[1].lower()

    if command == 'login':
        if len(sys.argv) != 5:
            output_error('Usage: insta_session.py login <username> <password> <session_file>', 'usage')
        result = login(sys.argv[2], sys.argv[3], sys.argv[4])
        output_json(result)

    elif command == 'verify':
        if len(sys.argv) != 3:
            output_error('Usage: insta_session.py verify <session_file>', 'usage')
        result = verify(sys.argv[2])
        output_json(result)

    elif command == 'info':
        if len(sys.argv) != 3:
            output_error('Usage: insta_session.py info <session_file>', 'usage')
        result = get_info(sys.argv[2])
        output_json(result)

    else:
        output_error(f'Unknown command: {command}. Use: login, verify, info', 'usage')


if __name__ == '__main__':
    main()
