# google_sheet_handler.py

import os
import logging
import gspread
import pandas as pd
from oauth2client.service_account import ServiceAccountCredentials
from config import Config, COLUMN_MAP, CREDENTIALS_FILE 
from helpers import retry_on_failure, _get_col_letter

class GoogleSheetHandler:
    """
    Kapselt alle Interaktionen mit dem Google Sheet.
    Finale, robuste Version v2.1.2
    """
    def __init__(self, sheet_url=None):
        self.logger = logging.getLogger(__name__ + ".GoogleSheetHandler")
        self.logger.info("Initialisiere GoogleSheetHandler...")
        self.sheet_url = sheet_url or Config.SHEET_URL
        if "docs.google.com" not in self.sheet_url:
             raise ValueError(f"Ungültige Google Sheet URL: '{self.sheet_url}'")
        self.client = None
        self.sheet = None
        self._all_data_with_headers = []
        self._header_rows = 5

    @retry_on_failure
    def _connect(self):
        if self.client: return True
        self.logger.info("Stelle neue Verbindung mit Google Sheets her...")
        try:
            if not os.path.exists(CREDENTIALS_FILE):
                 raise FileNotFoundError(f"Credential-Datei nicht gefunden: {CREDENTIALS_FILE}")
            creds = ServiceAccountCredentials.from_json_keyfile_name(CREDENTIALS_FILE, ["https://www.googleapis.com/auth/spreadsheets"])
            self.client = gspread.authorize(creds)
            spreadsheet = self.client.open_by_url(self.sheet_url)
            self.sheet = spreadsheet.sheet1
            self.logger.info("Verbindung erfolgreich.")
            return True
        except Exception as e:
            self.logger.error(f"FEHLER bei Google Sheets Verbindung: {e}")
            self.client = None
            return False

    @retry_on_failure
    def load_data(self):
        if not self.client and not self._connect(): return False
        self.logger.info("Lade Daten aus dem Haupt-Sheet ('Tabelle1')...")
        try:
            self._all_data_with_headers = self.sheet.get_all_values()
            self.logger.info(f"Daten geladen: {len(self._all_data_with_headers)} Zeilen.")
            for i, row in enumerate(self._all_data_with_headers):
                if "CRM Name" in row:
                    self._header_rows = i + 1
                    break
            return True
        except Exception as e:
            self.logger.critical(f"Fehler beim Laden der Sheet Daten: {e}")
            return False

    def get_all_data_with_headers(self):
        return self._all_data_with_headers.copy()

    def get_sheet_as_dataframe(self, sheet_name):
        """
        Liest ein komplettes Tabellenblatt und gibt es als Pandas DataFrame zurück.
        NEU: Funktioniert auch, wenn die Header-Zeile doppelte Spaltennamen enthält.
        """
        try:
            if not self.client and not self._connect(): return None
            
            self.logger.debug(f"Lese Tabellenblatt '{sheet_name}' als DataFrame...")
            worksheet = self.client.open_by_url(self.sheet_url).worksheet(sheet_name)
            
            # Lese alle Werte als Liste von Listen, das ist robuster
            all_values = worksheet.get_all_values()
            
            if not all_values:
                self.logger.warning(f"Tabellenblatt '{sheet_name}' ist leer. Erstelle leeren DataFrame.")
                return pd.DataFrame()

            # Nimm die erste Zeile als Header und die restlichen als Daten
            header = all_values[0]
            data = all_values[1:]
            
            df = pd.DataFrame(data, columns=header)
            self.logger.info(f"{len(df)} Zeilen aus '{sheet_name}' als DataFrame geladen.")
            return df
        except gspread.exceptions.WorksheetNotFound:
            self.logger.warning(f"Tabellenblatt '{sheet_name}' nicht gefunden. Erstelle leeren DataFrame.")
            return pd.DataFrame()
        except Exception as e:
            self.logger.error(f"Fehler beim Lesen des Sheets '{sheet_name}' als DataFrame: {e}")
            return None

    def append_rows(self, sheet_name, values):
        try:
            if not self.client and not self._connect(): return False
            worksheet = self.client.open_by_url(self.sheet_url).worksheet(sheet_name)
            worksheet.append_rows(values, value_input_option='USER_ENTERED')
            self.logger.info(f"{len(values)} Zeilen erfolgreich an '{sheet_name}' angehängt.")
            return True
        except Exception as e:
            self.logger.error(f"Fehler beim Anhängen von Zeilen an das Sheet '{sheet_name}': {e}")
            return False
            
    def clear_and_write_data(self, sheet_name, data):
        try:
            if not self.client and not self._connect(): return False
            worksheet = self.client.open_by_url(self.sheet_url).worksheet(sheet_name)
            worksheet.clear()
            if not data:
                self.logger.warning("Keine Daten zum Schreiben in '{sheet_name}' vorhanden.")
                return True
            end_col_letter = _get_col_letter(len(data[0]))
            range_to_update = f'A1:{end_col_letter}{len(data)}'
            worksheet.update(range_name=range_to_update, values=data)
            self.logger.info(f"Schreiben von {len(data)} Zeilen in '{sheet_name}' erfolgreich.")
            return True
        except Exception as e:
            self.logger.error(f"Fehler bei clear_and_write_data für '{sheet_name}': {e}")
            return False
            
    def batch_update_cells(self, update_data):
        if not self.sheet and not self._connect():
            self.logger.error("FEHLER: Keine Sheet-Verbindung fuer Batch-Update.")
            return False
        if not update_data:
            return True
            
        sanitized_update_data = []
        for item in update_data:
            if 'range' in item and 'values' in item and isinstance(item['values'], list):
                sanitized_values = [[str(cell) if cell is not None else "" for cell in row] for row in item['values']]
                sanitized_update_data.append({'range': item['range'], 'values': sanitized_values})
        
        if not sanitized_update_data: return True
        
        total_cells = sum(len(row) for item in sanitized_update_data for row in item.get('values', []))
        self.logger.debug(f"Sende Batch-Update mit {len(sanitized_update_data)} Anfragen ({total_cells} Zellen)...")
        self.sheet.batch_update(sanitized_update_data, value_input_option='USER_ENTERED')
        self.logger.info(f"Batch-Update mit {total_cells} Zellen erfolgreich gesendet.")
        return True