import os
import time
import logging
import traceback
from dotenv import load_dotenv
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, UnexpectedAlertPresentException, NoAlertPresentException

# 지도 데이터
from mappings import REGION_MAP, CAT_CODES

# --- 1. 로깅 설정 (상세 모드) ---
# 로그 파일 초기화 (실행 시마다 새로 씀)
if os.path.exists("crawler.log"):
    os.remove("crawler.log")

logging.basicConfig(
    filename='crawler.log',
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] %(message)s',
    datefmt='%H:%M:%S',
    encoding='utf-8'
)

# 콘솔 출력 추가
console = logging.StreamHandler()
console.setLevel(logging.INFO)
logging.getLogger('').addHandler(console)

# 환경변수 로드
current_folder = os.path.dirname(os.path.abspath(__file__))
env_path = os.path.join(current_folder, '.env')
load_dotenv(env_path)

MY_ID = os.getenv("USER_ID")
MY_PW = os.getenv("USER_PW")
LOGIN_URL = os.getenv("TARGET_LOGIN_URL")
BASE_SEARCH_URL = "https://www.my-auction.co.kr/auction/search_list.php"

def get_driver():
    options = webdriver.ChromeOptions()
    options.add_argument("--headless")
    options.add_argument("--no-sandbox")
    options.add_argument("--disable-dev-shm-usage")
    options.add_argument("--disable-gpu")
    options.add_argument("--window-size=1280,720") # 해상도 조금 낮춤 (메모리 절약)
    
    # [추가] 메모리 누수 방지 옵션들
    options.add_argument("--disable-extensions")
    options.add_argument("--dns-prefetch-disable")
    options.add_argument("--disable-features=VizDisplayCompositor")
    
    options.binary_location = "/usr/bin/google-chrome-stable"
    
    driver = webdriver.Chrome(
        service=Service(ChromeDriverManager().install()), 
        options=options
    )
    
    # [중요] 페이지 로딩이 30초 넘어가면 그냥 끊어버리게 설정 (무한 대기 방지)
    driver.set_page_load_timeout(30)
    
    return driver

def handle_alert(driver):
    """혹시 떠있을지 모르는 경고창(Alert) 처리"""
    try:
        # 경고창이 뜰 때까지 3초만 기다려봄
        WebDriverWait(driver, 3).until(EC.alert_is_present())
        alert = driver.switch_to.alert
        alert_text = alert.text
        logging.warning(f"🚨 [경고창 감지됨] 내용: {alert_text}")
        alert.accept() # 확인 버튼 누름
        logging.info("👉 경고창 '확인'을 눌러서 닫았습니다.")
        return alert_text
    except TimeoutException:
        return None
    except NoAlertPresentException:
        return None

def login(driver):
    """로그인 수행 (과학수사 모드)"""
    try:
        logging.info("🔑 [1] 로그인 페이지 접속 시도...")
        driver.get(LOGIN_URL)
        
        # 페이지 로딩 대기
        time.sleep(2)
        
        # 1. 접속 직후 스크린샷
        driver.save_screenshot("debug_1_login_page.png")
        logging.info("📸 접속 화면 저장 완료 (debug_1_login_page.png)")

        # 2. 아이디/비번 입력 요소 찾기
        logging.info("⌨️ [2] 아이디/비번 입력 중...")
        
        try:
            id_input = WebDriverWait(driver, 10).until(
                EC.presence_of_element_located((By.ID, "id"))
            )
            pw_input = driver.find_element(By.ID, "passwd")
        except TimeoutException:
            logging.error("❌ 입력창을 찾을 수 없습니다! (ID='id' 요소 없음)")
            with open("debug_error_source.html", "w", encoding="utf-8") as f:
                f.write(driver.page_source)
            return False

        id_input.clear()
        id_input.send_keys(MY_ID)
        pw_input.clear()
        pw_input.send_keys(MY_PW)
        
        # 3. 전송 (엔터키)
        logging.info("🚀 [3] 로그인 정보 전송 (Enter)...")
        pw_input.send_keys(Keys.RETURN)
        
        # --- 중요: 전송 직후 경고창 체크 ---
        time.sleep(2)
        alert_msg = handle_alert(driver)
        if alert_msg:
            logging.error(f"❌ 로그인 실패 (사이트 메시지): {alert_msg}")
            return False

        # 4. URL 변화 확인
        current_url = driver.current_url
        logging.info(f"📍 현재 URL: {current_url}")

        if "login.php" in current_url:
            logging.error("⚠️ URL이 여전히 로그인 페이지입니다. 실패 의심!")
            driver.save_screenshot("debug_2_login_failed.png")
            
            # HTML 덤프 떠서 확인
            with open("debug_failed_source.html", "w", encoding="utf-8") as f:
                f.write(driver.page_source)
            logging.info("📄 현재 페이지 소스를 'debug_failed_source.html'로 저장했습니다.")
            return False
        else:
            logging.info("✅ 로그인 성공! (페이지 이동 확인됨)")
            return True

    except Exception as e:
        logging.error(f"❌ 로그인 중 에러 발생: {e}")
        logging.error(traceback.format_exc())
        return False

def run_instant_search(sido_name, gugun_name, cat_name, limit=10):
    driver = get_driver()
    results = []
    
    try:
        logging.info(f"🤖 크롤러 시작 (지역: {sido_name} {gugun_name}, 물건: {cat_name})")
        
        if not login(driver):
            logging.error("🚫 로그인 실패로 종료합니다. (로그 및 스크린샷 확인 필요)")
            driver.quit()
            return []

        # 코드 변환
        sido_code = REGION_MAP[sido_name]["code"]
        gugun_code = REGION_MAP[sido_name]["sub_regions"].get(gugun_name, "")
        cat_code = CAT_CODES.get(cat_name, "101")
        
        target_url = f"{BASE_SEARCH_URL}?address1_01={sido_code}&address1_02={gugun_code}&usage_code={cat_code}"
        logging.info(f"🌐 검색 페이지 접속: {target_url}")
        
        driver.get(target_url)
        time.sleep(3)
        
        soup = BeautifulSoup(driver.page_source, 'html.parser')
        
        # 결과 파싱
        items = soup.select("form[name='fboardlist'] table tbody tr")
        if not items:
            items = soup.select("tr")
        
        logging.info(f"📦 발견된 리스트 개수: {len(items)}")
        
        count = 0
        for item in items:
            if count >= limit: break
            
            text = item.text.strip()
            if "대항력" in text: continue
            
            try:
                link_tag = item.select_one("a[href*='search_view.php']")
                if not link_tag: continue
                
                a_id = link_tag.text.strip()
                href = link_tag['href']
                
                if len(a_id) < 5: continue
                if not href.startswith("http"): href = "https://www.my-auction.co.kr" + href
                
                results.append({
                    "auction_id": a_id,
                    "title": a_id,
                    "info_text": " ".join(text.split())[:100],
                    "link": href,
                    "status": "진행"
                })
                count += 1
                logging.info(f" - 수집: {a_id}")
                
            except Exception:
                continue
                
    except Exception as e:
        logging.error(f"❌ 전체 에러: {e}")
    finally:
        driver.quit()
        
    return results