from copy import deepcopy
import re

from urllib.parse import urlencode

from sqlalchemy.orm import Session

from app.automation.tasks.login import HudlCredentials, canonical_hudl_login_url
from app.core.config import (
    HUDL_EMAIL,
    HUDL_LOGIN_URL,
    HUDL_PASSWORD,
    get_frontend_base_url,
)
from app.core.credential_crypto import decrypt_secret, encrypt_secret
from app.core.database import SessionLocal
from app.core.security import create_token_pair
from app.models.account_model import Account

DEFAULT_HUDL_LOGIN_URL = canonical_hudl_login_url(
    HUDL_LOGIN_URL or "https://identity.hudl.com/u/login/identifier"
)

def _encrypt_metadata(metadata: dict | None) -> dict | None:
    if not metadata:
        return None
    stored = deepcopy(metadata)
    if stored.get("imap_password"):
        stored["imap_password"] = encrypt_secret(stored["imap_password"])
    return stored


def _public_metadata(metadata: dict | None) -> dict | None:
    if not metadata:
        return None
    public = deepcopy(metadata)
    if "imap_password" in public:
        public["imap_password"] = "********"
    return public


def account_id_from_email(email: str) -> str:
    """Stable slug from Hudl email (matches frontend Settings behavior)."""
    slug = email.strip().lower().replace("@", "-at-")
    slug = re.sub(r"[^a-z0-9-]", "-", slug)
    slug = re.sub(r"-+", "-", slug).strip("-")
    return (slug or "hudl-account")[:100]


def resolve_account_fields(
    hudl_email: str,
    account_id: str | None = None,
    name: str | None = None,
) -> tuple[str, str]:
    email = hudl_email.strip()
    resolved_id = (account_id or account_id_from_email(email)).strip()
    resolved_name = (name or email).strip()
    return resolved_id, resolved_name


def get_account_by_account_id(db: Session, account_id: str) -> Account | None:
    return db.query(Account).filter(Account.account_id == account_id).first()


def get_account_by_hudl_email(db: Session, hudl_email: str) -> Account | None:
    return (
        db.query(Account)
        .filter(Account.hudl_email == hudl_email.strip())
        .first()
    )


def authenticate_account(db: Session, email: str, password: str) -> Account | None:
    """Authenticate against accounts table using hudl_email and stored password."""
    account = get_account_by_hudl_email(db, email)
    if not account or not account.is_active:
        return None

    try:
        stored_password = decrypt_secret(account.hudl_password_enc)
    except ValueError:
        return None

    if stored_password != password:
        return None

    return account


def account_auth_payload(account: Account) -> dict:
    name_parts = account.name.split(" ") if account.name else []
    first_name = name_parts[0] if name_parts else ""
    last_name = " ".join(name_parts[1:]) if len(name_parts) > 1 else ""

    return {
        "id": str(account.id),
        "email": account.hudl_email,
        "name": account.name or "",
        "firstName": first_name,
        "lastName": last_name,
        "bio": "",
        "role": "ACCOUNT",
        "account_id": account.account_id,
        "auth_type": "account",
    }


def get_active_account(db: Session) -> Account | None:
    return (
        db.query(Account)
        .filter(Account.is_active.is_(True))
        .order_by(Account.updated_at.desc())
        .first()
    )


def load_active_credentials() -> HudlCredentials:
    db = SessionLocal()
    try:
        account = get_active_account(db)
        if account:
            password = decrypt_secret(account.hudl_password_enc)
            return HudlCredentials(
                email=account.hudl_email,
                password=password,
                login_url=account.hudl_login_url,
            )
    finally:
        db.close()

    if HUDL_EMAIL and HUDL_PASSWORD and DEFAULT_HUDL_LOGIN_URL:
        return HudlCredentials(
            email=HUDL_EMAIL,
            password=HUDL_PASSWORD,
            login_url=DEFAULT_HUDL_LOGIN_URL,
        )

    raise ValueError(
        "No Hudl credentials configured. "
        "Ingest an account via POST /api/v1/accounts or set HUDL_* in .env"
    )


def create_account(
    db: Session,
    *,
    account_id: str,
    name: str,
    hudl_email: str,
    hudl_password: str,
    hudl_login_url: str,
    metadata: dict | None = None,
) -> Account:
    """Create a new account and mark it as the active one."""
    login_url = canonical_hudl_login_url(hudl_login_url)
    encrypted_metadata = _encrypt_metadata(metadata)

    db.query(Account).filter(Account.is_active.is_(True)).update(
        {"is_active": False},
        synchronize_session=False,
    )

    account = Account(
        account_id=account_id,
        name=name,
        hudl_email=hudl_email,
        hudl_password_enc=encrypt_secret(hudl_password),
        hudl_login_url=login_url,
        metadata_json=encrypted_metadata,
        is_active=True,
    )
    db.add(account)
    db.commit()
    db.refresh(account)
    return account


def upsert_account(
    db: Session,
    *,
    account_id: str,
    name: str,
    hudl_email: str,
    hudl_password: str,
    hudl_login_url: str,
    metadata: dict | None = None,
) -> Account:
    """
    Create or update an account by account_id and mark it active.
    """
    existing = get_account_by_account_id(db, account_id)
    if not existing:
        return create_account(
            db,
            account_id=account_id,
            name=name,
            hudl_email=hudl_email,
            hudl_password=hudl_password,
            hudl_login_url=hudl_login_url,
            metadata=metadata,
        )

    login_url = canonical_hudl_login_url(hudl_login_url)
    encrypted_metadata = _encrypt_metadata(metadata)

    db.query(Account).filter(
        Account.is_active.is_(True),
        Account.id != existing.id,
    ).update(
        {"is_active": False},
        synchronize_session=False,
    )

    existing.account_id = account_id
    existing.name = name
    existing.hudl_email = hudl_email
    existing.hudl_password_enc = encrypt_secret(hudl_password)
    existing.hudl_login_url = login_url
    existing.metadata_json = encrypted_metadata
    existing.is_active = True

    db.add(existing)
    db.commit()
    db.refresh(existing)
    return existing


def to_account_response(account: Account) -> dict:
    return {
        "id": account.id,
        "account_id": account.account_id,
        "name": account.name,
        "Handshake_email": account.hudl_email,
        "metadata": _public_metadata(account.metadata_json),
    }


def _account_token_data(account: Account) -> dict:
    return {
        "account_id": account.id,
        "email": account.hudl_email,
        "auth_type": "account",
    }


def build_frontend_access_url(
    access_token: str,
    email: str,
    refresh_token: str = "",
    request_host: str | None = None,
) -> str:
    base_url = get_frontend_base_url(request_host)
    if not base_url:
        return ""
    params = {
        "token": access_token,
        "email": email,
        "redirect": "/admin/exchange",
    }
    if refresh_token:
        params["refresh_token"] = refresh_token
    return f"{base_url}/auth/access?{urlencode(params)}"


def to_account_ingest_response(
    account: Account,
    verification: dict,
    request_host: str | None = None,
) -> dict:
    tokens = create_token_pair(_account_token_data(account))
    access_token = tokens["access"]["token"]
    refresh_token = tokens["refresh"]["token"]
    return {
        **to_account_response(account),
        "verification": verification,
        "tokens": tokens,
        "frontend_url": build_frontend_access_url(
            access_token,
            account.hudl_email,
            refresh_token=refresh_token,
            request_host=request_host,
        ),
    }
