#!/usr/bin/env python3
"""
NEFT file processing scheduler.
Runs polling loop every 30 minutes to process new files.
"""

import signal
import time
import sys
from datetime import datetime
from logging_config import get_logger, setup_logging
from config import get_config
from db import OracleConnector, Repository
from sftp import SFTPClient, FileMonitor
from processors import FileProcessor

logger = get_logger(__name__)


class Scheduler:
    """Main scheduler for NEFT file processing."""

    def __init__(self):
        """Initialize scheduler."""
        self.config = get_config()
        self.config.validate()
        self.running = True
        self.cycle_count = 0

        # Setup signal handlers for graceful shutdown
        signal.signal(signal.SIGTERM, self._signal_handler)
        signal.signal(signal.SIGINT, self._signal_handler)

    def _signal_handler(self, signum, frame):
        """Handle shutdown signals gracefully."""
        logger.info(f"Received signal {signum}, shutting down gracefully...")
        self.running = False

    def initialize_database(self):
        """Initialize database connection and verify tables exist."""
        try:
            connector = OracleConnector()
            if connector.test_connection():
                logger.info("Database connection test passed")
                repository = Repository()
                repository.verify_tables_exist()
                return True
            else:
                logger.error("Database connection test failed")
                return False
        except SystemExit as e:
            logger.error(f"Database initialization failed: {e}")
            raise
        except Exception as e:
            logger.error(f"Error initializing database: {e}", exc_info=True)
            return False

    def run_processing_cycle(self):
        """Run single file processing cycle."""
        self.cycle_count += 1
        logger.info(f"=== Starting processing cycle {self.cycle_count} ===")

        sftp_client = SFTPClient()
        repository = Repository()

        try:
            # Connect to SFTP
            if not sftp_client.connect():
                logger.error("Failed to connect to SFTP server")
                return

            # Scan for new files across all banks
            monitor = FileMonitor(sftp_client)
            new_files = []
            today_str = datetime.now().strftime("%d%m%Y")
            logger.info(f'listing file for {today_str}')

            for bank_code in self.config.bank_codes:
                # Get list of files already processed for this specific bank
                bank_processed = repository.get_processed_files(bank_code)
                remote_path = f"{self.config.sftp_base_path}/{bank_code}/NEFT"
               
                
                pattern = f"{today_str}_*_NEFT_OUTWARD.TXT"
                files = sftp_client.list_files(remote_path, pattern=pattern)


                for filename in files:
                    if filename not in bank_processed:
                        full_path = f"{remote_path}/{filename}"
                        new_files.append((filename, bank_code, full_path))
                        logger.info(f"Found new file: {filename} (bank: {bank_code})")
                    else:
                        logger.debug(f"Skipping already processed file for {bank_code}: {filename}")

            if not new_files:
                logger.info("No new files to process")
                return

            logger.info(f"Found {len(new_files)} new files to process")

            # Process files
            processor = FileProcessor(repository, sftp_client)
            stats = processor.process_files(new_files)

            # Log summary
            logger.info(f"Cycle {self.cycle_count} complete:")
            logger.info(f"  Total files: {stats['total']}")
            logger.info(f"  Successful: {stats['successful']}")
            logger.info(f"  Failed: {stats['failed']}")

            # Call neft_api_txn_post procedure once per cycle to process all inserted transactions
            if stats['successful'] > 0:
                logger.info("Calling neft_api_txn_post procedure for all inserted transactions...")
                if repository.call_neft_api_txn_post():
                    logger.info("Transaction post-processing completed successfully")
                else:
                    logger.error("Transaction post-processing failed")

        except Exception as e:
            logger.error(f"Error in processing cycle: {e}", exc_info=True)

        finally:
            sftp_client.disconnect()

    def run(self):
        """Run scheduler main loop."""
        logger.info("="*80)
        logger.info("NEFT_OUTWARD File Processing Scheduler Started")
        logger.info(f"Poll Interval: {self.config.poll_interval_minutes} minutes")
        logger.info(f"Bank Codes: {', '.join(self.config.bank_codes)}")
        logger.info("="*80)

        # Initialize database
        try:
            if not self.initialize_database():
                logger.error("Failed to initialize database. Exiting.")
                return
        except SystemExit as e:
            logger.error(f"Fatal error: {e}")
            raise

        # Run processing loop
        poll_interval_seconds = self.config.poll_interval_minutes * 60

        while self.running:
            try:
                self.run_processing_cycle()
            except Exception as e:
                logger.error(f"Unexpected error in processing cycle: {e}", exc_info=True)

            # Wait for next cycle
            if self.running:
                logger.info(f"Waiting {self.config.poll_interval_minutes} minutes until next cycle...")
                time.sleep(poll_interval_seconds)

        logger.info("Scheduler shutdown complete")


def main():
    """Main entry point."""
    # Setup logging
    setup_logging()

    # Create and run scheduler
    scheduler = Scheduler()
    scheduler.run()


if __name__ == '__main__':
    main()
