import time
import os
import re
import urllib.parse
from typing import Dict, Any, Optional
from automation.platform_handlers.base_handler import BasePlatformHandler

class FacebookHandler(BasePlatformHandler):
    PLATFORM_NAME = "Facebook"
    BASE_URL = "https://www.facebook.com/"

    def phase_upload(self, page, flyer_path: str, guide: Optional[Dict[str, Any]] = None) -> bool:
        """
        Sesi 1: Upload Media
        Membuka dialog posting Facebook, menekan tombol Foto/Video, dan melampirkan flyer ke dialog.
        PENTING: Tidak pernah mengklik file chooser atau dropzone secara fisik untuk mencegah popup Windows File Explorer.
        """
        upload_url = (guide and guide.get("direct_upload_url")) or self.BASE_URL
        self.log(f"Membuka Facebook ({upload_url})...")
        page.goto(upload_url, wait_until="domcontentloaded", timeout=45000)
        time.sleep(3)
        self.dismiss_common_modals(page)
        self.setup_clipboard_interceptor(page)

        # Cek jika butuh login
        if self.check_login_required(page, guide):
            self.log("Facebook membutuhkan login. Silakan login akun terlebih dahulu di Chrome Bot!", "ERROR")
            return False

        # 1. Buka kotak dialog Buat Postingan
        self.log("Membuka area Buat Postingan Facebook...")
        opened = False
        create_box_selectors = [
            "div[role='button']:has-text(\"What's on your mind\")",
            "div[role='button']:has-text('Apa yang Anda pikirkan')",
            "span:has-text(\"What's on your mind\")",
            "span:has-text('Apa yang Anda pikirkan')",
            "div[aria-label*=\"What's on your mind\"]",
            "div[aria-label*='Buat postingan']"
        ]
        for sel in create_box_selectors:
            try:
                btn = page.locator(sel).first
                if btn.is_visible(timeout=1500):
                    btn.click()
                    opened = True
                    self.log(f"Dialog buat postingan dibuka via ({sel}).")
                    break
            except Exception:
                continue

        # Vision Fallback jika kotak buat postingan belum terbuka
        if not opened and self.brain:
            self.log("Kotak postingan tidak ditemukan via CSS. Memanggil AI Vision...", "WARN")
            v_res = self.consult_vision(page, "Cari tombol atau kotak 'Apa yang Anda pikirkan' atau 'What's on your mind' di beranda Facebook.")
            if v_res.get("coordinates_percent"):
                opened = self.click_visual_target(page, v_res, step_name="facebook_open_create")

        time.sleep(2)
        abs_flyer = os.path.abspath(flyer_path)

        # 2. Cari dan klik tombol Foto/Video di dialog untuk memicu attach input file
        self.log("Mencari tombol Foto/Video di dialog postingan...")
        photo_btn_selectors = [
            "div[role='dialog'] div[aria-label*='Photo/video' i]",
            "div[role='dialog'] div[aria-label*='Foto/video' i]",
            "div[role='dialog'] span:has-text('Photo/video')",
            "div[role='dialog'] span:has-text('Foto/video')",
            "div[role='dialog'] div[aria-label*='Add to your post'] div[role='button']",
            "div[role='dialog'] div[aria-label*='Tambahkan ke postingan'] div[role='button']"
        ]
        photo_clicked = False
        for pbs in photo_btn_selectors:
            try:
                p_el = page.locator(pbs).first
                if p_el.is_visible(timeout=1000):
                    p_el.click()
                    photo_clicked = True
                    self.log(f"Tombol Foto/video diklik ({pbs}).")
                    time.sleep(1.5)
                    break
            except Exception:
                continue

        # Vision Fallback jika tombol Foto/Video belum terklik
        if not photo_clicked and self.brain:
            self.log("Tombol Foto/video tidak ditemukan via CSS. Memanggil AI Vision...", "WARN")
            v_res = self.consult_vision(page, "Cari tombol atau ikon Foto/Video hijau pada dialog posting Facebook ini. Berikan koordinatnya.")
            if v_res.get("coordinates_percent"):
                photo_clicked = self.click_visual_target(page, v_res, step_name="facebook_photo_btn")
                time.sleep(1.5)

        # 3. Pasang flyer LANGSUNG ke input file DOM tanpa klik native file chooser
        # Menjamin Windows File Explorer tidak pernah terbuka di host OS
        self.log("Memasang flyer ke input file Facebook (metode non-dialog)...")
        file_attached = False

        # Strategi A: Cari input file spesifik di dalam dialog atau form
        file_input_candidates = [
            "div[role='dialog'] input[type='file']",
            "form input[type='file']",
            "input[type='file'][accept*='image']",
            "input[type='file']"
        ]
        for fic in file_input_candidates:
            try:
                inputs = page.locator(fic).all()
                for inp in inputs:
                    try:
                        inp.set_input_files(abs_flyer)
                        file_attached = True
                        self.log(f"Flyer berhasil dipasang langsung ke elemen DOM ({fic}).")
                        time.sleep(2.5)
                        break
                    except Exception:
                        continue
                if file_attached:
                    break
            except Exception:
                continue

        # Strategi B: Jika belum terpasang, tunggu sejenak dan cari kembali semua input file
        if not file_attached:
            time.sleep(2.0)
            try:
                all_inputs = page.locator("input[type='file']").all()
                for inp in all_inputs:
                    try:
                        inp.set_input_files(abs_flyer)
                        file_attached = True
                        self.log("Flyer berhasil dipasang via all inputs fallback.")
                        time.sleep(2.5)
                        break
                    except Exception:
                        continue
            except Exception as up_err:
                self.log(f"Fallback input file: {up_err}", "WARN")

        # 4. Verifikasi visual: Gambar preview harus ada di dialog!
        self.log("Memverifikasi lampiran flyer di dialog Facebook...")
        is_verified = False
        for _ in range(4):
            thumb = page.locator("div[role='dialog'] img[src*='blob:'], div[role='dialog'] img[src*='scontent'], div[role='dialog'] div[aria-label*='Edit'], div[role='dialog'] div[aria-label*='Remove'], div[role='dialog'] div[aria-label*='Hapus']").first
            if thumb.is_visible(timeout=2000):
                is_verified = True
                self.log("Verifikasi Sesi 1 Sukses: Flyer terbukti terpasang di dialog Facebook!", "SUCCESS")
                break
            time.sleep(1.5)

        return is_verified

    def phase_metadata(self, page, title: str, caption: str, target_link: Optional[str] = None, guide: Optional[Dict[str, Any]] = None) -> bool:
        """
        Sesi 2: Content & Metadata
        Memasukkan teks judul, keterangan caption, dan target link ke kotak status.
        """
        self.log("Mengisi teks postingan ke dialog Facebook...")
        full_content = f"{title}\n\n{caption}"
        if target_link:
            full_content += f"\n\nLink: {target_link}"

        # Focus text box in dialog
        textbox_selectors = [
            "div[role='dialog'] div[role='textbox']",
            "div[role='dialog'] div[contenteditable='true']",
            "div[role='dialog'] div[data-lexical-editor='true']",
            "div[role='dialog'] div[aria-label*=\"What's on your mind\"]",
            "div[role='dialog'] div[aria-label*='Apa yang Anda pikirkan']"
        ]
        box_focused = False
        for sel in textbox_selectors:
            try:
                box = page.locator(sel).first
                if box.is_visible(timeout=1500):
                    box.click()
                    box_focused = True
                    time.sleep(0.3)
                    break
            except Exception:
                continue

        # Masukkan konten via Ctrl+V atau keyboard
        pasted = False
        try:
            page.evaluate("(text) => navigator.clipboard.writeText(text)", full_content)
            page.keyboard.press("Control+v")
            pasted = True
            self.log("Caption berhasil di-paste (Ctrl+V) ke dalam status.")
        except Exception:
            pass

        if not pasted:
            try:
                page.keyboard.insert_text(full_content)
                pasted = True
            except Exception:
                page.keyboard.type(full_content, delay=10)

        time.sleep(1.5)
        return True

    def phase_publish(self, page, guide: Optional[Dict[str, Any]] = None) -> bool:
        """
        Sesi 3: Publish
        Menekan tombol Kirim / Post yang sudah aktif (berwarna biru).
        """
        self.log("Memeriksa tombol Kirim / Post Facebook...")
        post_buttons = [
            "div[role='dialog'] div[aria-label='Post'][role='button']",
            "div[role='dialog'] div[aria-label='Kirim'][role='button']",
            "div[role='dialog'] div[aria-label='Bagikan'][role='button']",
            "div[role='dialog'] div[role='button']:has-text('Post')",
            "div[role='dialog'] div[role='button']:has-text('Kirim')",
            "div[role='dialog'] div[role='button']:has-text('Bagikan')",
            "div[role='dialog'] button:has-text('Post')",
            "div[role='dialog'] button:has-text('Kirim')",
            "div[role='dialog'] span:has-text('Post')",
            "div[role='dialog'] span:has-text('Kirim')"
        ]
        post_clicked = False

        for _ in range(3):
            for sel in post_buttons:
                try:
                    btn = page.locator(sel).first
                    if btn.is_visible(timeout=1000):
                        aria_dis = btn.get_attribute("aria-disabled")
                        if aria_dis != "true":
                            try:
                                btn.click(force=True)
                            except Exception:
                                btn.evaluate("el => el.click()")
                            post_clicked = True
                            self.log(f"Tombol Post Facebook berhasil diklik via ({sel})!", "SUCCESS")
                            break
                        else:
                            self.log("Tombol Post Facebook masih memproses media (disabled)...", "INFO")
                except Exception:
                    continue
            if post_clicked:
                break
            time.sleep(2.0)

        # Vision Fallback jika tombol Post belum terklik atau masih disabled
        if not post_clicked and self.brain:
            self.log("Tombol Post belum terklik via CSS. Memanggil AI Vision...", "WARN")
            v_res = self.consult_vision(page, "Cari tombol Post atau Kirim berwarna biru yang aktif untuk mempublikasikan status di Facebook. Berikan koordinatnya.")
            if v_res.get("coordinates_percent"):
                post_clicked = self.click_visual_target(page, v_res, step_name="facebook_post_btn")

        # Shortcut fallback jika belum terklik
        if not post_clicked:
            try:
                page.keyboard.press("Control+Enter")
                time.sleep(2)
                if not page.locator("div[role='dialog']").first.is_visible(timeout=2000):
                    post_clicked = True
                    self.log("Postingan Facebook berhasil terkirim via Control+Enter!")
            except Exception:
                pass

        if not post_clicked:
            return False

        # Verifikasi: Dialog tertutup
        self.log("Menunggu proses pengiriman selesai di server Facebook...")
        time.sleep(6)
        return True

    def phase_extract_link(self, page, title: str, guide: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        """
        Sesi 4: Ekstraksi Tautan
        Membuka linimasa profil (https://www.facebook.com/me), mencari postingan teratas,
        dan menyalin permalink postingan via timestamp atau menu titik tiga (•••).
        """
        post_url = None

        # 1. Cek URL saat ini jika diarahkan langsung
        curr_url = page.url
        if any(kw in curr_url for kw in ["/posts/", "permalink.php", "story.php", "fbid="]):
            post_url = curr_url
            self.log(f"URL browser langsung mengarah ke postingan: {post_url}", "SUCCESS")

        # 2. Cek clipboard interceptor jika sudah tersalin sebelumnya
        if not post_url:
            c = self.get_intercepted_clipboard(page)
            if c and "facebook.com" in c and not c.endswith("/me") and "profile.php" not in c:
                post_url = c
                self.log(f"Tautan postingan terdeteksi dari clipboard interceptor: {post_url}", "SUCCESS")

        # 3. Cek feed teratas
        if not post_url:
            try:
                feed_link = page.locator("div[role='feed'] div[role='article'] a[href*='/posts/'], div[role='feed'] div[role='article'] a[href*='permalink.php']").first
                if feed_link.is_visible(timeout=2000):
                    href = feed_link.get_attribute("href")
                    if href:
                        post_url = href.split("?")[0] if "permalink.php" not in href else href
                        self.log(f"Tautan ditemukan di feed: {post_url}", "SUCCESS")
            except Exception:
                pass

        # 4. Buka linimasa profil akun sendiri (https://www.facebook.com/me)
        if not post_url:
            self.log("Membuka linimasa profil sendiri (https://www.facebook.com/me) untuk menyalin tautan postingan...")
            try:
                page.goto("https://www.facebook.com/me", wait_until="domcontentloaded", timeout=30000)
                time.sleep(3)
                self.dismiss_common_modals(page)
                self.setup_clipboard_interceptor(page)

                # Gulir ke bawah 650px agar postingan teratas melewati banner/composer dan tampil penuh di layar
                self.log("Menggulir linimasa profil 650px ke bawah untuk menampilkan postingan teratas...")
                page.evaluate("window.scrollBy(0, 650)")
                time.sleep(2)

                # STRATEGI A: Menu titik tiga (•••) -> Embed / Sematkan (Menghasilkan permalink kanonikal resmi Facebook)
                action_btn = page.locator("div[aria-label*='Actions for this post'], div[aria-label*='Tindakan untuk postingan ini'], div[aria-label*='More options'], div[aria-label*='Opsi lainnya']").first
                if action_btn.is_visible(timeout=3000):
                    action_btn.scroll_into_view_if_needed()
                    time.sleep(0.5)
                    action_btn.click()
                    time.sleep(1.5)

                    # 1. Cek opsi Embed / Sematkan
                    embed_item = page.locator("span:has-text('Embed'), span:has-text('Sematkan'), div[role='menuitem']:has-text('Embed'), div[role='menuitem']:has-text('Sematkan')").first
                    if embed_item.is_visible(timeout=2000):
                        embed_item.click()
                        time.sleep(2)
                        raw_code = page.evaluate("""() => {
                            const inputs = Array.from(document.querySelectorAll('div[role="dialog"] input, div[role="dialog"] textarea, div[role="dialog"] code'));
                            return inputs.map(i => i.value || i.innerText).join(' ');
                        }""")
                        match = re.search(r'href=([^&"\']+)', raw_code)
                        if match:
                            post_url = urllib.parse.unquote(match.group(1))
                            self.log(f"Tautan postingan berhasil diekstraksi dari kode Embed Facebook: {post_url}", "SUCCESS")

                        # Tutup modal dialog Embed
                        close_btn = page.locator("div[role='dialog'] div[aria-label*='Close'], div[role='dialog'] div[aria-label*='Tutup']").first
                        if close_btn.is_visible(timeout=1000):
                            try:
                                close_btn.click()
                            except Exception:
                                pass

                    # 2. Cek opsi Copy link / Salin tautan jika ada
                    if not post_url:
                        copy_item = page.locator("div[role='menuitem']:has-text('Copy link'), div[role='menuitem']:has-text('Salin tautan'), span:has-text('Copy link'), span:has-text('Salin tautan')").first
                        if copy_item.is_visible(timeout=1500):
                            copy_item.click()
                            time.sleep(1.2)
                            copied = self.get_intercepted_clipboard(page)
                            if not copied:
                                try:
                                    copied = page.evaluate("() => navigator.clipboard.readText()")
                                except Exception:
                                    pass
                            if copied and "facebook.com" in copied and not copied.endswith("/me") and "profile.php" not in copied:
                                post_url = copied
                                self.log(f"Tautan berhasil disalin via menu titik tiga: {post_url}", "SUCCESS")

                # STRATEGI B: Tautan foto flyer postingan teratas (karena flyer diunggah sebagai foto)
                if not post_url:
                    photo = page.locator("a[href*='/photo/?fbid='], a[href*='photo.php?fbid='], a[href*='/photos/']").first
                    if photo.is_visible(timeout=2500):
                        href = photo.get_attribute("href")
                        if href:
                            clean_href = href.split("&__cft__")[0].split("&__tn__")[0]
                            if not clean_href.startswith("http"):
                                clean_href = "https://www.facebook.com" + clean_href
                            fbid_m = re.search(r'fbid=(\d+)', clean_href)
                            if fbid_m:
                                post_url = f"https://www.facebook.com/photo/?fbid={fbid_m.group(1)}"
                            else:
                                post_url = clean_href
                            self.log(f"Tautan foto postingan ditemukan di profil: {post_url}", "SUCCESS")

                # STRATEGI C: Tautan timestamp / waktu di postingan teratas
                if not post_url:
                    top_article = page.locator("div[role='feed'] div[role='article'], div[role='main'] div[role='article'], div[role='article']").first
                    if top_article.is_visible(timeout=2000):
                        time_links = top_article.locator("a[href*='/posts/'], a[href*='permalink.php'], a[href*='story.php']").all()
                        for tl in time_links:
                            try:
                                h = tl.get_attribute("href")
                                if h and any(k in h for k in ["/posts/", "permalink.php", "story.php"]):
                                    post_url = h.split("?")[0] if "permalink.php" not in h else h
                                    self.log(f"Tautan postingan ditemukan dari timestamp profil: {post_url}", "SUCCESS")
                                    break
                            except Exception:
                                continue
            except Exception as fe:
                self.log(f"Pemeriksaan profil Facebook: {fe}", "WARN")

        # 5. Vision Fallback dengan deteksi rekomendasi scroll
        if not post_url and self.brain:
            self.log("Memanggil AI Vision untuk menemukan menu titik tiga atau tautan postingan...", "WARN")
            v_res = self.consult_vision(page, "Cari tombol menu titik tiga (•••) atau tautan pada postingan paling atas di linimasa profil Facebook ini.")
            
            # Jika AI Vision mendeteksi perlu scroll
            action_needed = (v_res.get("action_needed") or "").lower()
            rec_text = (v_res.get("recommendation") or "").lower()
            if "scroll" in action_needed or "scroll" in rec_text or "gulir" in rec_text:
                self.log("AI Vision merekomendasikan scroll. Menggulir linimasa 600px lagi...", "INFO")
                page.evaluate("window.scrollBy(0, 600)")
                time.sleep(2)
                v_res = self.consult_vision(page, "Cari tombol menu titik tiga (•••) pada postingan teratas setelah digulir.")

            if v_res.get("coordinates_percent"):
                self.click_visual_target(page, v_res, step_name="facebook_more_menu")
                time.sleep(1.5)
                # Cek menu Sematkan / Embed
                embed_item = page.locator("span:has-text('Embed'), span:has-text('Sematkan'), div[role='menuitem']:has-text('Embed'), div[role='menuitem']:has-text('Sematkan')").first
                if embed_item.is_visible(timeout=2000):
                    embed_item.click()
                    time.sleep(2)
                    raw_code = page.evaluate("""() => {
                        const inputs = Array.from(document.querySelectorAll('div[role="dialog"] input, div[role="dialog"] textarea, div[role="dialog"] code'));
                        return inputs.map(i => i.value || i.innerText).join(' ');
                    }""")
                    match = re.search(r'href=([^&"\']+)', raw_code)
                    if match:
                        post_url = urllib.parse.unquote(match.group(1))
                        self.log(f"Tautan postingan berhasil diekstraksi via AI Vision menu Embed: {post_url}", "SUCCESS")
                else:
                    copy_item = page.locator("div[role='menuitem']:has-text('Copy link'), div[role='menuitem']:has-text('Salin tautan')").first
                    if copy_item.is_visible(timeout=1500):
                        copy_item.click()
                        time.sleep(1.2)
                        copied = self.get_intercepted_clipboard(page)
                        if copied and "facebook.com" in copied and not copied.endswith("/me"):
                            post_url = copied
                            self.log(f"Tautan postingan berhasil disalin via AI Vision menu: {post_url}", "SUCCESS")

        if not post_url:
            self.log("Gagal menyalin tautan postingan Facebook spesifik. Tidak mencatat link profil sendiri ke Excel.", "ERROR")
            return {
                "success": False,
                "post_url": None,
                "message": "FAILED: Postingan Facebook terkirim tapi URL postingan spesifik tidak dapat disalin dari linimasa profil."
            }

        self.log(f"Berhasil! Tautan Facebook valid tersimpan: {post_url}", "SUCCESS")
        return {
            "success": True,
            "post_url": post_url,
            "message": "Postingan berhasil dipublikasikan di Facebook!"
        }
