"""Scrape Exotic Wood Zone products via Shopify JSON API."""

import argparse
import csv
import time
from datetime import date
from pathlib import Path
from typing import Dict, List

import requests

SPECIES_MAP = {
    "brazilian rosewood": "rosewood", "indian rosewood": "rosewood", "rosewood": "rosewood",
    "black walnut": "walnut", "walnut": "walnut", "maple": "maple", "alder": "alder",
    "mahogany": "mahogany", "sapele": "sapele", "koa": "koa", "spruce": "spruce",
    "cedar": "cedar", "ebony": "ebony", "ash": "ash", "basswood": "basswood",
    "poplar": "poplar", "cherry": "cherry", "korina": "korina", "limba": "korina",
    "purpleheart": "purpleheart", "zebrawood": "zebrawood", "padauk": "padauk",
    "wenge": "wenge", "cocobolo": "cocobolo", "zircote": "zircote", "ziricote": "zircote",
    "bocote": "bocote", "katalox": "katalox", "paela": "paela",
    "madagascar rosewood": "rosewood",
}

LUTHIER_KEYWORDS = [
    "guitar", "bass", "neck", "body", "fretboard", "fingerboard", "top", "back",
    "side", "binding", "inlay", "luthier", "headplate", "veneer", "rosette",
    "drop top", "soundboard", "billet", "headstock",
]

EXCLUDE_KEYWORDS = [
    "pen blank", "bowl blank", "turning square", "knife scale", "pistol grip",
    "peppermill", "stopper", "bottle stopper", "spindle", "game call",
]


def _detect_species(text: str) -> str:
    text = text.lower()
    for key, val in SPECIES_MAP.items():
        if key in text:
            return val
    return "other"


def _is_luthier_product(title: str, tags: List[str]) -> bool:
    text = (title + " " + " ".join(tags)).lower()
    for keyword in EXCLUDE_KEYWORDS:
        if keyword in text:
            return False
    for keyword in LUTHIER_KEYWORDS:
        if keyword in text:
            return True
    return False


def _fetch_shopify_products(base_url: str, limit: int = 100) -> List[Dict[str, str]]:
    results = []
    page = 1

    while len(results) < limit:
        url = f"{base_url}/products.json?limit=250&page={page}"

        try:
            resp = requests.get(url, timeout=30, headers={"User-Agent": "Mozilla/5.0"})
            if resp.status_code != 200:
                break
            data = resp.json()
            products = data.get("products", [])
            if not products:
                break

            for p in products:
                title = p.get("title", "")
                tags = p.get("tags", [])
                if isinstance(tags, str):
                    tags = tags.split(", ")
                if not _is_luthier_product(title, tags):
                    continue

                variants = p.get("variants", [{}])
                price = variants[0].get("price", "0.00") if variants else "0.00"
                image = ""
                if p.get("images"):
                    image = p["images"][0].get("src", "")
                handle = p.get("handle", "")
                link = f"{base_url}/products/{handle}"
                category = p.get("product_type", "Wood")

                row = {
                    "id": f"ewz_{p['id']}",
                    "name": title,
                    "seller": "Exotic Wood Zone",
                    "species": _detect_species(title + " " + " ".join(tags)),
                    "price": f"${price}",
                    "listed_date": date.today().isoformat(),
                    "status": "Active",
                    "image_url": image,
                    "link": link,
                    "dimensions": "",
                    "figure": "",
                    "category": category,
                    "raw_attributes": ", ".join(tags),
                }
                results.append(row)
                if len(results) >= limit:
                    break

            page += 1
            time.sleep(0.5)

        except Exception:
            break

    return results


def _write_csv(path: str, rows: List[Dict[str, str]]) -> None:
    if not rows:
        return
    fieldnames = list(rows[0].keys())
    Path(path).parent.mkdir(parents=True, exist_ok=True)
    with open(path, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=fieldnames)
        writer.writeheader()
        writer.writerows(rows)


def run(data_dir: str, limit: int = 5000) -> str:
    """Run the Exotic Wood Zone scraper, writing output to data_dir/raw/exoticwood_latest.csv."""
    output_path = str(Path(data_dir) / "raw" / "exoticwood_latest.csv")
    rows = _fetch_shopify_products("https://exoticwoodzone.com", limit)
    if not rows:
        return "No products returned from Exotic Wood Zone."
    _write_csv(output_path, rows)
    return f"Scraped {len(rows)} items from Exotic Wood Zone to {output_path}"


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--limit", type=int, default=1000)
    parser.add_argument("--output", default="data/raw/exoticwood_latest.csv")
    args = parser.parse_args()
    data = _fetch_shopify_products("https://exoticwoodzone.com", args.limit)
    _write_csv(args.output, data)
    print(f"Scraped {len(data)} items from Exotic Wood Zone.")
