#!/usr/bin/env python3
import os
import sys
import re
import yaml

def print_error(msg):
    print(f"\033[91m[ERROR] {msg}\033[0m", file=sys.stderr)

def print_success(msg):
    print(f"\033[92m[SUCCESS] {msg}\033[0m")

def print_info(msg):
    print(f"[INFO] {msg}")

def main():
    errors_found = False

    # 1. Load valid roles from _data/types.yaml
    types_path = os.path.join('_data', 'types.yaml')
    if not os.path.exists(types_path):
        print_error(f"Could not find types file: {types_path}")
        sys.exit(1)

    with open(types_path, 'r', encoding='utf-8') as f:
        try:
            types_data = yaml.safe_load(f) or {}
        except Exception as e:
            print_error(f"Failed to parse {types_path}: {e}")
            sys.exit(1)

    # Valid roles are keys defined before 'link' (general configuration)
    valid_roles = []
    for key, val in types_data.items():
        if key == 'link':
            break
        valid_roles.append(key)

    print_info(f"Loaded valid roles: {', '.join(valid_roles)}")

    # 2. Lint member profiles in _members/
    members_dir = '_members'
    if not os.path.exists(members_dir):
        print_error(f"Could not find members directory: {members_dir}")
        errors_found = True
    else:
        print_info("Validating member profiles...")
        for filename in os.listdir(members_dir):
            if not filename.endswith('.md'):
                continue

            filepath = os.path.join(members_dir, filename)
            with open(filepath, 'r', encoding='utf-8') as f:
                content = f.read()

            # Parse front matter
            fm_match = re.match(r'^---\s*\n(.*?)\n---\s*\n', content, re.DOTALL)
            if not fm_match:
                print_error(f"{filepath}: Missing front matter delimiters (---)")
                errors_found = True
                continue

            try:
                fm = yaml.safe_load(fm_match.group(1)) or {}
            except Exception as e:
                print_error(f"{filepath}: Failed to parse YAML front matter: {e}")
                errors_found = True
                continue

            # Validate name
            if 'name' not in fm or not fm['name']:
                print_error(f"{filepath}: Missing or empty 'name'")
                errors_found = True

            # Validate role
            if 'role' not in fm or not fm['role']:
                print_error(f"{filepath}: Missing or empty 'role'")
                errors_found = True
            elif fm['role'] not in valid_roles:
                print_error(f"{filepath}: Invalid role '{fm['role']}'. Must be one of: {', '.join(valid_roles)}")
                errors_found = True

            # Validate affiliation
            if 'affiliation' not in fm or not fm['affiliation']:
                print_error(f"{filepath}: Missing or empty 'affiliation'")
                errors_found = True

            # Validate image exists in the repository
            if 'image' in fm and fm['image']:
                img_path = fm['image'].strip()
                # Clean leading slash if present
                if img_path.startswith('/'):
                    img_path = img_path[1:]

                # Check if image points to an existing file in repo
                if not os.path.exists(img_path):
                    print_error(f"{filepath}: Image '{img_path}' does not exist in the repository")
                    errors_found = True

    # 3. Lint manually managed citations in _data/sources.yaml
    sources_path = os.path.join('_data', 'sources.yaml')
    if os.path.exists(sources_path):
        print_info("Validating sources.yaml...")
        with open(sources_path, 'r', encoding='utf-8') as f:
            try:
                sources = yaml.safe_load(f) or []
            except Exception as e:
                print_error(f"Failed to parse {sources_path}: {e}")
                sources = []
                errors_found = True

        seen_ids = set()
        for idx, entry in enumerate(sources):
            if not isinstance(entry, dict):
                print_error(f"{sources_path} [index {idx}]: Entry is not a dictionary/object")
                errors_found = True
                continue

            entry_id = entry.get('id')
            if not entry_id:
                print_error(f"{sources_path} [index {idx}]: Entry is missing 'id'")
                errors_found = True
                continue

            # Validate DOI prefix
            if not str(entry_id).startswith('doi:'):
                print_error(f"{sources_path}: ID '{entry_id}' must start with 'doi:' prefix")
                errors_found = True

            # Validate uniqueness
            if entry_id in seen_ids:
                print_error(f"{sources_path}: Duplicate DOI ID '{entry_id}' found")
                errors_found = True
            seen_ids.add(entry_id)

    if errors_found:
        print_error("Linting failed. Please fix the errors above.")
        sys.exit(1)
    else:
        print_success("All YAML, DOI, and front-matter checks passed successfully!")
        sys.exit(0)

if __name__ == '__main__':
    main()
