import json
import re
from pathlib import Path

# ================================
# REGEX PATTERNS
# ================================

ID_PATTERN = re.compile(r"^:ID:\s*(.+)", re.MULTILINE)
TITLE_PATTERN = re.compile(r"^#\+title:\s*(.+)", re.IGNORECASE | re.MULTILINE)

# Org links:
# [[id:...]]
# [[file:...]]
# [[./...]]
LINK_PATTERN = re.compile(r"\[\[(.*?)\]\]")


# ================================
# PARSING FUNCTIONS
# ================================

def parse_org_file(file_path):
    """Extract ID, title, and links from an Org file."""
    content = file_path.read_text(encoding="utf-8", errors="ignore")

    id_match = ID_PATTERN.search(content)
    title_match = TITLE_PATTERN.search(content)

    org_id = id_match.group(1).strip() if id_match else None
    title = title_match.group(1).strip() if title_match else "Untitled"

    links = extract_links(content)

    return org_id, title, links


def extract_links(content):
    """Extract all internal Org links."""
    raw_links = LINK_PATTERN.findall(content)

    links = []

    for link in raw_links:
        # Remove description part: [[link][desc]]
        if "][" in link:
            link = link.split("][")[0]

        # ID links
        if link.startswith("id:"):
            links.append(link.replace("id:", "").strip())

        # File links
        elif link.startswith("file:"):
            path = link.replace("file:", "").strip()
            links.append(path)

        # Relative links
        elif link.endswith(".org"):
            links.append(link.strip())

    return links


# ================================
# MAIN GENERATOR
# ================================

def generate_search_index(org_dir, out_file):
    print("Generating search-index.json with links...")

    org_dir = Path(org_dir).expanduser()
    out_file = Path(out_file).expanduser()

    org_files = [
        f for f in org_dir.rglob("*.org")
        if not re.search(r"/\.#[^/]+\.org$", str(f))
    ]

    # First pass: collect all files + IDs
    file_map = {}  # id -> url
    path_map = {}  # relative path -> url
    temp_entries = []

    for file_path in org_files:
        org_id, title, links = parse_org_file(file_path)
        relative = file_path.relative_to(org_dir).with_suffix('')
        url = f"/{relative}.html"

        if org_id:
            file_map[org_id] = url

        path_map[str(relative) + ".org"] = url

        temp_entries.append({
            "title": title,
            "url": url,
            "id": org_id,
            "raw_links": links
        })

    # Second pass: resolve links → URLs
    index = []

    for entry in temp_entries:
        resolved_links = []

        for link in entry["raw_links"]:
            # ID link
            if link in file_map:
                resolved_links.append(file_map[link])

            # File link
            elif link in path_map:
                resolved_links.append(path_map[link])

        index.append({
            "title": entry["title"],
            "url": entry["url"],
            "id": entry["id"],
            "links": list(set(resolved_links))  # remove duplicates
        })

    # De-duplicate by ID
    seen_ids = set()
    unique_index = []
    for entry in index:
        if entry["id"] and entry["id"] not in seen_ids:
            unique_index.append(entry)
            seen_ids.add(entry["id"])

    out_file.parent.mkdir(parents=True, exist_ok=True)

    with open(out_file, "w", encoding="utf-8") as f:
        json.dump(unique_index, f, ensure_ascii=False, indent=2)

    print(f"search-index.json generated ({len(unique_index)} entries).")


# ================================
# ALL FILES JSON (UNCHANGED)
# ================================

def generate_all_files_json(search_index_file, out_file):
    search_index_file = Path(search_index_file).expanduser()
    out_file = Path(out_file).expanduser()

    with open(search_index_file, "r", encoding="utf-8") as f:
        data = json.load(f)

    print(f"Loaded {len(data)} entries from {search_index_file}")

    data.sort(key=lambda x: x.get("title", "").lower())

    grouped = {}
    for entry in data:
        title = entry.get("title", "")
        if not title:
            continue
        letter = title[0].upper()
        grouped.setdefault(letter, []).append({
            "id": entry["id"],
            "title": title,
            "url": entry["url"]
        })

    output = {
        "title": "All Files",
        "description": "A complete alphabetical index of all published pages.",
        "groups": grouped,
    }

    with open(out_file, "w", encoding="utf-8") as f:
        json.dump(output, f, ensure_ascii=False, indent=2)

    print(f"all-files.json generated → {out_file}")


# ================================
# ENTRY POINT
# ================================

def main():
    base_dir = Path.home() / "master-folder" / "org_files" / "org_roam"
    search_index = base_dir / "output" / "search-index.json"
    all_files_json = base_dir / "all-files.json"

    generate_search_index(base_dir, search_index)
    generate_all_files_json(search_index, all_files_json)


if __name__ == "__main__":
    main()
