#!/usr/bin/env python3
"""
generate_mod_list.py

Scan the `mods/` folder for `.pw.toml` files and generate a listing grouped by side: client, server, both.

Usage examples:
  # Dry run: print summary to console
  python scripts/generate_mod_list.py --mods-dir mods --dry-run

  # Write Markdown to README (preview first)
  python scripts/generate_mod_list.py --mods-dir mods --output readme.md --format markdown

The script will try to use tomllib (Python 3.11+). If not available and the `toml` package is installed, it will use that as a fallback.
"""

import argparse
import os
import glob
import sys
from pathlib import Path

try:
    import tomllib as toml_parser
    TOML_PARSER = 'tomllib'
except Exception:
    try:
        import toml as toml_parser
        TOML_PARSER = 'toml'
    except Exception:
        toml_parser = None
        TOML_PARSER = None


def parse_toml_file(path):
    data = None
    text = None
    try:
        with open(path, 'rb') as f:
            if TOML_PARSER == 'tomllib':
                data = toml_parser.load(f)
            elif TOML_PARSER == 'toml':
                # toml library expects text
                text = f.read().decode('utf-8')
                data = toml_parser.loads(text)
            else:
                raise RuntimeError('No TOML parser available. Install Python 3.11+ or the `toml` package.')
    except Exception as e:
        return None, str(e)
    return data, None


def collect_mods(mods_dir):
    mods_dir = Path(mods_dir)
    if not mods_dir.exists():
        raise FileNotFoundError(f"Mods directory not found: {mods_dir}")

    pattern = str(mods_dir / '*.pw.toml')
    files = sorted(glob.glob(pattern, recursive=False), key=lambda p: p.lower())

    client = []
    server = []
    both = []
    skipped = []

    for fp in files:
        data, err = parse_toml_file(fp)
        if err:
            skipped.append((fp, f"parse error: {err}"))
            continue

        # Read fields
        name = data.get('name') if isinstance(data, dict) else None
        filename = data.get('filename') if isinstance(data, dict) else None
        side = data.get('side') if isinstance(data, dict) else None

        # Normalize
        side_norm = None
        if isinstance(side, str):
            side_norm = side.strip().lower()

        entry = {
            'path': fp,
            'name': name or Path(fp).stem,
            'filename': filename or '',
            'side': side_norm or 'both',
        }

        if side_norm == 'client':
            client.append(entry)
        elif side_norm == 'server':
            server.append(entry)
        else:
            both.append(entry)

    return {
        'client': client,
        'server': server,
        'both': both,
        'skipped': skipped,
        'total': len(files),
    }


def generate_markdown_listing(mods):
    lines = []
    lines.append('# Mods listing (generated)')
    lines.append('')
    lines.append('This listing was generated by `scripts/generate_mod_list.py`. It groups mods by the `side` field in each `.pw.toml`.')
    lines.append('')

    def write_group(title, items):
        lines.append(f'## {title} ({len(items)})')
        lines.append('')
        if not items:
            lines.append('_No mods in this category._')
            lines.append('')
            return
        for it in items:
            name = it['name'] or Path(it['path']).stem
            filename = it.get('filename') or ''
            relpath = os.path.relpath(it['path'])
            if filename:
                lines.append(f'- **{name}** — `{filename}` — `{relpath}`')
            else:
                lines.append(f'- **{name}** — `{relpath}`')
        lines.append('')

    write_group('Client-only mods', mods['client'])
    write_group('Server-only mods', mods['server'])
    write_group('Client & Server (both)', mods['both'])

    if mods['skipped']:
        lines.append('## Skipped / warnings')
        lines.append('')
        for path, reason in mods['skipped']:
            lines.append(f'- `{path}` — {reason}')
        lines.append('')

    lines.append(f'Generated with parser: {TOML_PARSER or "none"}')
    lines.append('')
    return '\n'.join(lines)


def generate_simple_listing(mods):
    out = []
    out.append('Client-only mods:')
    for it in mods['client']:
        out.append(f" - {it['name']} ({it.get('filename','')})")
    out.append('')
    out.append('Server-only mods:')
    for it in mods['server']:
        out.append(f" - {it['name']} ({it.get('filename','')})")
    out.append('')
    out.append('Both:')
    for it in mods['both']:
        out.append(f" - {it['name']} ({it.get('filename','')})")
    out.append('')
    if mods['skipped']:
        out.append('Skipped:')
        for p, r in mods['skipped']:
            out.append(f" - {p}: {r}")
    return '\n'.join(out)


def parse_args():
    p = argparse.ArgumentParser(description='Generate mod listing from mods/*.pw.toml')
    p.add_argument('--mods-dir', default='mods', help='Directory containing .pw.toml files (default: mods)')
    p.add_argument('--output', '-o', help='Write output to file instead of printing')
    p.add_argument('--format', choices=['markdown', 'simple'], default='markdown', help='Output format')
    p.add_argument('--dry-run', action='store_true', help='Do not write output, only print summary')
    p.add_argument('--verbose', action='store_true', help='Verbose output')
    return p.parse_args()


def main():
    args = parse_args()

    if TOML_PARSER is None:
        print('No TOML parser available. Install Python 3.11+ (tomllib) or the `toml` package (pip install toml).')
        sys.exit(2)

    try:
        mods = collect_mods(args.mods_dir)
    except FileNotFoundError as e:
        print(f'ERROR: {e}')
        sys.exit(3)

    # Summary
    client_n = len(mods['client'])
    server_n = len(mods['server'])
    both_n = len(mods['both'])
    total = mods['total']

    print(f'Total manifests found: {total}')
    print(f'Client-only: {client_n}, Server-only: {server_n}, Both: {both_n}, Skipped: {len(mods["skipped"])})')

    if args.dry_run:
        # Print a short preview of each category
        if args.format == 'markdown':
            out = generate_markdown_listing(mods)
        else:
            out = generate_simple_listing(mods)
        print('\n--- Preview ---\n')
        print(out)
        return

    # If output specified, write formatted content
    if args.format == 'markdown':
        content = generate_markdown_listing(mods)
    else:
        content = generate_simple_listing(mods)

    if args.output:
        outpath = Path(args.output)
        # Make backup if file exists
        if outpath.exists():
            bak = outpath.with_suffix(outpath.suffix + '.bak')
            print(f'Backing up existing {outpath} to {bak}')
            outpath.replace(bak)
        outpath.write_text(content, encoding='utf-8')
        print(f'Wrote listing to {outpath} (format: {args.format})')
    else:
        print(content)


if __name__ == '__main__':
    main()
