#!/usr/bin/env python3
"""
WHALEN - The Autonomous Whale Hunter
Finds, qualifies, scans, and reaches out to whales 24/7
GOAL: Generate revenue while you sleep
"""
import sqlite3
import requests
import json
import time
import random
import smtplib
import subprocess
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from datetime import datetime, timedelta
from pathlib import Path

# Config
DB_PATH = "/Eden/DATA/whale_crm.db"
CONFIG_PATH = "/Eden/CONFIG/whale_templates.json"
EMAIL_CONFIG = "/Eden/SECRETS/email_config.json"
GITHUB_TOKEN = Path("/Eden/SECRETS/github_token").read_text().strip()

# Limits - SAFE outreach
MAX_OUTREACH_PER_DAY = 2
MAX_FOLLOWUPS_PER_DAY = 3
HOURS_BEFORE_FOLLOWUP = 48

PHI = 1.618033988749895

def log(msg):
    print(f"[{datetime.now().strftime('%H:%M:%S')}] 🐋 {msg}")

def init_db():
    conn = sqlite3.connect(DB_PATH)
    c = conn.cursor()
    
    c.execute('''CREATE TABLE IF NOT EXISTS whales (
        id INTEGER PRIMARY KEY,
        company TEXT UNIQUE,
        website TEXT,
        funding TEXT,
        funding_amount TEXT,
        employees TEXT,
        industry TEXT,
        cto_name TEXT,
        cto_email TEXT,
        cto_linkedin TEXT,
        github_org TEXT,
        pain_points TEXT,
        stage TEXT DEFAULT 'identified',
        score INTEGER DEFAULT 0,
        risk_grade TEXT,
        scan_results TEXT,
        notes TEXT,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        last_contacted TIMESTAMP,
        followup_count INTEGER DEFAULT 0
    )''')
    
    c.execute('''CREATE TABLE IF NOT EXISTS outreach_log (
        id INTEGER PRIMARY KEY,
        whale_id INTEGER,
        type TEXT,
        template TEXT,
        sent_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        response TEXT,
        FOREIGN KEY (whale_id) REFERENCES whales(id)
    )''')
    
    conn.commit()
    conn.close()

def load_templates():
    return json.loads(Path(CONFIG_PATH).read_text())

def load_email_config():
    return json.loads(Path(EMAIL_CONFIG).read_text())

# ============ WHALE FINDING ============

