#!/usr/bin/env python3
"""Main entry point for trading bot - Single Watch Folder"""

import sys
import os
import platform
import pytz
from datetime import datetime
import time

# Add current directory to path
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

from config.config import Config
from brokers.zerodha_broker import ZerodhaBroker
from brokers.firstock_broker import FirstockBroker
from processors.file_processor import FileProcessor
from utils.logger import TradingLogger

# Cross-platform lock implementation
if platform.system() == 'Windows':
    import msvcrt
    class CrossPlatformLock:
        def __init__(self, lock_file):
            self.lock_file = lock_file
            self.file_handle = None
            self.lock_acquired = False
        
        def acquire(self):
            try:
                lock_dir = os.path.dirname(self.lock_file)
                if lock_dir and not os.path.exists(lock_dir):
                    os.makedirs(lock_dir, exist_ok=True)
                
                self.file_handle = open(self.lock_file, 'w+')
                msvcrt.locking(self.file_handle.fileno(), msvcrt.LK_NBLCK, 1)
                self.file_handle.write(f"pid={os.getpid()}\n")
                self.file_handle.write(f"time={time.time()}\n")
                self.file_handle.flush()
                self.lock_acquired = True
                return True
            except:
                if self.file_handle:
                    self.file_handle.close()
                return False
        
        def release(self):
            if self.file_handle and self.lock_acquired:
                try:
                    msvcrt.locking(self.file_handle.fileno(), msvcrt.LK_UNLCK, 1)
                    self.file_handle.close()
                except:
                    pass
                try:
                    os.remove(self.lock_file)
                except:
                    pass
                self.lock_acquired = False
        
        def __enter__(self):
            self.acquire()
            return self
        
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.release()
else:
    import fcntl
    class CrossPlatformLock:
        def __init__(self, lock_file):
            self.lock_file = lock_file
            self.file_handle = None
            self.lock_acquired = False
        
        def acquire(self):
            try:
                lock_dir = os.path.dirname(self.lock_file)
                if lock_dir and not os.path.exists(lock_dir):
                    os.makedirs(lock_dir, exist_ok=True)
                
                self.file_handle = open(self.lock_file, 'w')
                fcntl.flock(self.file_handle.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
                self.file_handle.write(f"pid={os.getpid()}\n")
                self.file_handle.write(f"time={time.time()}\n")
                self.file_handle.flush()
                self.lock_acquired = True
                return True
            except:
                if self.file_handle:
                    self.file_handle.close()
                return False
        
        def release(self):
            if self.file_handle and self.lock_acquired:
                try:
                    fcntl.flock(self.file_handle.fileno(), fcntl.LOCK_UN)
                    self.file_handle.close()
                except:
                    pass
                try:
                    os.remove(self.lock_file)
                except:
                    pass
                self.lock_acquired = False
        
        def __enter__(self):
            self.acquire()
            return self
        
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.release()

def get_broker(client_code: str, config: Config):
    """Factory method to get appropriate broker instance"""
    broker_type = config.get_client_broker(client_code)
    credentials = config.get_client_credentials(client_code)
    
    if broker_type == 'zerodha':
        return ZerodhaBroker(credentials, client_code)
    else:
        return FirstockBroker(credentials, client_code)

def main():
    """Main execution function"""
    if len(sys.argv) != 2:
        print(f"Usage: python {sys.argv[0]} <client_code>")
        print("Available clients:")
        config = Config()
        for client_code in config.get_all_clients().keys():
            print(f"  - {client_code}")
        sys.exit(1)
    
    client_code = sys.argv[1]
    
    # Load configuration
    try:
        config = Config()
    except Exception as e:
        print(f"[ERROR] Failed to load configuration: {e}")
        sys.exit(1)
    
    # Check if client exists
    if not config.get_client(client_code):
        print(f"[ERROR] Unknown client code: {client_code}")
        print(f"Available clients: {list(config.get_all_clients().keys())}")
        sys.exit(1)
    
    # Process locking
    lock_dir = config.get_lock_dir()
    lock_file = os.path.join(lock_dir, f"trading_bot_{client_code}.lock")
    
    lock = CrossPlatformLock(lock_file)
    if not lock.acquire():
        print(f"[SKIP] Another instance for client {client_code} is already running")
        sys.exit(0)
    
    try:
        # Initialize components
        logger = TradingLogger(client_code)
        broker = get_broker(client_code, config)
        
        # Get client configuration
        symbol_properties = {}
        for symbol in ['NIFTY', 'SENSEX']:
            symbol_properties[symbol] = config.get_symbol_config(client_code, symbol)
        
        global_limits = config.get_client_limits(client_code)
        
        # Set dynamic profit
        broker.dynamic_profit_enabled = global_limits.get('dynamic_profit_enabled', False)
        
        # Get folder paths - single watch folder for all
        watch_folder = config.get_watch_folder()
        processed_folder = config.get_processed_folder(client_code)
        
        # Log start
        ist = pytz.timezone('Asia/Kolkata')
        now = datetime.now(ist).strftime('%Y-%m-%d %H:%M:%S')
        logger.info(f"=== Starting trading bot for client: {client_code} ===")
        logger.info(f"Platform: {platform.system()} {platform.release()}")
        logger.info(f"Broker: {config.get_client_broker(client_code)}")
        logger.info(f"Client ID: {broker.client_id}")
        logger.info(f"Watch Folder: {watch_folder}")
        logger.info(f"Processed Folder: {processed_folder}")
        logger.info(f"Lock File: {lock_file}")
        logger.info(f"Start Time: {now}")
        
        # Create necessary directories
        os.makedirs(watch_folder, exist_ok=True)
        os.makedirs(processed_folder, exist_ok=True)
        
        # Run processor
        processor = FileProcessor(
            client_code=client_code,
            broker=broker,
            symbol_properties=symbol_properties,
            global_limits=global_limits,
            watch_folder=watch_folder,
            processed_folder=processed_folder,
            config=config
        )
        processor.process_files()
        
        # Log completion
        now = datetime.now(ist).strftime('%Y-%m-%d %H:%M:%S')
        logger.info(f"=== Completed processing for client: {client_code} at {now} ===")
        
    except KeyboardInterrupt:
        print(f"\n[INFO] Bot stopped by user for client: {client_code}")
    except Exception as e:
        print(f"[ERROR] Fatal error for client {client_code}: {e}")
        import traceback
        traceback.print_exc()
        sys.exit(1)
    finally:
        lock.release()

if __name__ == "__main__":
    main()