from __future__ import annotations
import ipaddress, os, socket
from pathlib import Path
from urllib.parse import urlparse

PLAYWRIGHT_BROWSERS_PATH=os.environ.setdefault('PLAYWRIGHT_BROWSERS_PATH',os.environ.get('PLAYWRIGHT_BROWSERS_PATH','/var/lib/fiyat-radar/pw-browsers'))


def _public_url(url: str) -> None:
    p=urlparse(url)
    if p.scheme not in ('http','https') or not p.hostname:
        raise ValueError('Tarayıcı URL geçersiz')
    try: infos=socket.getaddrinfo(p.hostname,None,type=socket.SOCK_STREAM)
    except socket.gaierror as e: raise ValueError('Tarayıcı URL çözümlenemedi') from e
    ips={x[4][0] for x in infos}
    if not ips: raise ValueError('Tarayıcı URL IP bulunamadı')
    for raw in ips:
        try:
            if not ipaddress.ip_address(raw).is_global:
                raise ValueError('Tarayıcı özel/yerel IP adreslerine erişemez')
        except ValueError as e:
            if 'özel/yerel' in str(e): raise
            raise ValueError('Tarayıcı URL IP geçersiz') from e


class HybridBrowser:
    """Son çare Chromium getiricisi. Tek browser, tek context, sınırlı sayfa."""
    def __init__(self, *, enabled=True, max_pages=4, timeout_ms=18000, user_agent=None, storage_state_path=None):
        self.enabled=bool(enabled); self.max_pages=max(0,int(max_pages)); self.timeout_ms=max(5000,int(timeout_ms))
        self.user_agent=user_agent
        self.storage_state_path=storage_state_path or os.environ.get('FIYAT_RADAR_BROWSER_STATE','/var/lib/fiyat-radar/browser-state.json')
        self.used=0; self._pw=None; self._browser=None; self._context=None

    @property
    def available(self): return self.enabled and self.used < self.max_pages

    def _start(self):
        if self._context is not None: return
        if not self.enabled: raise RuntimeError('Hibrit Chromium kapalı')
        from playwright.sync_api import sync_playwright
        self._pw=sync_playwright().start()
        self._browser=self._pw.chromium.launch(headless=True,args=['--disable-dev-shm-usage','--disable-gpu','--no-first-run','--no-default-browser-check'])
        kwargs={'locale':'tr-TR','viewport':{'width':1280,'height':900},'service_workers':'block'}
        if self.user_agent: kwargs['user_agent']=self.user_agent
        try:
            if self.storage_state_path and Path(self.storage_state_path).is_file(): kwargs['storage_state']=self.storage_state_path
        except OSError: pass
        try:
            self._context=self._browser.new_context(**kwargs)
        except Exception:
            # Eski/bozuk storage-state tarayıcıyı tamamen devre dışı bırakmasın.
            if 'storage_state' not in kwargs:
                raise
            kwargs.pop('storage_state',None)
            try:
                Path(self.storage_state_path).unlink(missing_ok=True)
            except OSError:
                pass
            self._context=self._browser.new_context(**kwargs)
        def route_handler(route):
            # JS/XHR çalışsın; ağır görseller, video, font ve CSS indirilmesin.
            if route.request.resource_type in {'image','media','font','stylesheet'}:
                route.abort()
            else:
                route.continue_()
        self._context.route('**/*',route_handler)

    def fetch(self,url: str):
        if not self.available: raise RuntimeError('Chromium fallback kullanım limiti doldu')
        _public_url(url); self._start(); self.used+=1
        page=self._context.new_page()
        try:
            page.goto(url,wait_until='domcontentloaded',timeout=self.timeout_ms)
            page.wait_for_timeout(1200)
            final=page.url
            _public_url(final)
            html=page.content()
            if len(html)<200: raise ValueError('Chromium sayfa içeriği çok kısa')
            low=html.lower()
            challenge_markers=(
                'verify you are human','captcha','cf-chl-',
                'access denied','robot olmadığınızı','insan olduğunuzu doğrulayın'
            )
            if any(marker in low for marker in challenge_markers):
                raise RuntimeError('Site otomasyon erişimini doğrulama/anti-bot ekranıyla engelliyor')
            return html,final
        finally:
            page.close()

    def close(self):
        try:
            if self._context:
                try:
                    if self.storage_state_path:
                        Path(self.storage_state_path).parent.mkdir(parents=True,exist_ok=True)
                        self._context.storage_state(path=self.storage_state_path)
                except Exception:
                    pass
                self._context.close()
        finally:
            try:
                if self._browser: self._browser.close()
            finally:
                if self._pw: self._pw.stop()
                self._context=self._browser=self._pw=None
