#!/usr/bin/env python3
"""
ArXiv Daily Bot - Minimal version for cron jobs.
Finds interesting papers and generates a daily digest.
"""

import json
import urllib.request
import urllib.parse
import xml.etree.ElementTree as ET
from datetime import datetime, timedelta
from pathlib import Path
import time
import re


def fetch_arxiv_papers(category='cs.SD', days_back=1, max_results=200):
    """Fetch recent papers from arXiv API."""
    base_url = 'http://export.arxiv.org/api/query?'
    query = f'cat:{category}'
    params = {
        'search_query': query,
        'start': 0,
        'max_results': max_results,
        'sortBy': 'submittedDate',
        'sortOrder': 'descending'
    }

    url = base_url + urllib.parse.urlencode(params)
    response = urllib.request.urlopen(url)
    data = response.read().decode('utf-8')

    root = ET.fromstring(data)
    ns = {'atom': 'http://www.w3.org/2005/Atom'}

    papers = []
    cutoff_date = datetime.now() - timedelta(days=days_back)

    for entry in root.findall('atom:entry', ns):
        arxiv_id = entry.find('atom:id', ns).text.split('/abs/')[-1]
        title = entry.find('atom:title', ns).text.strip().replace('\n', ' ')
        abstract = entry.find('atom:summary', ns).text.strip().replace('\n', ' ')
        published = entry.find('atom:published', ns).text
        pub_date = datetime.strptime(published[:10], '%Y-%m-%d')

        if pub_date >= cutoff_date:
            papers.append({
                'arxiv_id': arxiv_id,
                'url': f'https://arxiv.org/abs/{arxiv_id}',
                'title': title,
                'abstract': abstract,
                'published': published[:10]
            })

    return papers


def compute_similarity(text1, text2):
    """Simple word-based similarity."""
    words1 = set(re.findall(r'\b\w+\b', text1.lower()))
    words2 = set(re.findall(r'\b\w+\b', text2.lower()))

    stopwords = {'the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for',
                 'of', 'with', 'by', 'from', 'is', 'are', 'was', 'were', 'be', 'been',
                 'we', 'this', 'that', 'these', 'those', 'which', 'using', 'use'}

    words1 = words1 - stopwords
    words2 = words2 - stopwords

    if not words1 or not words2:
        return 0.0

    intersection = len(words1 & words2)
    union = len(words1 | words2)

    return intersection / union if union > 0 else 0.0


def score_papers(papers, profile, threshold=0.15):
    """Score papers based on interest profile."""
    scored = []

    for paper in papers:
        paper_text = f"{paper['title']} {paper['abstract']}"

        # Compare against summaries
        max_similarity = 0
        for summary in profile.get('summaries', []):
            similarity = compute_similarity(paper_text, summary)
            max_similarity = max(max_similarity, similarity)

        # Keyword bonus
        keyword_score = 0
        paper_words = set(re.findall(r'\b\w+\b', paper_text.lower()))
        for keyword in profile.get('top_keywords', [])[:20]:
            if keyword in paper_words:
                keyword_score += 1

        combined_score = max_similarity + (keyword_score * 0.02)

        if combined_score >= threshold:
            paper['interest_score'] = combined_score
            scored.append(paper)

    return sorted(scored, key=lambda x: x['interest_score'], reverse=True)


def generate_digest(papers, output_file):
    """Generate markdown digest."""
    lines = [
        f"# ArXiv Daily Digest - {datetime.now().strftime('%Y-%m-%d')}",
        "",
        f"Found **{len(papers)}** interesting papers:",
        ""
    ]

    for i, paper in enumerate(papers, 1):
        lines.append(f"## {i}. {paper['title']}")
        lines.append(f"**Score:** {paper['interest_score']:.3f} | **Published:** {paper['published']}")
        lines.append(f"**URL:** {paper['url']}")
        lines.append("")
        lines.append(f"**Abstract:** {paper['abstract'][:400]}...")
        lines.append("")
        lines.append("---")
        lines.append("")

    with open(output_file, 'w') as f:
        f.write('\n'.join(lines))


def main():
    import argparse

    parser = argparse.ArgumentParser()
    parser.add_argument('--categories', default='cs.SD,cs.LG,cs.CL')
    parser.add_argument('--days', type=int, default=1)
    parser.add_argument('--threshold', type=float, default=0.15)
    parser.add_argument('--output', default='digest.md')
    parser.add_argument('--profile', default='interest_profile.json')

    args = parser.parse_args()

    # Load profile
    profile_path = Path(args.profile)
    if not profile_path.exists():
        print(f"Error: {profile_path} not found")
        print("Copy your interest profile here first")
        return 1

    with open(profile_path) as f:
        profile = json.load(f)

    print(f"Loaded profile: {profile.get('papers_analyzed', 0)} papers")

    # Fetch papers
    all_papers = []
    for category in args.categories.split(','):
        print(f"Fetching {category}...")
        papers = fetch_arxiv_papers(category.strip(), args.days)
        all_papers.extend(papers)
        time.sleep(3)

    # Remove duplicates
    seen = set()
    unique = []
    for paper in all_papers:
        if paper['arxiv_id'] not in seen:
            seen.add(paper['arxiv_id'])
            unique.append(paper)

    print(f"Total papers: {len(unique)}")

    # Score papers
    interesting = score_papers(unique, profile, args.threshold)
    print(f"Interesting papers: {len(interesting)}")

    if interesting:
        # Generate digest
        generate_digest(interesting, args.output)
        print(f"✓ Digest saved to {args.output}")

        # Print top 3
        print("\nTop 3:")
        for i, paper in enumerate(interesting[:3], 1):
            print(f"{i}. {paper['title']}")
            print(f"   Score: {paper['interest_score']:.3f}")
            print(f"   {paper['url']}\n")
    else:
        print("No interesting papers found")

    return 0


if __name__ == '__main__':
    exit(main())
