
import requests
import json
import time
import csv
import os
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import StaleElementReferenceException
from webdriver_manager.chrome import ChromeDriverManager
from PIL import Image
import qrcode_terminal

# --- KONFIGURASI ---
COOKIE_FILE = 'shopee_cookie.json'
OUTPUT_CSV_FILE = 'shopee_bulk_reviews.csv'
PRODUCT_URLS = [
    "https://shopee.co.id/frame-head-unit-android-9-inch-10-inch-honda-mobilio-brio-brv-2016--2019-i.27401483.13636733473"
]
HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
    'Accept': 'application/json',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'en-US,en;q=0.9,id;q=0.8',
    'X-Requested-With': 'XMLHttpRequest',
    'X-API-SOURCE': 'pc',
}

def get_cookies_via_qrcode():
    """Menjalankan Selenium headless untuk login via QR code dan menyimpan cookies."""
    print("Memulai proses login via QR code...")
    chrome_options = Options()
    chrome_options.add_argument("--headless")
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-dev-shm-usage")
    chrome_options.add_argument("--window-size=1920,1080")
    chrome_options.add_argument("user-agent=" + HEADERS['User-Agent'])

    try:
        service = Service(ChromeDriverManager().install())
        driver = webdriver.Chrome(service=service, options=chrome_options)
    except Exception as e:
        print(f"Gagal memulai Selenium: {e}")
        return False

    try:
        login_url = "https://shopee.co.id/buyer/login/qr?next=https%3A%2F%2Fshopee.co.id%2F"
        print("Membuka halaman login Shopee...")
        driver.get(login_url)
        
        wait = WebDriverWait(driver, 10)
        qr_code_selector = "div.zFPfur"

        print("\n" + "="*50)
        print("PERSIAPKAN APLIKASI SHOPEE ANDA...")
        print("QR code akan muncul dan diperbarui secara otomatis.")
        print("="*50)
        time.sleep(3)

        # Loop untuk me-refresh QR code
        while driver.current_url.startswith("https://shopee.co.id/buyer/login"):
            os.system('clear') # Membersihkan terminal
            print("Mengambil QR code terbaru... Silakan pindai (scan).")
            try:
                qr_element = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, qr_code_selector)))
                time.sleep(0.5)
                qr_screenshot_path = "qrcode.png"
                qr_element.screenshot(qr_screenshot_path)
                qrcode_terminal.draw(qr_screenshot_path)
                print("Menunggu Anda scan... (akan refresh otomatis)")
            except Exception as e:
                print(f"Gagal mengambil QR code, mencoba lagi... Error: {e}")
            
            # Tunggu 10 detik sebelum refresh, beri waktu untuk scan
            # Cek URL setiap detik untuk respons cepat setelah login
            for _ in range(10):
                if not driver.current_url.startswith("https://shopee.co.id/buyer/login"):
                    break
                time.sleep(1)

        print("\nLogin berhasil terdeteksi!")

        # Ambil dan simpan cookies
        cookies = driver.get_cookies()
        with open(COOKIE_FILE, 'w') as f:
            json.dump(cookies, f)
        print(f"Cookies baru yang valid telah disimpan di '{COOKIE_FILE}'.")
        return True

    except Exception as e:
        print(f"Terjadi error saat proses login QR code: {e}")
        driver.save_screenshot('error_screenshot.png')
        print("Screenshot error disimpan sebagai 'error_screenshot.png'")
        return False
    finally:
        driver.quit()
        if os.path.exists("qrcode.png"):
            os.remove("qrcode.png")

def load_cookies_and_set_csrf(session):
    if not os.path.exists(COOKIE_FILE):
        print(f"File '{COOKIE_FILE}' tidak ditemukan. Memulai login baru...")
        if not get_cookies_via_qrcode():
            return False

    try:
        with open(COOKIE_FILE, 'r') as f:
            cookies_list = json.load(f)
    except (json.JSONDecodeError, FileNotFoundError):
        print("File cookie rusak atau tidak ada. Memulai login baru...")
        if not get_cookies_via_qrcode():
            return False

    csrf_token = None
    for cookie in cookies_list:
        session.cookies.set(cookie['name'], cookie['value'], domain=cookie['domain'])
        if cookie['name'] == 'csrftoken':
            csrf_token = cookie['value']

    if csrf_token:
        HEADERS['x-csrftoken'] = csrf_token
        return True
    else:
        print("Error: 'csrftoken' tidak ditemukan. Mencoba login ulang...")
        if not get_cookies_via_qrcode():
            return False
        # Coba lagi setelah mendapatkan cookie baru
        return load_cookies_and_set_csrf(session)

# --- FUNGSI-FUNGSI SCRAPING (TIDAK BERUBAH) ---

