import sys
import yfinance as yf
import pandas as pd
import numpy as np
import pandas_ta as ta  # Import pandas_ta
from PyQt5.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QHBoxLayout,
    QLabel, QPushButton, QLineEdit, QTableWidget, QTableWidgetItem,
    QHeaderView, QAbstractItemView, QMessageBox, QCheckBox
)
from PyQt5.QtGui import QIcon, QFont
from PyQt5.QtCore import Qt, QTimer, QThreadPool, QRunnable, pyqtSlot, QObject, pyqtSignal
import traceback

nfo_stocks = [
    "NSE:AARTIDRUGS",
    "NSE:AARTIIND",
    "NSE:AARTIPHARM","NSE:ABB",
    "NSE:ABBOTINDIA",
    "NSE:ABCAPITAL",
    "NSE:ABFRL",
    "NSE:ACC","NSE:ADANIENT",
]

stock_list = []

def transform_stock_name(name):
    # Remove the prefix 'NSE:' or 'BSE:' and add appropriate suffix
    if 'NSE:' in name:
        name = name.split('NSE:')[1]
        if '-' in name:
            name = name.split('-')[0]
        name += '.NS'
    elif 'BSE:' in name:
        name = name.split('BSE:')[1]
        name += '.BO'      
    return name

class WorkerSignals(QObject):
    result = pyqtSignal(list)  # Signal to send the result
    error = pyqtSignal(str)    # Signal to send any error messages

class Worker(QRunnable):
    def __init__(self, symbols, rsi_threshold, macd_condition, momentum_condition):
        super().__init__()
        self.symbols = symbols
        self.rsi_threshold = rsi_threshold
        self.macd_condition = macd_condition
        self.momentum_condition = momentum_condition
        self.signals = WorkerSignals()

    @pyqtSlot()
    def run(self):
        data_list = []
        try:
            for symbol in self.symbols:
                try:
                    print(f"Processing {symbol}")
                    ticker = yf.Ticker(symbol)
                    hist = ticker.history(period='1y', interval='1d')  # Fetch one year of daily data

                    # Skip if no data is returned
                    if hist.empty:
                        print(f"No data for {symbol}")
                        continue

                    # Calculate indicators
                    hist['RSI'] = ta.rsi(hist['Close'], length=14)
                    macd = ta.macd(hist['Close'])
                    hist['MACD'] = macd['MACD_12_26_9']
                    hist['MACD_signal'] = macd['MACDs_12_26_9']
                    hist['Momentum'] = ta.mom(hist['Close'], length=10)

                    # Drop rows with NaN values in indicators
                    hist = hist.dropna(subset=['RSI', 'MACD', 'MACD_signal', 'Momentum'])

                    if hist.empty:
                        print(f"No valid data after dropping NaNs for {symbol}")
                        continue

                    # Get the latest data point
                    last_row = hist.iloc[-1]

                    # Extract required values
                    last_close = last_row['Close']
                    prev_close = hist['Close'].iloc[-2]
                    day_high = last_row['High']
                    day_low = last_row['Low']
                    volume = last_row['Volume']
                    rsi = last_row['RSI']
                    macd_value = last_row['MACD']
                    macd_signal = last_row['MACD_signal']
                    momentum = last_row['Momentum']

                    # Percentage change from previous close
                    perc_change = ((last_close - prev_close) / prev_close) * 100

                    # Apply filters based on user inputs
                    condition = True  # Start with True and apply conditions

                    # Apply RSI filter
                    if self.rsi_threshold is not None:
                        condition = condition and (rsi <= self.rsi_threshold)

                    # Apply MACD filter
                    if self.macd_condition:
                        condition = condition and (macd_value > macd_signal)

                    # Apply Momentum filter
                    if self.momentum_condition:
                        condition = condition and (momentum > 0)

                    if condition:
                        data_list.append({
                            'Symbol': symbol,
                            'Last Close': round(last_close, 2),
                            'Change %': round(perc_change, 2),
                            'RSI': round(rsi, 2),
                            'MACD': round(macd_value, 2),
                            'Momentum': round(momentum, 2),
                            'Volume': int(volume)
                        })
                except Exception as e:
                    print(f"Error fetching data for {symbol}: {e}")
                    continue
            # Emit the result
            self.signals.result.emit(data_list)
        except Exception as e:
            traceback.print_exc()
            # Emit any error messages
            self.signals.error.emit(str(e))

