def fetch_stock_data(ticker, start_date, end_date=None):
    """Fetch historical stock data with optional end date."""
    try:
        # Normalize datetime handling
        start_date = pd.to_datetime(start_date)
        if end_date:
            end_date = pd.to_datetime(end_date)
            # Remove timezone info if present
            end_date = end_date.tz_localize(None) if end_date.tzinfo else end_date
        else:
            end_date = pd.Timestamp.now().normalize()
        
        # Remove timezone info from start_date if present
        start_date = start_date.tz_localize(None) if start_date.tzinfo else start_date
        
        ticker = ticker.strip().upper()
        
        # Add basic ticker validation
        if not ticker.isalnum():  # Check if ticker contains only letters and numbers
            raise ValueError(f"Invalid ticker symbol: {ticker}")
        
        today = pd.Timestamp.now().normalize()
        logger.info(f"Fetching data for ticker: {ticker} starting from {start_date.date()}")

        # First verify ticker exists and get its earliest available date from YFinance
        try:
            # Try downloading a small sample of data to validate ticker
            test_data = yf.download(
                ticker,
                start=today - pd.Timedelta(days=5),
                end=today,
                progress=False,
                auto_adjust=False,
                timeout=30
            )
            
            if test_data.empty:
                raise ValueError(f"No data available from YFinance for {ticker}")
            
            # Get full history to determine earliest date
            yf_ticker = yf.Ticker(ticker)
            yf_history = yf_ticker.history(period="max", interval="1d")
            
            earliest_yf_date = yf_history.index[0].tz_localize(None)  # Remove timezone info
            logger.info(f"YFinance has data for {ticker} from {earliest_yf_date.date()}")
            
            # Convert start_date to naive datetime for comparison
            start_date = start_date.tz_localize(None) if start_date.tzinfo else start_date
            
            # If requested start date is earlier than YFinance's earliest date, adjust it
            if start_date < earliest_yf_date:
                logger.warning(
                    f"Requested start_date {start_date.date()} is earlier than available YFinance data. "
                    f"Adjusting start_date to {earliest_yf_date.date()}."
                )
                start_date = earliest_yf_date
            
        except requests.exceptions.RequestException as e:
            logger.error(f"Network error while validating {ticker}: {str(e)}")
            raise ValueError(f"Network error validating ticker: {ticker}")
        except Exception as e:
            logger.error(f"Error validating ticker {ticker} with YFinance: {str(e)}")
            raise ValueError(f"Invalid ticker symbol: {ticker}")

        with get_db_session() as db:
            # Check if ticker exists in market_tickers table
            ticker_exists = db.execute(
                text("SELECT COUNT(*) FROM market_tickers WHERE ticker = :ticker"),
                {"ticker": ticker}
            ).scalar()

            # Retrieve sector information
            sector_query = text("""
                SELECT gics_sector, gics_sub_industry 
                FROM market_tickers 
                WHERE ticker = :ticker
            """)
            sector_info = db.execute(sector_query, {"ticker": ticker}).first()
            if sector_info:
                gics_sector, gics_sub_industry = sector_info
                logger.debug(f"Sector info for {ticker}: {gics_sector}, {gics_sub_industry}")
            else:
                gics_sector, gics_sub_industry = (None, None)
                logger.warning(f"No sector information found for {ticker}")

            # Get date range from database
            date_range_query = text("""
                SELECT MIN(date) AS min_date, MAX(date) AS max_date
                FROM stock_data
                WHERE ticker = :ticker
            """)
            date_range = db.execute(date_range_query, {"ticker": ticker}).first()
            min_date_db, max_date_db = date_range.min_date, date_range.max_date

            if min_date_db and max_date_db:
                # Convert database dates to naive datetime for comparison
                min_date_db = pd.to_datetime(min_date_db).tz_localize(None)
                max_date_db = pd.to_datetime(max_date_db).tz_localize(None)
                
                logger.info(f"Database has data for {ticker} from {min_date_db.date()} to {max_date_db.date()}")
                
                # If database's earliest date is later than start_date, fetch historical data from YFinance
                if min_date_db > start_date:
                    logger.info(f"Fetching historical data from YFinance for {ticker} ({start_date.date()} to {min_date_db.date()})")
                    historical_data = yf.download(
                        ticker,
                        start=start_date,
                        end=min_date_db + pd.Timedelta(days=1),  # Add 1 day buffer
                        progress=False,
                        auto_adjust=False,
                        timeout=30
                    )
                    
                    if not historical_data.empty:
                        historical_data['Adj Close'] = historical_data['Close']
                        if sector_info:
                            historical_data['gics_sector'] = gics_sector
                            historical_data['gics_sub_industry'] = gics_sub_industry
                        save_stock_data_to_db(ticker, historical_data)
                        logger.info(f"Saved {len(historical_data)} historical records for {ticker}")

                # Rest of the existing function logic remains the same...
                # Adjust start_date if it's earlier than the earliest date in the database
                final_start_date = max(start_date, earliest_yf_date)
                if min_date_db:
                    final_start_date = max(final_start_date, pd.to_datetime(min_date_db).tz_localize(None))

                if final_start_date > start_date:
                    logger.warning(
                        f"Requested start_date {start_date.date()} is earlier than available data. "
                        f"Adjusting start_date to {final_start_date.date()}."
                    )

                # Fetch data from the database
                stock_query = text("""
                    SELECT date, open, high, low, close, volume
                    FROM stock_data 
                    WHERE ticker = :ticker 
                    AND date >= :start_date
                    ORDER BY date
                """)
                result = db.execute(stock_query, {"ticker": ticker, "start_date": final_start_date})
                db_data = pd.DataFrame(result.fetchall(), columns=['Date', 'Open', 'High', 'Low', 'Close', 'Volume'])
                
                if not db_data.empty:
                    db_data.set_index('Date', inplace=True)
                    db_data['Adj Close'] = db_data['Close']  # Assuming Adjusted Close is same as Close
                    
                    if sector_info:
                        db_data['gics_sector'] = gics_sector
                        db_data['gics_sub_industry'] = gics_sub_industry
                    
                    logger.info(f"Fetched {len(db_data)} records from the database for {ticker}")
                    
                    # Determine if recent data needs to be updated
                    latest_db_date = db_data.index.max()
                    if latest_db_date < today - pd.Timedelta(days=1):
                        # Fetch recent data from YFinance
                        fetch_start = latest_db_date + pd.Timedelta(days=1)
                        logger.info(f"Fetching recent data from YFinance for {ticker} starting from {fetch_start.date()} to {today.date()}")
                        
                        new_data = yf.download(
                            ticker,
                            start=fetch_start,
                            end=today + pd.Timedelta(days=1),  # Inclusive of today
                            progress=False,
                            auto_adjust=False,
                            timeout=30
                        )
                        
                        if not new_data.empty:
                            new_data['Adj Close'] = new_data['Close']  # Assuming Adjusted Close is same as Close
                            if sector_info:
                                new_data['gics_sector'] = gics_sector
                                new_data['gics_sub_industry'] = gics_sub_industry
                            
                            # Save new data to the database
                            save_stock_data_to_db(ticker, new_data)
                            logger.info(f"Fetched and saved {len(new_data)} new records from YFinance for {ticker}")
                            
                            # Append new data to the existing DataFrame
                            db_data = pd.concat([db_data, new_data])
                        else:
                            logger.warning(f"No new data fetched from YFinance for {ticker} since {fetch_start.date()}")
                    
                    # Add validation for data quality
                    if not db_data.empty:
                        # Check for missing values
                        if db_data.isnull().any().any():
                            logger.warning(f"Found missing values in data for {ticker}")
                            db_data = db_data.fillna(method='ffill').fillna(method='bfill')
                        
                        # Verify date continuity
                        date_gaps = (db_data.index[1:] - db_data.index[:-1]).days > 1
                        if date_gaps.any():
                            logger.warning(f"Found date gaps in data for {ticker}")
                    
                    return db_data

            # If no data exists in the database, fetch all data from YFinance
            logger.info(f"No data found in the database for {ticker}. Fetching all historical data from YFinance.")
            stock_data = yf.download(
                ticker,
                start=start_date,
                end=end_date + pd.Timedelta(days=1),  # Add 1 day to include end_date
                progress=False,
                auto_adjust=False,
                timeout=30
            )
            
            if not stock_data.empty:
                stock_data['Adj Close'] = stock_data['Close']  # Assuming Adjusted Close is same as Close
                if sector_info:
                    stock_data['gics_sector'] = gics_sector
                    stock_data['gics_sub_industry'] = gics_sub_industry
                
                # Save fetched data to the database
                save_stock_data_to_db(ticker, stock_data)
                logger.info(f"Fetched and saved {len(stock_data)} records from YFinance for {ticker}")
                
                # Add validation for data quality
                if not stock_data.empty:
                    # Check for missing values
                    if stock_data.isnull().any().any():
                        logger.warning(f"Found missing values in data for {ticker}")
                        stock_data = stock_data.fillna(method='ffill').fillna(method='bfill')
                    
                    # Verify date continuity
                    date_gaps = (stock_data.index[1:] - stock_data.index[:-1]).days > 1
                    if date_gaps.any():
                        logger.warning(f"Found date gaps in data for {ticker}")
                
                return stock_data
            else:
                logger.warning(f"No data available from YFinance for {ticker}")
                return None

    except (ValueError, Exception) as e:
        error_msg = str(e)
        if isinstance(e, ValueError):
            logger.warning(error_msg)
            raise  # Re-raise ValueError for invalid tickers
        else:
            logger.error(f"Failed to fetch data for {ticker}: {error_msg}", exc_info=True)
            return None


check any logic problem of the above code, if so, enhance it, and return full updated code