from typing import Dict, List, Any
import os
from datetime import datetime
from .guidelines_parser import GuidelinesParser
from .image_analyzer import ImageAnalyzer
from .video_analyzer import VideoAnalyzer, is_video_file

# Try to import advanced NLP matcher, fallback to simple one
try:
    from .nlp_matcher import NLPMatcher
    print("✅ Using advanced NLP matcher with semantic analysis")
    USE_ADVANCED_NLP = True
except ImportError as e:
    print(f"⚠️  Advanced NLP not available: {e}")
    print("   Falling back to simple pattern-based matching")
    from .simple_nlp_matcher import SimpleNLPMatcher as NLPMatcher
    USE_ADVANCED_NLP = False

class ContentEvaluator:
    def __init__(self, guidelines_path: str):
        print("🚀 Initializing Content Evaluator...")
        print("   Loading guidelines parser...")
        self.guidelines_parser = GuidelinesParser(guidelines_path)
        print("   Loading image analyzer...")
        self.image_analyzer = ImageAnalyzer()
        print("   Loading video analyzer...")
        self.video_analyzer = VideoAnalyzer()
        print(f"   Loading NLP matcher ({'Advanced' if USE_ADVANCED_NLP else 'Simple'})...")
        self.nlp_matcher = NLPMatcher()
        print("   ✅ Content evaluator ready!")

    def evaluate_image(self, image_path: str) -> Dict[str, Any]:
        print(f"\n🔍 Evaluating: {os.path.basename(image_path)}")

        # Analyze image content
        print("📸 Step 1: Image analysis...")
        image_analysis = self.image_analyzer.analyze_image(image_path)

        if "error" in image_analysis:
            print(f"   ❌ Image analysis failed")
            return {
                "approved": False,
                "reason": f"Image analysis failed: {image_analysis['error']}",
                "link": os.path.abspath(image_path),
                "timestamp": datetime.now().isoformat(),
                "analysis": image_analysis
            }

        # Extract text content for NLP analysis
        text_content = image_analysis.get("extracted_text", {}).get("text", "")
        print(f"📝 Step 2: Text content - {len(text_content)} characters")

        if not text_content or len(text_content.strip()) < 3:
            print("   ⚠️  Insufficient text for evaluation")
            return {
                "approved": False,
                "reason": "No readable text found in image for guideline evaluation",
                "link": os.path.abspath(image_path),
                "timestamp": datetime.now().isoformat(),
                "analysis": image_analysis
            }

        # Perform NLP analysis against guidelines
        print("🧠 Step 3: NLP analysis...")
        approval_rules = self.guidelines_parser.get_approval_rules()
        rejection_rules = self.guidelines_parser.get_rejection_rules()

        nlp_results = self.nlp_matcher.analyze_content(
            text_content, approval_rules, rejection_rules
        )

        print("⚖️  Step 4: Final decision making...")
        # Combine results
        final_approval = self._make_final_decision(image_analysis, nlp_results)

        result = {
            "approved": final_approval["approved"],
            "reason": final_approval["reason"],
            "link": os.path.abspath(image_path),
            "timestamp": datetime.now().isoformat(),
            "confidence": final_approval.get("confidence", 0.0),
            "text_extracted": text_content,
            "word_count": len(text_content.split()),
            "guideline_matches": [
                {
                    "category": match.rule_category,
                    "type": match.rule_type,
                    "confidence": match.confidence,
                    "reasoning": match.reasoning
                }
                for match in nlp_results["matches"]
            ],
            "scores": {
                "approval_score": nlp_results["approval_score"],
                "rejection_score": nlp_results["rejection_score"],
                "net_score": nlp_results["net_score"]
            },
            "image_quality": {
                "has_text": image_analysis["extracted_text"]["has_text"],
                "text_confidence": image_analysis["extracted_text"]["confidence"],
                "is_high_quality": image_analysis["quality_metrics"]["is_high_quality"]
            }
        }

        status = "✅ APPROVED" if result["approved"] else "❌ REJECTED"
        print(f"🎯 Final Result: {status} (confidence: {result['confidence']:.2f})")
        return result

    def _make_final_decision(self, image_analysis: Dict, nlp_results: Dict) -> Dict[str, Any]:
        print("   Checking text reliability...")
        # Check if text extraction was reliable
        text_info = image_analysis.get("extracted_text", {})
        text_confidence = text_info.get("confidence", 0)

        if text_confidence < 30:
            print(f"   ❌ Low OCR confidence: {text_confidence:.1f}%")
            return {
                "approved": False,
                "reason": "Text in image is too unclear for reliable guideline evaluation (low OCR confidence)",
                "confidence": 0.2
            }

        print("   Checking image quality...")
        # Check image quality - but don't make it a hard blocker
        quality_info = image_analysis.get("quality_metrics", {})
        quality_penalty = 0.0
        if not quality_info.get("is_high_quality", False):
            print("   ⚠️  Lower image quality detected - adding penalty but not blocking")
            quality_penalty = 0.2  # Small penalty instead of hard rejection

        print("   Applying NLP decision logic...")
        # Use NLP results for final decision
        approved = nlp_results["approved"]
        net_score = nlp_results["net_score"]
        rejection_score = nlp_results["rejection_score"]

        # High rejection score = definite rejection
        if rejection_score > 0.8:
            print(f"   ❌ High rejection score: {rejection_score:.2f}")
            return {
                "approved": False,
                "reason": nlp_results["reasoning"],
                "confidence": min(rejection_score, 0.95)
            }

        # Strong positive score = approval
        if approved and net_score > 0.5:
            print(f"   ✅ Strong approval score: {net_score:.2f}")
            final_confidence = min(net_score - quality_penalty, 0.9)
            return {
                "approved": True,
                "reason": nlp_results["reasoning"],
                "confidence": max(final_confidence, 0.3)
            }

        # Borderline cases
        if net_score > -0.2 and rejection_score < 0.5:
            print(f"   ⚡ Borderline approval: {net_score:.2f}")
            final_confidence = max(0.6 - quality_penalty, 0.3)
            return {
                "approved": True,
                "reason": f"Borderline approval - {nlp_results['reasoning']}",
                "confidence": final_confidence
            }
        else:
            print(f"   ❌ Does not meet guidelines: {net_score:.2f}")
            return {
                "approved": False,
                "reason": f"Does not meet brand guidelines - {nlp_results['reasoning']}",
                "confidence": 0.7
            }

    def evaluate_video(self, video_path: str) -> Dict[str, Any]:
        """Evaluate video by extracting and analyzing key frames"""
        print(f"\n🎬 Evaluating video: {os.path.basename(video_path)}")

        # Check if file is a video
        if not is_video_file(video_path):
            return {
                "error": "Not a supported video format",
                "approved": False,
                "reason": "File is not a supported video format"
            }

        try:
            # Analyze video and extract frames
            video_analysis = self.video_analyzer.analyze_video(video_path)

            if "error" in video_analysis:
                return {
                    "error": video_analysis["error"],
                    "approved": False,
                    "reason": f"Video analysis failed: {video_analysis['error']}"
                }

            frames_data = video_analysis.get("extracted_frames", [])
            if not frames_data:
                return {
                    "approved": False,
                    "reason": "No frames could be extracted from video",
                    "confidence": 0.1
                }

            print(f"   🖼️  Analyzing {len(frames_data)} extracted frames...")

            # Select best frames for analysis
            best_frames = self.video_analyzer.get_best_frames(frames_data, max_frames=5)
            print(f"   🎯 Selected {len(best_frames)} best quality frames")

            # Analyze each selected frame
            frame_results = []
            combined_text = []

            for i, frame_data in enumerate(best_frames, 1):
                print(f"   🔍 Analyzing frame {i}/{len(best_frames)} (t={frame_data['timestamp']:.1f}s)")

                frame_path = frame_data["path"]
                if not os.path.exists(frame_path):
                    print(f"     ⚠️  Frame file missing: {frame_path}")
                    continue

                # Analyze frame as an image
                frame_evaluation = self.evaluate_image(frame_path)

                if frame_evaluation and not frame_evaluation.get("error"):
                    frame_results.append({
                        "timestamp": frame_data["timestamp"],
                        "frame_number": frame_data["frame_number"],
                        "evaluation": frame_evaluation,
                        "quality_score": frame_data.get("quality_score", 0)
                    })

                    # Collect text for combined analysis
                    if frame_evaluation.get("text_extracted"):
                        combined_text.append(frame_evaluation["text_extracted"])

            if not frame_results:
                return {
                    "approved": False,
                    "reason": "No frames could be successfully analyzed",
                    "confidence": 0.2
                }

            # Determine overall video approval based on frames
            approved_frames = sum(1 for result in frame_results if result["evaluation"].get("approved", False))
            total_frames = len(frame_results)
            approval_rate = approved_frames / total_frames if total_frames > 0 else 0

            # Video is approved if majority of key frames are approved
            overall_approved = approval_rate >= 0.6  # At least 60% of frames approved

            # Calculate weighted confidence based on frame quality and approval
            confidence_scores = [
                result["evaluation"].get("confidence", 0) * (1 + result.get("quality_score", 0) / 1000)
                for result in frame_results
            ]
            avg_confidence = sum(confidence_scores) / len(confidence_scores) if confidence_scores else 0

            # Determine reason
            if overall_approved:
                reason = f"Video content approved - {approved_frames}/{total_frames} key frames meet guidelines"
            else:
                reason = f"Video content does not meet guidelines - only {approved_frames}/{total_frames} key frames approved"

            # Add video-specific information
            result = {
                "approved": overall_approved,
                "reason": reason,
                "confidence": min(avg_confidence, 0.95),
                "video_analysis": {
                    "duration_seconds": video_analysis.get("duration_seconds", 0),
                    "frames_analyzed": len(frame_results),
                    "frames_approved": approved_frames,
                    "approval_rate": approval_rate,
                    "combined_text": " ".join(combined_text) if combined_text else "",
                    "word_count": len(" ".join(combined_text).split()) if combined_text else 0
                },
                "frame_results": frame_results,
                "link": video_path,
                "media_type": "video"
            }

            print(f"   🎬 Video evaluation complete: {'✅ APPROVED' if overall_approved else '❌ REJECTED'} ({approval_rate:.1%} frame approval)")
            return result

        except Exception as e:
            print(f"   ❌ Video evaluation failed: {str(e)}")
            return {
                "error": f"Video evaluation failed: {str(e)}",
                "approved": False,
                "reason": f"Technical error during video analysis: {str(e)}"
            }

    def evaluate_directory(self, directory_path: str) -> List[Dict[str, Any]]:
        print(f"\n📁 Evaluating directory: {directory_path}")
        results = []

        if not os.path.exists(directory_path):
            print("   ❌ Directory not found")
            return [{"error": f"Directory not found: {directory_path}"}]

        # Get all image files
        print("   Scanning for image files...")
        image_files = []
        for filename in os.listdir(directory_path):
            file_path = os.path.join(directory_path, filename)
            if os.path.isfile(file_path):
                _, ext = os.path.splitext(filename.lower())
                if ext in ['.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.webp']:
                    image_files.append(file_path)

        print(f"   Found {len(image_files)} image files")

        if not image_files:
            print("   ❌ No supported images found")
            return [{"error": "No supported image files found in directory"}]

        # Evaluate each image
        for i, image_path in enumerate(image_files, 1):
            print(f"\n📊 Processing {i}/{len(image_files)}: {os.path.basename(image_path)}")
            try:
                result = self.evaluate_image(image_path)
                results.append(result)
            except Exception as e:
                print(f"   ❌ Evaluation failed: {str(e)}")
                results.append({
                    "approved": False,
                    "reason": f"Evaluation failed: {str(e)}",
                    "link": os.path.abspath(image_path),
                    "timestamp": datetime.now().isoformat(),
                    "error": str(e)
                })

        print(f"\n✅ Directory evaluation complete - {len(results)} results")
        return results

    def generate_summary(self, results: List[Dict[str, Any]]) -> Dict[str, Any]:
        print("📊 Generating summary...")
        if not results:
            return {"error": "No results to summarize"}

        total_images = len(results)
        approved_count = sum(1 for r in results if r.get("approved", False))
        rejected_count = total_images - approved_count

        # Categorize rejection reasons
        rejection_reasons = {}
        for result in results:
            if not result.get("approved", False):
                reason = result.get("reason", "Unknown")
                category = self._categorize_rejection_reason(reason)
                rejection_reasons[category] = rejection_reasons.get(category, 0) + 1

        summary = {
            "total_images": total_images,
            "approved": approved_count,
            "rejected": rejected_count,
            "approval_rate": approved_count / total_images if total_images > 0 else 0,
            "rejection_categories": rejection_reasons,
            "timestamp": datetime.now().isoformat()
        }

        print(f"   📈 Summary: {approved_count}/{total_images} approved ({summary['approval_rate']:.1%})")
        return summary

    def _categorize_rejection_reason(self, reason: str) -> str:
        reason_lower = reason.lower()

        if "text" in reason_lower and ("unclear" in reason_lower or "confidence" in reason_lower):
            return "Poor Text Quality"
        elif "quality" in reason_lower and ("poor" in reason_lower or "low" in reason_lower):
            return "Poor Image Quality"
        elif "guideline" in reason_lower or "brand" in reason_lower:
            return "Brand Guideline Violations"
        elif "ai-first" in reason_lower or "tech" in reason_lower:
            return "AI-First Messaging"
        elif "replace" in reason_lower or "replacement" in reason_lower:
            return "Artist Replacement Language"
        else:
            return "Other Issues"