"""
Social Media Publisher Service
==============================

Business logic for creating, editing, scheduling and publishing social media posts
for the NORDA Business Chamber Facebook page.
"""

import logging
import os
from datetime import datetime
from typing import Optional, Dict, List, Tuple

from database import SessionLocal, SocialPost, SocialMediaConfig, Company, NordaEvent

logger = logging.getLogger(__name__)

# Post types supported
POST_TYPES = {
    'member_spotlight': 'Poznaj Członka NORDA',
    'event_invitation': 'Zaproszenie na Wydarzenie',
    'event_recap': 'Relacja z Wydarzenia',
    'regional_news': 'Aktualności Regionalne',
    'chamber_news': 'Aktualności Izby',
}

# AI Prompt templates for NORDA chamber posts (Polish)
AI_PROMPTS = {
    'member_spotlight': """Napisz post na Facebook dla Izby Gospodarczej NORDA Biznes, przedstawiający firmę członkowską:

Firma: {company_name}
Branża: {category}
Miasto: {city}
Opis: {description}
Strona WWW: {website}

Post powinien:
- Zaczynać się od ciepłego nagłówka typu "Poznajcie naszego członka!" lub podobnego
- Opisać czym zajmuje się firma (2-3 zdania)
- Podkreślić wartość tej firmy dla społeczności biznesowej
- Zachęcić do odwiedzenia strony firmy
- Zawierać 3-5 hashtagów (#NordaBiznes #IzbaGospodarcza #Wejherowo + branżowe)
- Być napisany ciepło, z dumą i wspierająco
- Mieć 100-200 słów
- Być po polsku

Odpowiedz WYŁĄCZNIE tekstem postu (z hashtagami na końcu).""",

    'event_invitation': """Napisz post na Facebook zapraszający na wydarzenie Izby Gospodarczej NORDA Biznes:

Wydarzenie: {event_title}
Data: {event_date}
Miejsce: {event_location}
Opis: {event_description}

Post powinien:
- Być entuzjastyczny i zachęcający do udziału
- Zawierać najważniejsze informacje (co, kiedy, gdzie)
- Wspomnieć korzyści z udziału
- Zawierać CTA (zachęta do rejestracji/kontaktu)
- Zawierać 3-5 hashtagów (#NordaBiznes #Networking #Wejherowo + tematyczne)
- Mieć 100-150 słów
- Być po polsku

Odpowiedz WYŁĄCZNIE tekstem postu.""",

    'event_recap': """Napisz post na Facebook będący relacją z wydarzenia Izby Gospodarczej NORDA Biznes:

Wydarzenie: {event_title}
Data: {event_date}
Miejsce: {event_location}
Tematy: {event_topics}
Liczba uczestników: {attendees_count}

Post powinien:
- Dziękować uczestnikom za obecność
- Podsumować najważniejsze tematy/wnioski
- Wspomnieć atmosferę i wartość spotkania
- Zachęcić do udziału w kolejnych wydarzeniach
- Zawierać 3-5 hashtagów
- Mieć 100-200 słów
- Być po polsku, relacyjny i dziękujący

Odpowiedz WYŁĄCZNIE tekstem postu.""",

    'regional_news': """Napisz post na Facebook dla Izby Gospodarczej NORDA Biznes komentujący aktualność regionalną:

Temat: {topic}
Źródło: {source}
Fakty: {facts}

Post powinien:
- Informować o temacie w kontekście biznesowym regionu
- Być informacyjny i ekspercki
- Dodać perspektywę Izby (jak to wpływa na lokalny biznes)
- Zawierać 3-5 hashtagów (#NordaBiznes #Pomorze #Wejherowo + tematyczne)
- Mieć 100-200 słów
- Być po polsku

Odpowiedz WYŁĄCZNIE tekstem postu.""",

    'chamber_news': """Napisz post na Facebook z aktualnościami Izby Gospodarczej NORDA Biznes:

Temat: {topic}
Szczegóły: {details}

Post powinien:
- Być oficjalny ale przystępny
- Przekazać najważniejsze informacje
- Zachęcić do interakcji (pytania, komentarze)
- Zawierać 3-5 hashtagów (#NordaBiznes #IzbaGospodarcza + tematyczne)
- Mieć 80-150 słów
- Być po polsku

Odpowiedz WYŁĄCZNIE tekstem postu.""",
}


