#!/usr/bin/env python3
"""CannaDeals FL - Tiered Deal Posting Engine with Verification"""

import asyncio
import json
import sys
import logging
import httpx
from datetime import datetime
from pathlib import Path
from typing import Optional, Dict, List, Any

try:
    from twikit import Client
except ImportError:
    print("ERROR: twikit not installed")
    sys.exit(1)

from posted_db import check_posted, record_post, init_db, generate_deal_hash

# Configuration
DEALS_API = "https://www.cannadealsfl.com/api/deals"
COOKIES_PATH = Path(__file__).parent / "x_cookies.json"
LOG_PATH = Path(__file__).parent / "post_deal_v2.log"

# TIER SYSTEM
TIER_1 = ["jungle boys", "the flowery", "cookies", "goldflower", "gold flower"]
TIER_2 = ["sunburn", "sunburn cannabis", "trulieve", "muv", "rise"]
TIER_3 = ["surterra", "curaleaf", "planet 13", "planet13", "grow healthy"]
SKIP_DISPOS = ["ayr", "green dragon", "cannabist", "sanctuary", "one plant", "eden", "fluent"]

# Track posting cycle position
CYCLE_FILE = Path(__file__).parent / ".posting_cycle"

DISPO_HASHTAGS = {
    "jungle boys": "#JungleBoys", "the flowery": "#TheFlowery", "cookies": "#Cookies",
    "goldflower": "#GoldFlower", "sunburn": "#Sunburn", "trulieve": "#Trulieve",
    "muv": "#MUV", "rise": "#RiseDispensary", "surterra": "#Surterra",
    "curaleaf": "#Curaleaf", "planet 13": "#Planet13", "planet13": "#Planet13",
    "grow healthy": "#GrowHealthy"
}
BASE_HASHTAGS = "#FLMedicalTrees #FloridaCannabis #MMJ"

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[logging.FileHandler(LOG_PATH), logging.StreamHandler()]
)
logger = logging.getLogger(__name__)


def get_tier(dispo_name: str) -> int:
    """Get tier for dispensary (1=high, 2=mid, 3=low, 0=skip)."""
    d = dispo_name.lower()
    for skip in SKIP_DISPOS:
        if skip in d:
            return 0
    if any(t in d for t in TIER_1):
        return 1
    if any(t in d for t in TIER_2):
        return 2
    if any(t in d for t in TIER_3):
        return 3
    return 0


def get_next_tier() -> int:
    """Get next tier based on posting cycle (5:2:1 ratio)."""
    cycle = [1, 1, 2, 1, 1, 2, 1, 3]  # 5 tier1, 2 tier2, 1 tier3
    
    if CYCLE_FILE.exists():
        pos = int(CYCLE_FILE.read_text().strip())
    else:
        pos = 0
    
    next_tier = cycle[pos % len(cycle)]
    CYCLE_FILE.write_text(str(pos + 1))
    return next_tier


def fetch_deals() -> List[Dict[str, Any]]:
    """Fetch deals from API."""
    try:
        with httpx.Client(timeout=30.0) as client:
            response = client.get(DEALS_API)
            response.raise_for_status()
            return response.json().get("deals", [])
    except Exception as e:
        logger.error(f"Failed to fetch deals: {e}")
        return []


def score_deal(deal: Dict) -> int:
    """Score deal quality."""
    score = 0
    title = (deal.get("title") or "").lower()
    desc = (deal.get("description") or "").lower()
    
    keywords = {"flash sale": 10, "limited time": 8, "today only": 8, "bogo": 7}
    for kw, pts in keywords.items():
        if kw in title or kw in desc:
            score += pts
    
    if "$" in title and "%" in title:
        score += 5
    if any(x in title for x in ["35%", "40%", "50%", "60%"]):
        score += 5
    if "flower" in title:
        score += 5
    if any(x in title for x in ["rosin", "live rosin", "live resin"]):
        score += 3
    if any(x in title for x in ["$15", "$20", "$25", "$30"]):
        score += 2
    
    return score


def format_tweet(deal: Dict) -> str:
    """Format deal for Twitter."""
    title = deal.get("title", "")
    dispo = deal.get("dispensary", {}).get("name", "")
    dispo_slug = dispo.lower()
    
    # Get hashtag
    dispo_tag = ""
    for key, tag in DISPO_HASHTAGS.items():
        if key in dispo_slug:
            dispo_tag = tag
            break
    
    # Build hook
    hook = title
    if dispo and dispo.lower() not in title.lower():
        hook = f"{title} @ {dispo}"
    if len(hook) > 70:
        hook = hook[:67] + "..."
    
    # Extract highlights from description
    desc = deal.get("description", "")
    highlights = []
    for line in desc.split('\n')[:3]:
        line = line.strip().replace('•', '').strip()
        if line and len(line) > 10 and not line.startswith('http'):
            if len(line) > 55:
                line = line[:52] + "..."
            highlights.append(line)
            if len(highlights) >= 2:
                break
    
    # Build tweet
    lines = [f"🔥 {hook}"]
    for h in highlights[:2]:
        lines.append(f"• {h}")
    lines.append(f"\n21+ | Medical card required")
    lines.append(f"More deals 👉 cannadealsfl.com")
    lines.append(f"\n{BASE_HASHTAGS} {dispo_tag}".strip())
    
    tweet = "\n".join(lines)
    
    # Truncate if needed
    if len(tweet) > 280:
        for i in range(len(lines)-1, -1, -1):
            if lines[i].startswith("•") and len(tweet) > 280:
                lines.pop(i)
                tweet = "\n".join(lines)
    
    return tweet


