import csv
import re
import requests
from collections import defaultdict

ACCESS_TOKEN_SANDBOX = "EAAAl60tZLgxdxhvD2Jdh7dRXcJz8nSsvcBW6g9rlXDVof6xFrXWMd29UCbOYmyW"
ACCESS_TOKEN = "EAAAlzTxcLpe46hddBlJOn5W7kw7AhlOS75IQoVrilB1LbXfO5qH0RlKZj4ceXQN"

BASE_URL = "https://connect.squareup.com/v2"

HEADERS_OLD = {
    "Authorization": f"Bearer {ACCESS_TOKEN}",
    "Content-Type": "application/json"
}

HEADERS_NEW = {
    "Authorization": f"Bearer {ACCESS_TOKEN_SANDBOX}",
    "Content-Type": "application/json"
}

INPUT_CSV = "square_item_images_old_store.csv"
OUTPUT_MATCHED = "square_image_relink_map.csv"
OUTPUT_UNMATCHED = "square_image_unmatched.csv"


def norm_name(s: str) -> str:
    """Normalize names so small differences (case, extra spaces, punctuation) don't break matches."""
    if not s:
        return ""
    s = s.strip().lower()
    s = s.replace("&", "and")
    s = re.sub(r"[\u2018\u2019\u201c\u201d]", "'", s)  # smart quotes → plain
    s = re.sub(r"[^a-z0-9\s\-]", " ", s)               # remove weird punctuation
    s = re.sub(r"\s+", " ", s).strip()                 # collapse whitespace
    return s


def fetch_new_store_items():
    """Pull all ITEM objects from the NEW store."""
    objects = []
    cursor = None
    while True:
        payload = {
            "object_types": ["ITEM"]
        }
        if cursor:
            payload["cursor"] = cursor

        r = requests.post(f"{BASE_URL}/catalog/search", headers=HEADERS_NEW, json=payload)
        r.raise_for_status()
        data = r.json()
        objects.extend(data.get("objects", []))
        cursor = data.get("cursor")
        if not cursor:
            break
    return objects


def build_new_item_index(new_items):
    """
    Returns:
      - name_index: normalized_name -> list of {item_id, raw_name}
      - raw_map: item_id -> raw_name
    """
    name_index = defaultdict(list)
    raw_map = {}

    for obj in new_items:
        item_id = obj.get("id")
        item_data = obj.get("item_data", {})
        raw_name = item_data.get("name", "") or ""

        raw_map[item_id] = raw_name
        key = norm_name(raw_name)
        if key:
            name_index[key].append({"new_item_id": item_id, "new_item_name": raw_name})

    return name_index, raw_map


def main():
    # 1) Load old-store image mapping CSV
    old_rows = []
    with open(INPUT_CSV, "r", newline="") as f:
        reader = csv.DictReader(f)
        for row in reader:
            old_rows.append(row)

    print(f"Loaded {len(old_rows)} old-store item→image rows from {INPUT_CSV}")

    # 2) Pull new-store items
    new_items = fetch_new_store_items()
    print(f"Pulled {len(new_items)} ITEM objects from NEW store")

    # 3) Index new items by normalized name
    name_index, _ = build_new_item_index(new_items)
    print(f"Indexed {len(name_index)} unique normalized item names in NEW store")

    # 4) Match by item_name
    matched = []
    unmatched = []

    for row in old_rows:
        old_item_name = row.get("item_name", "") or ""
        key = norm_name(old_item_name)

        candidates = name_index.get(key, [])
        if not candidates:
            row["match_status"] = "NO_MATCH"
            unmatched.append(row)
            continue

        if len(candidates) > 1:
            # Same name exists multiple times in the new store (rare, but possible)
            # Keep them all so you can choose; also mark ambiguous.
            for c in candidates:
                out = dict(row)
                out["match_status"] = "AMBIGUOUS_NAME_MULTIPLE_NEW_ITEMS"
                out["new_item_id"] = c["new_item_id"]
                out["new_item_name"] = c["new_item_name"]
                matched.append(out)
        else:
            c = candidates[0]
            out = dict(row)
            out["match_status"] = "MATCHED"
            out["new_item_id"] = c["new_item_id"]
            out["new_item_name"] = c["new_item_name"]
            matched.append(out)

    print(f"Matched rows: {len(matched)}")
    print(f"Unmatched rows: {len(unmatched)}")

    # 5) Export matched + unmatched
    matched_fields = [
        "match_status",
        "item_id", "item_name",
        "new_item_id", "new_item_name",
        "image_id", "image_url"
    ]
    with open(OUTPUT_MATCHED, "w", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=matched_fields)
        writer.writeheader()
        for r in matched:
            writer.writerow({k: r.get(k, "") for k in matched_fields})

    unmatched_fields = list(old_rows[0].keys()) + ["match_status"] if old_rows else ["match_status"]
    # de-dupe field list
    seen = set()
    unmatched_fields = [x for x in unmatched_fields if not (x in seen or seen.add(x))]

    with open(OUTPUT_UNMATCHED, "w", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=unmatched_fields)
        writer.writeheader()
        for r in unmatched:
            if "match_status" not in r:
                r["match_status"] = "NO_MATCH"
            writer.writerow({k: r.get(k, "") for k in unmatched_fields})

    print(f"Wrote matched:   {OUTPUT_MATCHED}")
    print(f"Wrote unmatched: {OUTPUT_UNMATCHED}")


if __name__ == "__main__":
    main()