def parse_product_url(url):
    try:
        parts = url.strip().split('-i.')[1].split('.')
        shop_id = int(parts[0])
        item_id = int(parts[1].split('?')[0])
        return shop_id, item_id
    except Exception as e:
        print(f"URL tidak valid: {url} -> {e}")
        return None, None

def get_product_reviews(session, shop_id, item_id):
    all_reviews = []
    offset = 0
    limit = 50
    print(f"  -> Mengambil ulasan untuk item {item_id}...")
    while True:
        api_url = f"https://shopee.co.id/api/v2/item/get_ratings?itemid={item_id}&shopid={shop_id}&limit={limit}&offset={offset}&filter=1&type=0"
        try:
            response = session.get(api_url, headers=HEADERS)
            if response.status_code == 403:
                print("    Error 403 Forbidden. Sesi mungkin tidak valid. Hapus file cookie dan coba lagi.")
                return None # Mengembalikan None untuk menandakan kegagalan
            response.raise_for_status()
            data = response.json()
            if data.get('error'):
                print(f"    Error dari API: {data['error_msg']}")
                break
            ratings = data.get('data', {}).get('ratings', [])
            if not ratings:
                print("    Selesai, tidak ada ulasan lagi.")
                break
            all_reviews.extend(ratings)
            print(f"    Berhasil mengambil {len(ratings)} ulasan. Total sekarang: {len(all_reviews)}")
            offset += limit
            time.sleep(1)
        except requests.exceptions.RequestException as e:
            print(f"    Error saat request ke API ulasan: {e}")
            break
        except json.JSONDecodeError:
            print("    Gagal mem-parse JSON dari respons API ulasan.")
            break
    return all_reviews

def get_product_info(session, shop_id, item_id):
    api_url = f"https://shopee.co.id/api/v4/pdp/get_pc?shopid={shop_id}&itemid={item_id}"
    try:
        response = session.get(api_url, headers=HEADERS)
        response.raise_for_status()
        data = response.json()
        if data.get('error'):
            return "PRODUK TIDAK DIKETAHUI", "TOKO TIDAK DIKETAHUI"
        product_name = data.get('data', {}).get('name', "N/A")
        shop_name = data.get('data', {}).get('shop_detailed', {}).get('name', "N/A")
        return product_name, shop_name
    except Exception as e:
        print(f"  -> Gagal mengambil info produk: {e}")
        return "PRODUK GAGAL DIMUAT", "TOKO GAGAL DIMUAT"

def write_to_csv(all_data):
    if not all_data:
        print("Tidak ada data untuk ditulis ke CSV.")
        return
    print(f"Menyimpan {len(all_data)} total baris ke '{OUTPUT_CSV_FILE}'...")
    headers = ['product_name', 'shop_name', 'review_id', 'order_id', 'author_username', 'rating_star', 'comment', 'media_type', 'media_url']
    with open(OUTPUT_CSV_FILE, 'w', newline='', encoding='utf-8-sig') as f:
        writer = csv.writer(f, delimiter=';')
        writer.writerow(headers)
        for item in all_data:
            review = item['review']
            common_data = [item['productName'], item['shopName'], review.get('cmtid'), review.get('orderid'), review.get('author_username'), review.get('rating_star'), review.get('comment', '').replace('\n', ' ')]
            has_images = review.get('images')
            has_videos = review.get('videos')
            if not has_images and not has_videos:
                writer.writerow(common_data + ['text_only', ''])
            else:
                if has_images:
                    for image_id in has_images:
                        writer.writerow(common_data + ['image', f"https://cf.shopee.co.id/file/{image_id}"])
                if has_videos:
                    for video_info in has_videos:
                        writer.writerow(common_data + ['video', video_info.get('url')])
    print("File CSV berhasil dibuat!")

def main():
    session = requests.Session()
    if not load_cookies_and_set_csrf(session):
        print("Gagal mendapatkan sesi login yang valid. Program berhenti.")
        return

    final_data_for_csv = []
    for url in PRODUCT_URLS:
        print(f"\nMemproses URL: {url}")
        shop_id, item_id = parse_product_url(url)
        if not shop_id or not item_id:
            continue
        product_name, shop_name = get_product_info(session, shop_id, item_id)
        print(f"  -> Produk: {product_name} | Toko: {shop_name}")
        reviews = get_product_reviews(session, shop_id, item_id)
        if reviews is None: # Cek jika sesi tidak valid
            print("Proses dihentikan karena sesi tidak valid.")
            break
        if reviews:
            for review in reviews:
                final_data_for_csv.append({"productName": product_name, "shopName": shop_name, "review": review})
        print(f"Selesai memproses URL. Total ulasan terkumpul saat ini: {len(final_data_for_csv)}")

    write_to_csv(final_data_for_csv)

if __name__ == "__main__":
    main()