class SocialPublisherService:
    """Service for managing social media posts for NORDA chamber."""

    # ---- CRUD Operations ----

    def get_posts(self, status: str = None, post_type: str = None,
                  limit: int = 50, offset: int = 0) -> List[SocialPost]:
        """Get posts with optional filters."""
        db = SessionLocal()
        try:
            query = db.query(SocialPost).order_by(SocialPost.created_at.desc())
            if status:
                query = query.filter(SocialPost.status == status)
            if post_type:
                query = query.filter(SocialPost.post_type == post_type)
            return query.offset(offset).limit(limit).all()
        finally:
            db.close()

    def get_post(self, post_id: int) -> Optional[SocialPost]:
        """Get single post by ID."""
        db = SessionLocal()
        try:
            return db.query(SocialPost).filter(SocialPost.id == post_id).first()
        finally:
            db.close()

    def create_post(self, post_type: str, content: str, user_id: int,
                    platform: str = 'facebook', hashtags: str = None,
                    company_id: int = None, event_id: int = None,
                    image_path: str = None, ai_model: str = None,
                    ai_prompt_template: str = None) -> SocialPost:
        """Create a new post draft."""
        db = SessionLocal()
        try:
            post = SocialPost(
                post_type=post_type,
                platform=platform,
                content=content,
                hashtags=hashtags,
                image_path=image_path,
                company_id=company_id,
                event_id=event_id,
                status='draft',
                ai_model=ai_model,
                ai_prompt_template=ai_prompt_template,
                created_by=user_id,
            )
            db.add(post)
            db.commit()
            db.refresh(post)
            logger.info(f"Created social post #{post.id} type={post_type}")
            return post
        except Exception as e:
            db.rollback()
            logger.error(f"Failed to create social post: {e}")
            raise
        finally:
            db.close()

    def update_post(self, post_id: int, **kwargs) -> Optional[SocialPost]:
        """Update post fields. Only draft/approved posts can be edited."""
        db = SessionLocal()
        try:
            post = db.query(SocialPost).filter(SocialPost.id == post_id).first()
            if not post:
                return None
            if post.status in ('published', 'failed'):
                logger.warning(f"Cannot edit post #{post_id} with status={post.status}")
                return None

            allowed_fields = {'content', 'hashtags', 'image_path', 'post_type',
                              'company_id', 'event_id', 'scheduled_at'}
            for key, value in kwargs.items():
                if key in allowed_fields:
                    setattr(post, key, value)

            post.updated_at = datetime.now()
            db.commit()
            db.refresh(post)
            return post
        except Exception as e:
            db.rollback()
            logger.error(f"Failed to update post #{post_id}: {e}")
            raise
        finally:
            db.close()

    def delete_post(self, post_id: int) -> bool:
        """Delete a post (only draft/approved)."""
        db = SessionLocal()
        try:
            post = db.query(SocialPost).filter(SocialPost.id == post_id).first()
            if not post:
                return False
            if post.status == 'published':
                logger.warning(f"Cannot delete published post #{post_id}")
                return False
            db.delete(post)
            db.commit()
            logger.info(f"Deleted social post #{post_id}")
            return True
        except Exception as e:
            db.rollback()
            logger.error(f"Failed to delete post #{post_id}: {e}")
            return False
        finally:
            db.close()

    # ---- Workflow ----

    def approve_post(self, post_id: int, user_id: int) -> Optional[SocialPost]:
        """Approve a draft post."""
        db = SessionLocal()
        try:
            post = db.query(SocialPost).filter(SocialPost.id == post_id).first()
            if not post or post.status != 'draft':
                return None
            post.status = 'approved'
            post.approved_by = user_id
            post.updated_at = datetime.now()
            db.commit()
            db.refresh(post)
            logger.info(f"Approved post #{post_id} by user #{user_id}")
            return post
        finally:
            db.close()

    def schedule_post(self, post_id: int, scheduled_at: datetime) -> Optional[SocialPost]:
        """Schedule an approved post for future publishing."""
        db = SessionLocal()
        try:
            post = db.query(SocialPost).filter(SocialPost.id == post_id).first()
            if not post or post.status not in ('draft', 'approved'):
                return None
            post.status = 'scheduled'
            post.scheduled_at = scheduled_at
            post.updated_at = datetime.now()
            db.commit()
            db.refresh(post)
            logger.info(f"Scheduled post #{post_id} for {scheduled_at}")
            return post
        finally:
            db.close()

    def publish_post(self, post_id: int) -> Tuple[bool, str]:
        """Publish a post to Facebook immediately.

        Returns:
            (success: bool, message: str)
        """
        db = SessionLocal()
        try:
            post = db.query(SocialPost).filter(SocialPost.id == post_id).first()
            if not post:
                return False, "Post nie znaleziony"
            if post.status not in ('draft', 'approved', 'scheduled'):
                return False, f"Nie można opublikować posta ze statusem: {post.status}"

            # Get FB config
            config = db.query(SocialMediaConfig).filter(
                SocialMediaConfig.platform == 'facebook',
                SocialMediaConfig.is_active == True
            ).first()

            if not config or not config.access_token or not config.page_id:
                return False, "Facebook nie jest skonfigurowany. Ustaw token w Ustawieniach."

            # Build message with hashtags
            message = post.content
            if post.hashtags:
                message += f"\n\n{post.hashtags}"

            # Determine if draft mode
            published = not config.debug_mode

            # Publish via Facebook Graph API
            from facebook_graph_service import FacebookGraphService
            fb = FacebookGraphService(config.access_token)

            image_path = None
            if post.image_path:
                base_dir = os.path.dirname(os.path.abspath(__file__))
                full_path = os.path.join(os.path.dirname(base_dir), post.image_path)
                if os.path.exists(full_path):
                    image_path = full_path

            result = fb.create_post(
                page_id=config.page_id,
                message=message,
                image_path=image_path,
                published=published,
            )

            if result and 'id' in result:
                post.status = 'published'
                post.published_at = datetime.now()
                post.meta_post_id = result['id']
                post.meta_response = result
                post.updated_at = datetime.now()
                db.commit()

                mode = "DRAFT (debug)" if config.debug_mode else "LIVE"
                logger.info(f"Published post #{post_id} -> FB {result['id']} ({mode})")
                return True, f"Post opublikowany ({mode}): {result['id']}"
            else:
                post.status = 'failed'
                post.meta_response = result
                post.updated_at = datetime.now()
                db.commit()
                return False, "Publikacja nie powiodła się. Sprawdź konfigurację Facebook."

        except Exception as e:
            db.rollback()
            logger.error(f"Failed to publish post #{post_id}: {e}")
            return False, f"Blad publikacji: {str(e)}"
        finally:
            db.close()

    # ---- AI Content Generation ----

    def generate_content(self, post_type: str, context: dict) -> Tuple[str, str]:
        """Generate post content using AI.

        Args:
            post_type: One of POST_TYPES keys
            context: Dict with template variables

        Returns:
            (content: str, ai_model: str)
        """
        template = AI_PROMPTS.get(post_type)
        if not template:
            raise ValueError(f"Unknown post type: {post_type}")

        # Fill template with context
        try:
            prompt = template.format(**context)
        except KeyError as e:
            raise ValueError(f"Missing context field: {e}")

        # Generate with Gemini
        from gemini_service import generate_text
        result = generate_text(prompt)

        if not result:
            raise RuntimeError("AI nie wygenerował treści. Spróbuj ponownie.")

        return result.strip(), 'gemini-3-flash'

    def get_company_context(self, company_id: int) -> dict:
        """Get company data for AI prompt context."""
        db = SessionLocal()
        try:
            company = db.query(Company).filter(Company.id == company_id).first()
            if not company:
                return {}
            return {
                'company_name': company.name or '',
                'category': company.category or '',
                'city': company.city or 'Wejherowo',
                'description': company.description or company.short_description or '',
                'website': company.website or '',
            }
        finally:
            db.close()

    def get_event_context(self, event_id: int) -> dict:
        """Get event data for AI prompt context."""
        db = SessionLocal()
        try:
            event = db.query(NordaEvent).filter(NordaEvent.id == event_id).first()
            if not event:
                return {}
            return {
                'event_title': event.title or '',
                'event_date': event.event_date.strftime('%d.%m.%Y %H:%M') if event.event_date else '',
                'event_location': event.location or '',
                'event_description': event.description or '',
            }
        finally:
            db.close()

    # ---- Facebook Config ----

    def get_fb_config(self) -> Optional[SocialMediaConfig]:
        """Get Facebook configuration."""
        db = SessionLocal()
        try:
            return db.query(SocialMediaConfig).filter(
                SocialMediaConfig.platform == 'facebook'
            ).first()
        finally:
            db.close()

    def save_fb_config(self, page_id: str, page_name: str, access_token: str,
                       debug_mode: bool, user_id: int) -> SocialMediaConfig:
        """Save/update Facebook configuration."""
        db = SessionLocal()
        try:
            config = db.query(SocialMediaConfig).filter(
                SocialMediaConfig.platform == 'facebook'
            ).first()

            if not config:
                config = SocialMediaConfig(platform='facebook')
                db.add(config)

            config.page_id = page_id
            config.page_name = page_name
            config.access_token = access_token
            config.debug_mode = debug_mode
            config.is_active = True
            config.updated_by = user_id
            config.updated_at = datetime.now()

            db.commit()
            db.refresh(config)
            logger.info(f"Saved FB config: page={page_name} debug={debug_mode}")
            return config
        except Exception as e:
            db.rollback()
            logger.error(f"Failed to save FB config: {e}")
            raise
        finally:
            db.close()

    # ---- Engagement Tracking ----

    def refresh_engagement(self, post_id: int) -> Optional[Dict]:
        """Refresh engagement metrics from Facebook for a published post."""
        db = SessionLocal()
        try:
            post = db.query(SocialPost).filter(SocialPost.id == post_id).first()
            if not post or not post.meta_post_id:
                return None

            config = db.query(SocialMediaConfig).filter(
                SocialMediaConfig.platform == 'facebook',
                SocialMediaConfig.is_active == True
            ).first()
            if not config or not config.access_token:
                return None

            from facebook_graph_service import FacebookGraphService
            fb = FacebookGraphService(config.access_token)
            engagement = fb.get_post_engagement(post.meta_post_id)

            if engagement:
                post.engagement_likes = engagement.get('likes', 0)
                post.engagement_comments = engagement.get('comments', 0)
                post.engagement_shares = engagement.get('shares', 0)
                post.engagement_reach = engagement.get('reactions_total', 0)
                post.engagement_updated_at = datetime.now()
                post.updated_at = datetime.now()
                db.commit()
                return engagement
            return None
        finally:
            db.close()

    # ---- Stats ----

    def get_stats(self) -> Dict:
        """Get summary statistics for social publisher dashboard."""
        db = SessionLocal()
        try:
            from sqlalchemy import func

            total = db.query(func.count(SocialPost.id)).scalar() or 0
            by_status = dict(
                db.query(SocialPost.status, func.count(SocialPost.id))
                .group_by(SocialPost.status).all()
            )
            by_type = dict(
                db.query(SocialPost.post_type, func.count(SocialPost.id))
                .group_by(SocialPost.post_type).all()
            )

            # Avg engagement for published posts
            avg_likes = db.query(func.avg(SocialPost.engagement_likes)).filter(
                SocialPost.status == 'published'
            ).scalar() or 0
            avg_comments = db.query(func.avg(SocialPost.engagement_comments)).filter(
                SocialPost.status == 'published'
            ).scalar() or 0

            return {
                'total': total,
                'by_status': by_status,
                'by_type': by_type,
                'avg_engagement': {
                    'likes': round(float(avg_likes), 1),
                    'comments': round(float(avg_comments), 1),
                },
            }
        finally:
            db.close()


# Singleton instance
social_publisher = SocialPublisherService()
