"""Model to track donation banner interactions and user engagement metrics.

Canonical interaction_type values (funnel):
  - page_viewed: user viewed the support/donate page
  - banner_impression: support banner was shown (measured client-side)
  - banner_dismissed: user dismissed the banner
  - link_clicked: user clicked a support CTA (donate or key; segment by source)
  - support_modal_opened, support_donation_clicked, support_license_clicked: support modal funnel
  - support_prompt_shown, support_prompt_dismissed: soft prompt funnel

Canonical source values for CTR per placement:
  - header, banner, banner_bmc, banner_paypal, banner_key
  - dashboard_widget, donate_page_hero, donate_page_button, donate_page_key
  - about_page, help_page
Sources ending with _key are key-purchase clicks; others are donate/learn-more.
"""

from datetime import datetime, timedelta

from app import db


class DonationInteraction(db.Model):
    """Track user interactions with donation prompts"""

    __tablename__ = "donation_interactions"

    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False, index=True)

    # Interaction type: page_viewed | banner_impression | banner_dismissed | link_clicked
    interaction_type = db.Column(db.String(50), nullable=False)

    # Placement/source: header | banner | banner_bmc | banner_paypal | banner_key | dashboard_widget | donate_page_* | about_page | help_page
    source = db.Column(db.String(100), nullable=True)

    # A/B test variant for experiments (e.g. control | key_first | cta_alt)
    variant = db.Column(db.String(50), nullable=True)

    # User metrics at time of interaction (for smart prompts)
    time_entries_count = db.Column(db.Integer, nullable=True)  # Total time entries
    days_since_signup = db.Column(db.Integer, nullable=True)  # Days since user created account
    total_hours = db.Column(db.Float, nullable=True)  # Total hours tracked

    # Timestamps
    created_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)

    # Relationships
    user = db.relationship("User", backref="donation_interactions")

    def __repr__(self):
        return f"<DonationInteraction {self.interaction_type} by user {self.user_id}>"

    @staticmethod
    def record_interaction(
        user_id: int,
        interaction_type: str,
        source: str = None,
        user_metrics: dict = None,
        variant: str = None,
    ):
        """Record a donation interaction (optionally with A/B variant)."""
        interaction = DonationInteraction(
            user_id=user_id,
            interaction_type=interaction_type,
            source=source,
            variant=variant,
        )

        if user_metrics:
            interaction.time_entries_count = user_metrics.get("time_entries_count")
            interaction.days_since_signup = user_metrics.get("days_since_signup")
            interaction.total_hours = user_metrics.get("total_hours")

        db.session.add(interaction)
        db.session.commit()
        return interaction

    @staticmethod
    def has_recent_donation_click(user_id: int, days: int = 30) -> bool:
        """Check if user clicked a donation/support outbound link in last N days."""
        cutoff = datetime.utcnow() - timedelta(days=days)
        interaction_types = ("link_clicked", "banner_clicked")
        return (
            DonationInteraction.query.filter(
                DonationInteraction.user_id == user_id,
                DonationInteraction.interaction_type.in_(interaction_types),
                DonationInteraction.created_at >= cutoff,
            ).first()
            is not None
        )

    @staticmethod
    def get_user_engagement_metrics(user_id: int) -> dict:
        """Get user engagement metrics for smart prompts"""
        from app.models import TimeEntry, User

        user = User.query.get(user_id)
        if not user:
            return {}

        # Days since signup
        days_since_signup = (datetime.utcnow() - user.created_at).days if user.created_at else 0

        # Time entries count
        time_entries_count = TimeEntry.query.filter_by(user_id=user_id).count()

        # Total hours
        total_hours = user.total_hours if hasattr(user, "total_hours") else 0.0

        return {
            "days_since_signup": days_since_signup,
            "time_entries_count": time_entries_count,
            "total_hours": total_hours,
        }
