import os
import requests
import gspread
import logging
import json
from google.oauth2.service_account import Credentials
from dotenv import load_dotenv

load_dotenv()

# Налаштування
HUGEPROFIT_TOKEN = os.getenv("HUGEPROFIT_TOKEN")
CRM_API_URL = "https://crm.h-profit.com/bapi"
GOOGLE_SHEET_ID = os.getenv("GOOGLE_SHEET_ID")

# --- ЛОГУВАННЯ ---
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s", 
    handlers=[logging.FileHandler("sync_log_crm.log", encoding='utf-8'), logging.StreamHandler()]
)
logger = logging.getLogger(__name__)

# Підключення
scopes = ["https://www.googleapis.com/auth/spreadsheets", "https://www.googleapis.com/auth/drive"]
creds = Credentials.from_service_account_file("wheelstore-drive-bot-2d1ebc787bf7.json", scopes=scopes)
client = gspread.authorize(creds)

def get_col_letter(col_idx):
    """Перетворює індекс колонки (0, 1, 2) в літеру (A, B, C)"""
    return chr(65 + col_idx)

def safe_write(row_list, mapping, col_name, value):
    """Безпечний запис у список рядка, якщо колонка існує"""
    if col_name in mapping:
        row_list[mapping[col_name]] = value

def sync_products():
    try:
        logger.info("📡 Підключаємось до Google таблиці...")
        sheet = client.open_by_key(GOOGLE_SHEET_ID).worksheet("CRM")
        
        # --- ЕТАП 0: ОТРИМАННЯ ЗАГОЛОВКІВ ---
        headers = sheet.row_values(1)
        header_map = {name.strip(): index for index, name in enumerate(headers)}
        
        required_cols = ["ID", "Назва", "Категорія", "Ціна", "Кількість"]
        for col in required_cols:
            if col not in header_map:
                logger.error(f"❌ У таблиці відсутня обов'язкова колонка: {col}")
                return

        # --- ЕТАП 1: ОТРИМАННЯ ТОВАРІВ З CRM ---
        logger.info("📥 Починаємо завантаження товарів з CRM...")
        products = []
        offset = 0
        
        while True:
            r = requests.get(
                f"{CRM_API_URL}/products", 
                headers={"Authorization": HUGEPROFIT_TOKEN}, 
                params={"limit": 100, "offset": offset}
            )
            
            if r.status_code != 200: 
                logger.error(f"❌ CRM Error: {r.status_code}")
                break
            
            data = r.json().get("data", [])
            if not data: break
                
            products.extend(data)
            offset += 100
            logger.info(f"   Завантажено {len(products)} товарів...")

        logger.info(f"✅ Всього з CRM: {len(products)}.")

        # Створюємо набір (set) ID, які є в CRM, для швидкого пошуку
        crm_ids_set = set()

        # --- ЕТАП 2: ОТРИМАННЯ ДАНИХ З ТАБЛИЦІ ---
        logger.info("📖 Читаємо ID з Google Sheet...")
        existing_ids_col = sheet.col_values(1) 
        
        id_to_row = {}
        # Пропускаємо заголовок (i=0 -> Row 1)
        for i, val in enumerate(existing_ids_col):
            if i == 0: continue 
            if val.strip().isdigit():
                id_to_row[int(val.strip())] = i + 1

        # --- ЕТАП 3: СПІВСТАВЛЕННЯ (UPDATE & ADD) ---
        batch_updates = []
        new_rows_to_add = []
        
        updated_count = 0
        new_count = 0

        logger.info("🔄 Обробка даних (Оновлення та додавання)...")

        for p in products:
            crm_id = p.get("id")
            if crm_id is None: continue
            
            crm_ids_set.add(crm_id) # Запам'ятовуємо, що цей ID живий

            name = p.get("name", "")
            
            # --- Категорія ---
            raw_cat = p.get("category")
            category_name = "Інше"
            if isinstance(raw_cat, list) and len(raw_cat) > 0:
                category_name = raw_cat[0].get("name", "Інше")
            elif isinstance(raw_cat, dict):
                category_name = raw_cat.get("name", "Інше")
            
            # --- Stock & Price ---
            stock_data = p.get("stock", [{}])
            if isinstance(stock_data, list) and len(stock_data) > 0:
                stock_data = stock_data[0]
            elif not isinstance(stock_data, dict):
                stock_data = {}

            qty = stock_data.get("quantity") or stock_data.get("instock") or 0
            price = float(stock_data.get("sale_price") or stock_data.get("price") or 0.0)
            
            # --- Дод. поля ---
            af = p.get("af", {})
            
            image_url = p.get("main_image")
            if not image_url:
                images_list = p.get("images", [])
                if isinstance(images_list, list) and len(images_list) > 0:
                    image_url = images_list[0]
                else:
                    image_url = ""
            
            comment = af.get("Коментар", "")
            if not comment: comment = p.get("description", "") or ""
            
            discount = 0
            if isinstance(af.get("custom_price"), dict):
                discount = af.get("custom_price", {}).get("Знижка", 0)

            hidden_status = af.get("Не показувати на сайті", "FALSE")
            if hidden_status is None: hidden_status = "FALSE"
            
            # --- ЛОГІКА ---
            row_num = id_to_row.get(crm_id)

            if row_num:
                # --- UPDATE ---
                batch_updates.append({
                    "range": f"F{row_num}:H{row_num}",
                    "values": [[qty, qty, price]]
                })
                batch_updates.append({
                    "range": f"O{row_num}:P{row_num}",
                    "values": [[discount, comment]]
                })

                if "Не показувати" in header_map:
                    col_idx = header_map["Не показувати"]
                    col_letter = get_col_letter(col_idx)
                    batch_updates.append({
                        "range": f"{col_letter}{row_num}",
                        "values": [[hidden_status]]
                    })
                updated_count += 1
            else:
                # --- ADD ---
                new_row = [''] * len(headers)
                safe_write(new_row, header_map, "ID", crm_id)
                safe_write(new_row, header_map, "Назва", name)
                safe_write(new_row, header_map, "Категорія", category_name)
                safe_write(new_row, header_map, "Кількість", qty)
                safe_write(new_row, header_map, "Доступно", qty)
                safe_write(new_row, header_map, "Ціна", price)
                safe_write(new_row, header_map, "Знижка", discount)
                safe_write(new_row, header_map, "Коментар", comment)
                safe_write(new_row, header_map, "Зображення", image_url)
                safe_write(new_row, header_map, "Не показувати", hidden_status)
                
                new_rows_to_add.append(new_row)
                new_count += 1

        # --- ВИКОНАННЯ ОНОВЛЕНЬ І ДОДАВАНЬ ---
        if batch_updates:
            logger.info(f"✍️ Оновлюємо {len(batch_updates)} комірок...")
            sheet.batch_update(batch_updates, value_input_option="USER_ENTERED")
        
        if new_rows_to_add:
            logger.info(f"➕ Додаємо {len(new_rows_to_add)} нових товарів...")
            sheet.append_rows(new_rows_to_add, value_input_option="USER_ENTERED")

        # --- ЕТАП 4: ВИДАЛЕННЯ (DELETE) ---
        # Знаходимо ID, які є в таблиці, але НЕМАЄ в CRM
        rows_to_delete = []
        for sheet_id, r_num in id_to_row.items():
            if sheet_id not in crm_ids_set:
                rows_to_delete.append(r_num)
        
        # Сортуємо у зворотному порядку (від найбільшого до найменшого)
        # Це критично важливо! Якщо видалити рядок 5, то рядок 6 стане 5-м.
        # Видаляючи з кінця, ми не ламаємо нумерацію.
        rows_to_delete.sort(reverse=True)
        
        if rows_to_delete:
            logger.info(f"🗑 Виявлено {len(rows_to_delete)} видалених товарів. Очищаємо таблицю...")
            for r_num in rows_to_delete:
                try:
                    sheet.delete_rows(r_num)
                    logger.info(f"   - Видалено рядок {r_num}")
                except Exception as del_err:
                    logger.error(f"   ❌ Помилка видалення рядка {r_num}: {del_err}")
        
        logger.info(f"🏁 Синхронізація завершена. Оновлено: {updated_count}, Додано: {new_count}, Видалено: {len(rows_to_delete)}")

    except Exception as e: 
        logger.exception("🔥 КРИТИЧНА ПОМИЛКА:")

if __name__ == "__main__":
    sync_products()