"""
Yield Domain models for Intent Routing feature.

Domains activated for yield generate passive income by routing
visitor intent to affiliate partners.
"""
from datetime import datetime
from decimal import Decimal
from typing import Optional
from sqlalchemy import String, DateTime, Float, Integer, Text, ForeignKey, Boolean, Numeric, Index
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.database import Base


class AffiliatePartner(Base):
    """
    Affiliate network/partner configuration.
    
    Partners are matched to domains based on detected intent category.
    """
    __tablename__ = "affiliate_partners"
    
    id: Mapped[int] = mapped_column(primary_key=True, index=True)
    
    # Identity
    name: Mapped[str] = mapped_column(String(100), nullable=False)  # "Comparis Dental"
    slug: Mapped[str] = mapped_column(String(50), unique=True, nullable=False)  # "comparis_dental"
    network: Mapped[str] = mapped_column(String(50), nullable=False)  # "awin", "partnerstack", "direct"
    
    # Matching criteria (JSON arrays stored as comma-separated for simplicity)
    intent_categories: Mapped[str] = mapped_column(Text, nullable=False)  # "medical_dental,medical_general"
    geo_countries: Mapped[str] = mapped_column(String(200), default="CH,DE,AT")  # ISO codes
    
    # Payout configuration
    payout_type: Mapped[str] = mapped_column(String(20), default="cpl")  # "cpc", "cpl", "cps"
    payout_amount: Mapped[Decimal] = mapped_column(Numeric(10, 2), default=0)
    payout_currency: Mapped[str] = mapped_column(String(3), default="CHF")
    
    # Integration
    tracking_url_template: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    api_endpoint: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)
    # Note: API keys should be stored encrypted or in env vars, not here
    
    # Display
    logo_url: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)
    description: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    
    # Status
    is_active: Mapped[bool] = mapped_column(Boolean, default=True)
    priority: Mapped[int] = mapped_column(Integer, default=0)  # Higher = preferred
    
    # Timestamps
    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
    updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    
    # Relationships
    yield_domains: Mapped[list["YieldDomain"]] = relationship("YieldDomain", back_populates="partner")
    
    def __repr__(self) -> str:
        return f"<AffiliatePartner {self.slug}>"
    
    @property
    def intent_list(self) -> list[str]:
        """Parse intent categories as list."""
        return [c.strip() for c in self.intent_categories.split(",") if c.strip()]
    
    @property
    def country_list(self) -> list[str]:
        """Parse geo countries as list."""
        return [c.strip() for c in self.geo_countries.split(",") if c.strip()]


class YieldDomain(Base):
    """
    Domain activated for yield/intent routing.
    
    When a user activates a domain for yield:
    1. They point DNS to our nameservers
    2. We detect the intent (e.g., "zahnarzt.ch" → medical/dental)
    3. We route traffic to affiliate partners
    4. User earns commission split
    """
    __tablename__ = "yield_domains"
    
    id: Mapped[int] = mapped_column(primary_key=True, index=True)
    user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), index=True, nullable=False)
    
    # Domain info
    domain: Mapped[str] = mapped_column(String(255), unique=True, nullable=False, index=True)
    
    # Intent detection
    detected_intent: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)  # "medical_dental"
    intent_confidence: Mapped[float] = mapped_column(Float, default=0.0)  # 0.0 - 1.0
    intent_keywords: Mapped[Optional[str]] = mapped_column(Text, nullable=True)  # JSON: ["zahnarzt", "zuerich"]
    
    # Routing
    partner_id: Mapped[Optional[int]] = mapped_column(ForeignKey("affiliate_partners.id"), nullable=True)
    active_route: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)  # Partner slug
    landing_page_url: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)

    # LLM-generated landing page config (used by routing when direct=false)
    landing_config_json: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    landing_template: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
    landing_headline: Mapped[Optional[str]] = mapped_column(String(300), nullable=True)
    landing_intro: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    landing_cta_label: Mapped[Optional[str]] = mapped_column(String(120), nullable=True)
    landing_model: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
    landing_generated_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    
    # Status
    status: Mapped[str] = mapped_column(String(30), default="pending", index=True)
    # pending, verifying, active, paused, inactive, error
    
    dns_verified: Mapped[bool] = mapped_column(Boolean, default=False)
    dns_verified_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    # "Connect" timestamp for Yield (nameserver/CNAME verified)
    connected_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    activated_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    paused_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    
    # Revenue tracking (aggregates, updated periodically)
    total_clicks: Mapped[int] = mapped_column(Integer, default=0)
    total_conversions: Mapped[int] = mapped_column(Integer, default=0)
    total_revenue: Mapped[Decimal] = mapped_column(Numeric(12, 2), default=0)
    currency: Mapped[str] = mapped_column(String(3), default="CHF")
    
    # Last activity
    last_click_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    last_conversion_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    
    # Timestamps
    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
    updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    
    # Relationships
    user: Mapped["User"] = relationship("User", back_populates="yield_domains")
    partner: Mapped[Optional["AffiliatePartner"]] = relationship("AffiliatePartner", back_populates="yield_domains")
    transactions: Mapped[list["YieldTransaction"]] = relationship(
        "YieldTransaction", back_populates="yield_domain", cascade="all, delete-orphan"
    )
    
    # Indexes
    __table_args__ = (
        Index("ix_yield_domains_user_status", "user_id", "status"),
    )
    
    def __repr__(self) -> str:
        return f"<YieldDomain {self.domain} ({self.status})>"
    
    @property
    def is_earning(self) -> bool:
        """Check if domain is actively earning."""
        return self.status == "active" and self.dns_verified
    