def search_github_for_whales():
    """Find repos with whale signals"""
    log("Searching GitHub for whales...")
    
    WHALE_SIGNALS = [
        "SOC2 compliance",
        "HIPAA security",
        "Series A startup",
        "enterprise security",
        "security audit needed",
        "penetration testing",
        "ISO 27001",
        "we're hiring security engineer",
        "security questionnaire",
    ]
    
    headers = {"Authorization": f"token {GITHUB_TOKEN}"}
    
    whales_found = []
    signal = random.choice(WHALE_SIGNALS)
    
    log(f"Signal: {signal}")
    
    try:
        # Search repos
        resp = requests.get(
            "https://api.github.com/search/repositories",
            headers=headers,
            params={"q": f"{signal} in:readme,description", "sort": "updated", "per_page": 10},
            timeout=30
        )
        
        if resp.status_code == 200:
            for repo in resp.json().get("items", [])[:5]:
                owner = repo.get("owner", {})
                org = owner.get("login", "")
                
                # Skip individuals, want orgs
                if owner.get("type") != "Organization":
                    continue
                
                # Check if already in DB
                conn = sqlite3.connect(DB_PATH)
                c = conn.cursor()
                c.execute("SELECT id FROM whales WHERE company=? OR github_org=?", (org, org))
                exists = c.fetchone()
                conn.close()
                
                if exists:
                    continue
                
                whale = {
                    "company": org,
                    "website": repo.get("homepage") or f"https://github.com/{org}",
                    "github_org": org,
                    "industry": "tech",
                    "pain_points": signal,
                    "score": min(100, repo.get("stargazers_count", 0) // 10),
                }
                
                whales_found.append(whale)
                log(f"  Found: {org}")
        
        # Search issues for pain signals
        resp = requests.get(
            "https://api.github.com/search/issues",
            headers=headers,
            params={"q": f"{signal} is:issue is:open", "sort": "created", "per_page": 5},
            timeout=30
        )
        
        if resp.status_code == 200:
            for issue in resp.json().get("items", [])[:3]:
                repo_url = issue.get("repository_url", "")
                if repo_url:
                    org = repo_url.split("/")[-2]
                    
                    conn = sqlite3.connect(DB_PATH)
                    c = conn.cursor()
                    c.execute("SELECT id FROM whales WHERE company=? OR github_org=?", (org, org))
                    exists = c.fetchone()
                    conn.close()
                    
                    if not exists and org not in [w["company"] for w in whales_found]:
                        whales_found.append({
                            "company": org,
                            "github_org": org,
                            "pain_points": signal,
                            "score": 30,
                        })
                        log(f"  Found (issue): {org}")
    
    except Exception as e:
        log(f"Search error: {e}")
    
    return whales_found

def save_whales(whales):
    """Save whales to database"""
    conn = sqlite3.connect(DB_PATH)
    c = conn.cursor()
    
    for whale in whales:
        try:
            c.execute("""INSERT OR IGNORE INTO whales 
                        (company, website, github_org, industry, pain_points, score, stage)
                        VALUES (?, ?, ?, ?, ?, ?, 'identified')""",
                     (whale.get("company"), whale.get("website"), whale.get("github_org"),
                      whale.get("industry"), whale.get("pain_points"), whale.get("score", 0)))
        except:
            pass
    
    conn.commit()
    conn.close()

# ============ WHALE QUALIFICATION ============

def qualify_whale(whale_id):
    """Research and score a whale"""
    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row
    c = conn.cursor()
    c.execute("SELECT * FROM whales WHERE id=?", (whale_id,))
    whale = dict(c.fetchone())
    conn.close()
    
    github_org = whale.get("github_org")
    if not github_org:
        return 0
    
    headers = {"Authorization": f"token {GITHUB_TOKEN}"}
    score = whale.get("score", 0)
    
    try:
        # Get org info
        resp = requests.get(f"https://api.github.com/orgs/{github_org}", headers=headers, timeout=30)
        if resp.status_code == 200:
            org_data = resp.json()
            
            # Company size signals
            if org_data.get("company"):
                score += 20
            
            # Blog/website = established
            if org_data.get("blog"):
                score += 10
                
            # Email available
            if org_data.get("email"):
                score += 30
                # Update whale with email
                conn = sqlite3.connect(DB_PATH)
                c = conn.cursor()
                c.execute("UPDATE whales SET cto_email=? WHERE id=?", (org_data["email"], whale_id))
                conn.commit()
                conn.close()
        
        # Check for security-related repos
        resp = requests.get(f"https://api.github.com/orgs/{github_org}/repos", headers=headers, params={"per_page": 10}, timeout=30)
        if resp.status_code == 200:
            repos = resp.json()
            
            for repo in repos:
                desc = (repo.get("description") or "").lower()
                name = repo.get("name", "").lower()
                
                # SaaS/product signals
                if any(x in desc + name for x in ["api", "sdk", "platform", "saas", "app"]):
                    score += 15
                    break
    
    except Exception as e:
        log(f"Qualification error: {e}")
    
    # Update score
    conn = sqlite3.connect(DB_PATH)
    c = conn.cursor()
    c.execute("UPDATE whales SET score=?, stage='qualified' WHERE id=?", (score, whale_id))
    conn.commit()
    conn.close()
    
    return score

# ============ WHALE SCANNING ============

def scan_whale(whale_id):
    """Run security scan on whale's repos"""
    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row
    c = conn.cursor()
    c.execute("SELECT * FROM whales WHERE id=?", (whale_id,))
    whale = dict(c.fetchone())
    conn.close()
    
    github_org = whale.get("github_org")
    if not github_org:
        return None
    
    log(f"Scanning {github_org}...")
    
    try:
        result = subprocess.run(
            ["python3", "/Eden/PRO/scans/enterprise_scanner.py", f"https://github.com/{github_org}"],
            capture_output=True, text=True, timeout=300
        )
        
        # Parse grade from output
        grade = "?"
        for line in result.stdout.split("\n"):
            if "RISK GRADE:" in line:
                grade = line.split(":")[-1].strip()
                break
        
        # Update whale
        conn = sqlite3.connect(DB_PATH)
        c = conn.cursor()
        c.execute("UPDATE whales SET risk_grade=?, stage='scanned' WHERE id=?", (grade, whale_id))
        conn.commit()
        conn.close()
        
        log(f"  Grade: {grade}")
        return grade
        
    except Exception as e:
        log(f"Scan error: {e}")
        return None

# ============ WHALE OUTREACH ============

def get_outreach_count_today():
    """Check how many outreach emails sent today"""
    conn = sqlite3.connect(DB_PATH)
    c = conn.cursor()
    c.execute("""SELECT COUNT(*) FROM outreach_log 
                 WHERE date(sent_at) = date('now') AND type='cold_email'""")
    count = c.fetchone()[0]
    conn.close()
    return count

def get_whales_for_outreach(limit=5):
    """Get qualified whales ready for outreach"""
    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row
    c = conn.cursor()
    
    c.execute("""SELECT * FROM whales 
                 WHERE stage IN ('qualified', 'scanned')
                 AND cto_email IS NOT NULL
                 AND last_contacted IS NULL
                 ORDER BY score DESC
                 LIMIT ?""", (limit,))
    
    whales = [dict(row) for row in c.fetchall()]
    conn.close()
    return whales

def get_whales_for_followup():
    """Get whales needing follow-up"""
    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row
    c = conn.cursor()
    
    cutoff = (datetime.now() - timedelta(hours=HOURS_BEFORE_FOLLOWUP)).isoformat()
    
    c.execute("""SELECT * FROM whales 
                 WHERE stage = 'contacted'
                 AND last_contacted < ?
                 AND followup_count < 2
                 ORDER BY score DESC
                 LIMIT 10""", (cutoff,))
    
    whales = [dict(row) for row in c.fetchall()]
    conn.close()
    return whales

def send_email(to_email, subject, body):
    """Send email via configured SMTP"""
    try:
        config = load_email_config()
        
        msg = MIMEMultipart()
        msg['From'] = f"Eden SAGE <{config['user']}>"
        msg['To'] = to_email
        msg['Subject'] = subject
        
        msg.attach(MIMEText(body, 'plain'))
        
        with smtplib.SMTP(config['smtp_server'], 587) as server:
            server.starttls()
            server.login(config['user'], config['password'])
            server.send_message(msg)
        
        return True
    except Exception as e:
        log(f"Email error: {e}")
        return False

def send_whale_outreach(whale):
    """Send cold email to whale"""
    templates = load_templates()
    template = templates["templates"]["cold_email_v1"]
    
    # Build email
    subject = template["subject"].replace("{company}", whale["company"])
    body = template["body"]
    
    replacements = {
        "{company}": whale["company"],
        "{cto_name}": whale.get("cto_name") or "there",
        "{funding}": whale.get("funding") or "your growth",
        "{industry}": whale.get("industry") or "tech",
        "{social_proof}": "SmolTech, iris-GmbH, and kubernetes ecosystem projects"
    }
    
    for key, value in replacements.items():
        body = body.replace(key, str(value))
    
    log(f"Emailing {whale['company']} ({whale['cto_email']})...")
    
    if send_email(whale["cto_email"], subject, body):
        # Log outreach
        conn = sqlite3.connect(DB_PATH)
        c = conn.cursor()
        c.execute("UPDATE whales SET stage='contacted', last_contacted=CURRENT_TIMESTAMP WHERE id=?", (whale["id"],))
        c.execute("INSERT INTO outreach_log (whale_id, type, template) VALUES (?, 'cold_email', 'cold_email_v1')", (whale["id"],))
        conn.commit()
        conn.close()
        log(f"  ✅ Sent!")
        return True
    
    return False

def send_whale_followup(whale):
    """Send follow-up email"""
    templates = load_templates()
    
    followup_num = whale.get("followup_count", 0) + 1
    template_key = f"followup_{followup_num}" if followup_num <= 2 else "followup_2"
    template = templates["templates"].get(template_key, templates["templates"]["followup_1"])
    
    subject = template["subject"].replace("{company}", whale["company"])
    body = template["body"].replace("{company}", whale["company"]).replace("{cto_name}", whale.get("cto_name") or "there")
    
    log(f"Follow-up #{followup_num} to {whale['company']}...")
    
    if send_email(whale["cto_email"], subject, body):
        conn = sqlite3.connect(DB_PATH)
        c = conn.cursor()
        c.execute("UPDATE whales SET last_contacted=CURRENT_TIMESTAMP, followup_count=? WHERE id=?", 
                  (followup_num, whale["id"]))
        c.execute("INSERT INTO outreach_log (whale_id, type, template) VALUES (?, 'followup', ?)", 
                  (whale["id"], template_key))
        conn.commit()
        conn.close()
        log(f"  ✅ Sent!")
        return True
    
    return False

# ============ MAIN LOOP ============

def get_stats():
    """Get pipeline stats"""
    conn = sqlite3.connect(DB_PATH)
    c = conn.cursor()
    
    c.execute("SELECT COUNT(*) FROM whales")
    total = c.fetchone()[0]
    
    c.execute("SELECT COUNT(*) FROM whales WHERE stage='contacted'")
    contacted = c.fetchone()[0]
    
    c.execute("SELECT COUNT(*) FROM outreach_log WHERE date(sent_at)=date('now')")
    today = c.fetchone()[0]
    
    conn.close()
    return {"total": total, "contacted": contacted, "today": today}

def run_cycle():
    """Run one whale hunting cycle"""
    log("=" * 50)
    log("WHALEN CYCLE")
    log("=" * 50)
    
    stats = get_stats()
    log(f"Pipeline: {stats['total']} whales | {stats['contacted']} contacted | {stats['today']} today")
    
    # Check daily limit
    outreach_today = get_outreach_count_today()
    if outreach_today >= MAX_OUTREACH_PER_DAY:
        log(f"Daily outreach limit reached ({outreach_today}/{MAX_OUTREACH_PER_DAY})")
    else:
        # 1. Find new whales
        new_whales = search_github_for_whales()
        if new_whales:
            save_whales(new_whales)
            log(f"Added {len(new_whales)} new whales")
        
        # 2. Qualify unqualified whales
        conn = sqlite3.connect(DB_PATH)
        c = conn.cursor()
        c.execute("SELECT id FROM whales WHERE stage='identified' LIMIT 3")
        to_qualify = [row[0] for row in c.fetchall()]
        conn.close()
        
        for whale_id in to_qualify:
            score = qualify_whale(whale_id)
            log(f"Qualified whale {whale_id}: score {score}")
        
        # 3. Send outreach (if under limit)
        remaining = MAX_OUTREACH_PER_DAY - outreach_today
        if remaining > 0:
            whales = get_whales_for_outreach(remaining)
            for whale in whales:
                send_whale_outreach(whale)
                time.sleep(random.randint(60, 180))  # Human-like delay
    
    # 4. Send follow-ups
    followup_whales = get_whales_for_followup()
    for whale in followup_whales[:MAX_FOLLOWUPS_PER_DAY]:
        send_whale_followup(whale)
        time.sleep(random.randint(30, 90))
    
    log("Cycle complete")

def main():
    log("🐋 WHALEN STARTING - Hunting whales for the Whalen family")
    log(f"Max outreach/day: {MAX_OUTREACH_PER_DAY}")
    log(f"Followup after: {HOURS_BEFORE_FOLLOWUP}h")
    
    init_db()
    
    while True:
        try:
            run_cycle()
            
            # Wait 2-4 hours between cycles (phi-based)
            wait_hours = 2 * PHI + random.random()
            wait_seconds = int(wait_hours * 3600)
            next_run = datetime.now() + timedelta(seconds=wait_seconds)
            
            log(f"Next cycle: {next_run.strftime('%H:%M')}")
            time.sleep(wait_seconds)
            
        except KeyboardInterrupt:
            log("Shutting down...")
            break
        except Exception as e:
            log(f"Error: {e}")
            time.sleep(300)

if __name__ == "__main__":
    main()