async def post_to_twitter(tweet_text: str, dry_run: bool = False) -> Optional[str]:
    """Post tweet and return ID."""
    if dry_run:
        print(f"\n{'='*50}")
        print("DRY RUN:")
        print(tweet_text)
        print(f"{'='*50}")
        print(f"Chars: {len(tweet_text)}/280")
        return "DRY_RUN"
    
    if not COOKIES_PATH.exists():
        logger.error("Cookies not found")
        return None
    
    with open(COOKIES_PATH) as f:
        cookies = json.load(f)
    
    client = Client('en-US')
    client.set_cookies({
        'auth_token': cookies.get('auth_token'),
        'ct0': cookies.get('ct0'),
    })
    
    try:
        result = await client.create_tweet(text=tweet_text)
        tweet_id = result.id if hasattr(result, 'id') else str(result)
        logger.info(f"Posted tweet ID: {tweet_id}")
        return str(tweet_id)
    except Exception as e:
        logger.error(f"Post failed: {e}")
        return None


async def verify_tweet(tweet_id: str) -> bool:
    """Verify tweet is actually live via user timeline."""
    if not COOKIES_PATH.exists():
        return False
    
    with open(COOKIES_PATH) as f:
        cookies = json.load(f)
    
    client = Client('en-US')
    client.set_cookies({
        'auth_token': cookies.get('auth_token'),
        'ct0': cookies.get('ct0'),
    })
    
    try:
        # Wait for tweet to propagate
        await asyncio.sleep(3)
        
        # Check user timeline for the tweet (more reliable than direct lookup)
        user = await client.get_user_by_screen_name('cannadealsfl')
        tweets = await user.get_tweets('Tweets', count=10)
        
        for t in tweets:
            if str(t.id) == tweet_id:
                logger.info(f"Verified tweet: {tweet_id}")
                return True
        
        logger.error(f"Tweet {tweet_id} not found in timeline")
        return False
        
    except Exception as e:
        logger.error(f"Verification failed: {e}")
        return False


def pick_best_deal_from_tier(deals: List[Dict], tier: int, platform: str) -> Optional[Dict]:
    """Pick best deal from specified tier."""
    candidates = []
    
    for deal in deals:
        dispo_name = deal.get("dispensary", {}).get("name", "").lower()
        deal_tier = get_tier(dispo_name)
        
        if deal_tier != tier:
            continue
        
        deal_id = deal.get("id", "")
        if check_posted(deal_id, platform):
            continue
        
        score = score_deal(deal)
        candidates.append((score, deal))
    
    if not candidates:
        return None
    
    candidates.sort(reverse=True, key=lambda x: x[0])
    return candidates[0][1]


async def main():
    if len(sys.argv) < 2:
        print("Usage: post_deal_v2.py x [--dry-run]")
        sys.exit(1)
    
    platform = sys.argv[1].lower()
    dry_run = "--dry-run" in sys.argv
    
    if platform not in ["x", "twitter"]:
        print("Unsupported platform")
        sys.exit(1)
    
    platform = "x"
    
    logger.info(f"Starting tiered posting - DryRun: {dry_run}")
    
    # Init DB
    try:
        init_db()
    except:
        pass
    
    # Fetch deals
    deals = fetch_deals()
    if not deals:
        logger.error("No deals fetched")
        sys.exit(1)
    
    # Get target tier
    target_tier = get_next_tier()
    tier_names = {1: "Tier 1 (Priority)", 2: "Tier 2 (Mid)", 3: "Tier 3 (Low)"}
    logger.info(f"Target: {tier_names.get(target_tier, 'Unknown')}")
    
    # Pick deal from tier
    deal = pick_best_deal_from_tier(deals, target_tier, platform)
    
    # Fallback: if no deal in target tier, try any tier
    if not deal:
        for tier in [1, 2, 3]:
            deal = pick_best_deal_from_tier(deals, tier, platform)
            if deal:
                logger.info(f"Fallback to {tier_names.get(tier)}")
                break
    
    if not deal:
        logger.warning("No eligible deals")
        print("No new deals to post")
        sys.exit(0)
    
    # Format and post
    dispo = deal.get("dispensary", {}).get("name", "Unknown")
    logger.info(f"Selected: {dispo} - {deal.get('title', '')[:50]}")
    
    tweet_text = format_tweet(deal)
    
    if dry_run:
        print(f"\nTier: {tier_names.get(target_tier)}")
        await post_to_twitter(tweet_text, dry_run=True)
        sys.exit(0)
    
    # Post
    tweet_id = await post_to_twitter(tweet_text)
    if not tweet_id:
        logger.error("Post failed")
        sys.exit(1)
    
    # VERIFY before recording
    print(f"Verifying tweet {tweet_id}...")
    verified = await verify_tweet(tweet_id)
    
    if not verified:
        logger.error("Verification failed — tweet not live")
        print("❌ Posted but verification failed — not recording")
        sys.exit(1)
    
    # Record only after verification
    deal_id = deal.get("id", "")
    tweet_url = f"https://twitter.com/cannadealsfl/status/{tweet_id}"
    
    record_post(
        deal_id=deal_id,
        platform=platform,
        post_id=tweet_id,
        url=tweet_url,
        deal_title=deal.get("title", ""),
        dispensary=dispo
    )
    
    logger.info(f"Posted & verified: {tweet_id}")
    print(f"\n✅ Posted & Verified!")
    print(f"Tweet ID: {tweet_id}")
    print(f"URL: {tweet_url}")


if __name__ == "__main__":
    asyncio.run(main())