class StockScannerApp(QWidget):
    def __init__(self):
        global stock_list
        super().__init__()
        self.setWindowTitle('STOCK SCANNER')
        self.setGeometry(100, 100, 1000, 600)
        self.setStyleSheet("background-color: rgba(173, 216, 230, 0.9);")  # Semi-transparent light blue

        # Predefined stock list
        self.stocknames = stock_list

        self.setup_ui()

        # Thread pool for running background tasks
        self.threadpool = QThreadPool()

        # Timer to refresh the data every 1 minute (60000 milliseconds)
        self.timer = QTimer()
        self.timer.setInterval(60000)  # 1 minute interval
        self.timer.timeout.connect(self.start_scan_stocks)
        self.timer.start()

    def setup_ui(self):
        # Set up main layout
        self.layout = QVBoxLayout()
        self.setLayout(self.layout)

        # Title Label
        self.title_label = QLabel('Stock Scanner for Indian Market')
        self.title_label.setFont(QFont('Arial', 16))
        self.title_label.setAlignment(Qt.AlignCenter)
        self.layout.addWidget(self.title_label)

        # Filter Inputs Layout
        self.filter_layout = QHBoxLayout()
        self.layout.addLayout(self.filter_layout)

        # RSI Threshold Input
        self.rsi_label = QLabel('RSI <= ')
        self.rsi_input = QLineEdit('70')  # Default value set to 70
        self.rsi_input.setFixedWidth(50)
        self.filter_layout.addWidget(self.rsi_label)
        self.filter_layout.addWidget(self.rsi_input)

        # MACD Condition Checkbox
        self.macd_checkbox = QCheckBox('MACD > Signal')
        self.macd_checkbox.setChecked(True)
        self.filter_layout.addWidget(self.macd_checkbox)

        # Momentum Condition Checkbox
        self.momentum_checkbox = QCheckBox('Momentum > 0')
        self.momentum_checkbox.setChecked(True)
        self.filter_layout.addWidget(self.momentum_checkbox)

        # Scan Button
        self.scan_button = QPushButton('Scan Stocks')
        self.scan_button.setFixedSize(150, 50)  # Set fixed size
        self.scan_button.setStyleSheet("""
            QPushButton {
                background-color: #3498db;  /* Button background /
                color: black ; /white;               / Text color /
                border-radius: 10px;        / Rounded corners /
                font-size: 16px;            / Font size /
                padding: 10px 20px;         / Padding around the text / 
            }
            QPushButton:hover {
                background-color:  #FFFF00 ; /#2980b9;  / Change color on hover */
            }
        """)
        self.scan_button.clicked.connect(self.start_scan_stocks)
        self.layout.addWidget(self.scan_button)

        # Results Table
        self.results_table = QTableWidget()
        self.results_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.results_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.layout.addWidget(self.results_table)

    def start_scan_stocks(self):
        # Use the predefined stocknames list
        symbols = self.stocknames

        # Retrieve filter parameters from the GUI
        try:
            rsi_threshold = float(self.rsi_input.text())
        except ValueError:
            QMessageBox.warning(self, 'Input Error', 'Please enter a valid number for RSI threshold.')
            return

        macd_condition = self.macd_checkbox.isChecked()
        momentum_condition = self.momentum_checkbox.isChecked()

        # Disable the Scan button to prevent multiple clicks
        self.scan_button.setEnabled(False)

        # Create a Worker object
        worker = Worker(symbols, rsi_threshold, macd_condition, momentum_condition)
        worker.signals.result.connect(self.on_scan_result)
        worker.signals.error.connect(self.on_scan_error)

        # Start the worker in the thread pool
        self.threadpool.start(worker)

    def on_scan_result(self, data_list):
        # Re-enable the Scan button
        self.scan_button.setEnabled(True)

        if data_list:
            self.populate_table(data_list)
        else:
            QMessageBox.information(self, 'No Results', 'No stocks met the criteria.')
            # Clear the table if no results
            self.results_table.clear()
            headers = ['Symbol', 'Last Close', 'Change %', 'RSI', 'MACD', 'Momentum', 'Volume']
            self.results_table.setColumnCount(len(headers))
            self.results_table.setHorizontalHeaderLabels(headers)
            self.results_table.setRowCount(0)

    def on_scan_error(self, error_message):
        # Re-enable the Scan button
        self.scan_button.setEnabled(True)
        QMessageBox.critical(self, 'Error', f'An error occurred:\n{error_message}')

    def populate_table(self, data_list):
        self.results_table.clear()
        headers = ['Symbol', 'Last Close', 'Change %', 'RSI', 'MACD', 'Momentum', 'Volume']
        self.results_table.setColumnCount(len(headers))
        self.results_table.setHorizontalHeaderLabels(headers)
        self.results_table.setRowCount(len(data_list))

        for row_idx, data in enumerate(data_list):
            for col_idx, header in enumerate(headers):
                value = str(data[header])
                cell = QTableWidgetItem(value)
                self.results_table.setItem(row_idx, col_idx, cell)

def main():
    global nfo_stocks
    global stock_list
    stock_list = []
    for stock in nfo_stocks:
        new_name = transform_stock_name(stock)
        stock_list.append(new_name)

    app = QApplication(sys.argv)
    window = StockScannerApp()
    window.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

i want to print 'Last Refreshed Time' on the window so that user can know when the window was refreshed .