"""
CNP Solutions — software license keys for cloud and on-premise deployments.
"""
import uuid
from sqlalchemy import Column, String, Boolean, Integer, DateTime, Text, ForeignKey, Index
from sqlalchemy.orm import relationship
from app.models.base import BaseModel


class LicenseKey(BaseModel):
    """
    Purchase token issued by CNP Solutions. One key typically activates one company
  on one deployment (cloud tenant or local node).
    """
    __tablename__ = "license_keys"

    id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))

    # Display prefix e.g. CNP-STND-2026-**** (last segment hidden in UI)
    key_prefix = Column(String(32), nullable=False, index=True)
    key_hash = Column(String(64), nullable=False, unique=True, index=True)
    # Encrypted full key — platform admin can reveal for customer reinstalls
    key_encrypted = Column(Text, nullable=True)

    plan = Column(String(50), default="standard")  # standard | professional | enterprise
    deployment_mode = Column(String(20), default="both")  # cloud | local | both

    status = Column(String(20), default="pending", index=True)
    # pending | active | expired | revoked | suspended

    valid_from = Column(DateTime, nullable=False)
    valid_until = Column(DateTime, nullable=False)

    max_users = Column(Integer, default=25)
    max_branches = Column(Integer, default=10)
    grace_days = Column(Integer, default=7)

    # Set when activated during company setup
    company_id = Column(String, ForeignKey("companies.id"), nullable=True, index=True)
    activated_at = Column(DateTime, nullable=True)
    activated_by_email = Column(String(255), nullable=True)

    customer_name = Column(String(255), nullable=True)
    customer_email = Column(String(255), nullable=True)
    notes = Column(Text, nullable=True)

    renewals_count = Column(Integer, default=0)

    nodes = relationship("DeploymentNode", back_populates="license_key", lazy="select")
    branch_licenses = relationship(
        "BranchLicense",
        back_populates="parent_license",
        foreign_keys="BranchLicense.parent_license_id",
        lazy="select",
    )


class BranchLicense(BaseModel):
    """
    Additional branch entitlement tied to a main LicenseKey.
    Expires when the parent main license expires; renewed/revoked with the parent.
    Each active slot allows one extra branch beyond head office (included in main).
    """
    __tablename__ = "branch_licenses"

    id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
    parent_license_id = Column(String, ForeignKey("license_keys.id"), nullable=False, index=True)
    company_id = Column(String, ForeignKey("companies.id"), nullable=False, index=True)
    branch_id = Column(String, ForeignKey("branches.id"), nullable=True, index=True)

    slot_code = Column(String(32), nullable=False, index=True)
    label = Column(String(255), nullable=True)
    status = Column(String(20), default="active", index=True)  # active | revoked

    valid_from = Column(DateTime, nullable=False)
    valid_until = Column(DateTime, nullable=False)
    notes = Column(Text, nullable=True)

    parent_license = relationship(
        "LicenseKey",
        back_populates="branch_licenses",
        foreign_keys=[parent_license_id],
    )
    company = relationship("Company", back_populates="branch_licenses")
    branch = relationship("Branch", foreign_keys=[branch_id])


class DeploymentNode(BaseModel):
    """
    Registered local/on-prem server that phones home to the cloud license hub.
    Enables hybrid access (local ERP reachable via cloud relay when configured).
    """
    __tablename__ = "deployment_nodes"

    id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
    license_key_id = Column(String, ForeignKey("license_keys.id"), nullable=False, index=True)
    company_id = Column(String, ForeignKey("companies.id"), nullable=True, index=True)

    node_name = Column(String(255), nullable=False)
    deployment_type = Column(String(20), default="local")  # local | cloud
    public_base_url = Column(String(500), nullable=True)  # e.g. https://client.example.com:8010
    sync_token_hash = Column(String(64), nullable=True)  # bearer for node API calls

    is_active = Column(Boolean, default=True)
    last_heartbeat_at = Column(DateTime, nullable=True)
    last_ip = Column(String(64), nullable=True)
    app_version = Column(String(50), nullable=True)
    machine_fingerprint = Column(String(128), nullable=True)

    # Cloud sync (LAN → hub)
    sync_requested_at = Column(DateTime, nullable=True)
    last_sync_at = Column(DateTime, nullable=True)
    last_sync_status = Column(String(32), nullable=True)  # ok | partial | failed
    last_sync_error = Column(Text, nullable=True)
    last_sync_events_count = Column(Integer, default=0)
    realtime_sync_enabled = Column(Boolean, default=True)

    license_key = relationship("LicenseKey", back_populates="nodes")
    company = relationship("Company", back_populates="deployment_nodes")

    __table_args__ = (
        Index("ix_deployment_nodes_company_active", "company_id", "is_active"),
    )
