"""
vprok.ru Windows Playwright Client
====================================
Каждые 30 секунд проверяет сервер-реле на наличие задания.
Если задание есть — открывает vprok.ru и добавляет товары в корзину.

Требования:
    pip install playwright requests
    playwright install chromium
"""

import time
import requests
from playwright.sync_api import sync_playwright, TimeoutError as PwTimeout

# ─── Настройки ───────────────────────────────────────────────────────────────
SERVER_URL = "http://185.130.212.192:5000"
API_KEY    = "vprok2024secret"
POLL_INTERVAL = 30  # секунды между проверками
# ─────────────────────────────────────────────────────────────────────────────

HEADERS = {"X-Api-Key": API_KEY, "Content-Type": "application/json"}


def log(msg: str):
    ts = time.strftime("%H:%M:%S")
    print(f"[{ts}] {msg}", flush=True)


def fetch_task():
    """Забрать задание с сервера. Возвращает dict или None."""
    try:
        r = requests.get(f"{SERVER_URL}/task", headers=HEADERS, timeout=10)
        if r.status_code == 204:
            return None
        if r.status_code == 200:
            return r.json()
        log(f"⚠️  Неожиданный статус от сервера: {r.status_code}")
        return None
    except Exception as e:
        log(f"❌ Ошибка подключения к серверу: {e}")
        return None


def report_done(status: str, message: str):
    """Отправить результат на сервер."""
    try:
        requests.post(
            f"{SERVER_URL}/task/done",
            headers=HEADERS,
            json={"status": status, "message": message},
            timeout=10
        )
        log(f"✅ Результат отправлен: [{status}] {message}")
    except Exception as e:
        log(f"❌ Не удалось отправить результат: {e}")


def add_item_to_cart(page, query: str, qty: int) -> tuple[bool, str]:
    """
    Ищет товар на vprok.ru и добавляет qty раз в корзину.
    Возвращает (success, message).
    """
    log(f"🔍 Ищу: «{query}» (кол-во: {qty})")

    try:
        # Переходим на главную и кликаем поиск
        page.goto("https://www.vprok.ru/", wait_until="domcontentloaded", timeout=30000)
        page.wait_for_timeout(1500)

        # Находим поле поиска и вводим запрос
        search_input = page.locator(
            "input[placeholder*='оиск'], input[type='search'], [data-testid='search-input'], .search__input"
        ).first
        search_input.click()
        search_input.fill("")
        search_input.type(query, delay=60)
        search_input.press("Enter")

        log(f"   ⏳ Жду результаты поиска...")
        page.wait_for_load_state("domcontentloaded")
        page.wait_for_timeout(2500)

        # Ищем кнопки добавления — берём первый доступный товар
        # vprok.ru использует разные классы, пробуем несколько вариантов
        add_button_selectors = [
            "button:has-text('Добавить'):not([disabled])",
            "button:has-text('В корзину'):not([disabled])",
            "[class*='add-to-cart']:not([disabled])",
            "[data-testid*='add']:not([disabled])",
        ]

        add_btn = None
        for selector in add_button_selectors:
            btns = page.locator(selector)
            count = btns.count()
            if count > 0:
                # Проверяем что рядом нет текста "Нет в наличии"
                for i in range(min(count, 5)):
                    btn = btns.nth(i)
                    try:
                        # Ищем ближайший контейнер товара
                        product_card = btn.locator("xpath=ancestor::*[contains(@class,'product') or contains(@class,'item') or contains(@class,'card')][1]")
                        card_text = product_card.inner_text(timeout=1000) if product_card.count() > 0 else ""
                        if "нет в наличии" in card_text.lower() or "недоступен" in card_text.lower():
                            log(f"   ⏭️  Товар #{i+1} недоступен, пропускаю")
                            continue
                        add_btn = btn
                        break
                    except Exception:
                        add_btn = btn
                        break
                if add_btn:
                    break

        if add_btn is None:
            return False, f"Кнопка 'Добавить' не найдена для «{query}»"

        # Добавляем нужное количество раз
        for n in range(qty):
            try:
                add_btn.scroll_into_view_if_needed()
                add_btn.click(timeout=5000)
                log(f"   ➕ Добавлено ({n+1}/{qty})")
                page.wait_for_timeout(800)

                # После первого клика кнопка может смениться на +/-
                if n < qty - 1:
                    plus_btn = page.locator(
                        "button:has-text('+'), [aria-label*='увеличить'], [class*='plus']:not([disabled])"
                    ).first
                    if plus_btn.count() > 0 and plus_btn.is_visible():
                        add_btn = plus_btn
            except PwTimeout:
                log(f"   ⚠️  Таймаут при клике на кнопку (попытка {n+1})")

        return True, f"«{query}» добавлен(о) ×{qty}"

    except Exception as e:
        return False, f"Ошибка при обработке «{query}»: {e}"


def process_task(task: dict):
    """Обрабатывает задание: открывает браузер и добавляет все товары."""
    items = task.get("items", [])
    task_id = task.get("id", "?")
    log(f"📦 Задание #{task_id} получено. Товаров: {len(items)}")

    results = []
    errors = []

    with sync_playwright() as pw:
        log("🌐 Запускаю браузер...")
        browser = pw.chromium.launch(
            headless=False,
            args=["--start-maximized"]
        )
        context = browser.new_context(
            viewport=None,  # использовать размер окна
            locale="ru-RU",
            timezone_id="Europe/Moscow"
        )
        page = context.new_page()

        for item in items:
            query = item.get("query", "").strip()
            qty   = int(item.get("qty", 1))
            if not query:
                continue

            success, msg = add_item_to_cart(page, query, qty)
            results.append(msg)
            if not success:
                errors.append(msg)
            log(f"   {'✅' if success else '❌'} {msg}")
            time.sleep(1)

        log("🛒 Все товары обработаны. Перехожу в корзину...")
        try:
            # Пытаемся открыть корзину
            cart_link = page.locator("a[href*='cart'], a[href*='basket'], [data-testid*='cart']").first
            if cart_link.count() > 0:
                cart_link.click()
                page.wait_for_load_state("domcontentloaded")
            else:
                page.goto("https://www.vprok.ru/cart", wait_until="domcontentloaded", timeout=15000)
        except Exception:
            pass

        log("👁️  Браузер оставлен открытым — проверьте корзину!")
        log("   (закройте браузер вручную когда будете готовы)")

        # Ждём пока пользователь не закроет браузер
        try:
            page.wait_for_event("close", timeout=0)  # бесконечно
        except Exception:
            pass

        # Отправляем результат
        if errors:
            status_str = "partial"
            message = f"Выполнено с ошибками: {'; '.join(errors)}"
        else:
            status_str = "ok"
            message = f"Все {len(results)} товар(ов) добавлены: {', '.join(results)}"

        report_done(status_str, message)

        try:
            browser.close()
        except Exception:
            pass


def main():
    log("🚀 vprok.ru клиент запущен")
    log(f"   Сервер: {SERVER_URL}")
    log(f"   Интервал проверки: {POLL_INTERVAL} сек")
    log("   Нажмите Ctrl+C для остановки\n")

    while True:
        task = fetch_task()
        if task:
            process_task(task)
        else:
            log(f"💤 Нет заданий, жду {POLL_INTERVAL} сек...")
        time.sleep(POLL_INTERVAL)


if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        log("\n👋 Остановка по запросу пользователя")