class YieldTransaction(Base):
    """
    Revenue events from affiliate partners.
    
    Tracks clicks, leads, and sales for each yield domain.
    """
    __tablename__ = "yield_transactions"
    
    id: Mapped[int] = mapped_column(primary_key=True, index=True)
    yield_domain_id: Mapped[int] = mapped_column(
        ForeignKey("yield_domains.id", ondelete="CASCADE"), 
        index=True, 
        nullable=False
    )
    
    # Event type
    event_type: Mapped[str] = mapped_column(String(20), nullable=False)  # "click", "lead", "sale"
    
    # Partner info
    partner_slug: Mapped[str] = mapped_column(String(50), nullable=False)
    partner_transaction_id: Mapped[Optional[str]] = mapped_column(String(200), nullable=True)
    # Our click id for attribution across systems (UUID string)
    click_id: Mapped[Optional[str]] = mapped_column(String(64), nullable=True, index=True)
    destination_url: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    
    # Amount
    gross_amount: Mapped[Decimal] = mapped_column(Numeric(10, 2), default=0)  # Full commission
    net_amount: Mapped[Decimal] = mapped_column(Numeric(10, 2), default=0)  # After Pounce cut (70%)
    currency: Mapped[str] = mapped_column(String(3), default="CHF")
    
    # Attribution
    referrer: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)
    user_agent: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)
    geo_country: Mapped[Optional[str]] = mapped_column(String(2), nullable=True)
    ip_hash: Mapped[Optional[str]] = mapped_column(String(64), nullable=True)  # Hashed for privacy
    
    # Status
    status: Mapped[str] = mapped_column(String(20), default="pending", index=True)
    # pending, confirmed, paid, rejected
    
    confirmed_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    paid_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    payout_id: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)  # FK to future payouts table
    
    # Timestamps
    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, index=True)
    
    # Relationships
    yield_domain: Mapped["YieldDomain"] = relationship("YieldDomain", back_populates="transactions")
    
    # Indexes
    __table_args__ = (
        Index("ix_yield_tx_domain_created", "yield_domain_id", "created_at"),
        Index("ix_yield_tx_status_created", "status", "created_at"),
        Index("ix_yield_tx_click_id", "click_id"),
    )
    
    def __repr__(self) -> str:
        return f"<YieldTransaction {self.event_type} {self.net_amount} {self.currency}>"


class YieldPayout(Base):
    """
    Payout records for user earnings.
    
    Aggregates confirmed transactions into periodic payouts.
    """
    __tablename__ = "yield_payouts"
    
    id: Mapped[int] = mapped_column(primary_key=True, index=True)
    user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), index=True, nullable=False)
    
    # Amount
    amount: Mapped[Decimal] = mapped_column(Numeric(12, 2), nullable=False)
    currency: Mapped[str] = mapped_column(String(3), default="CHF")
    
    # Period
    period_start: Mapped[datetime] = mapped_column(DateTime, nullable=False)
    period_end: Mapped[datetime] = mapped_column(DateTime, nullable=False)
    
    # Transaction count
    transaction_count: Mapped[int] = mapped_column(Integer, default=0)
    
    # Status
    status: Mapped[str] = mapped_column(String(20), default="pending", index=True)
    # pending, processing, completed, failed
    
    # Payment details
    payment_method: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)  # "stripe", "bank"
    payment_reference: Mapped[Optional[str]] = mapped_column(String(200), nullable=True)
    
    # Timestamps
    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
    processed_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    completed_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    
    # Relationship
    user: Mapped["User"] = relationship("User", back_populates="yield_payouts")
    
    def __repr__(self) -> str:
        return f"<YieldPayout {self.amount} {self.currency} ({self.status})>"

