"""HeyReach LinkedIn outbound endpoints for Sheets add-on."""

from __future__ import annotations

import logging
from typing import Any, Dict, List, Optional

import anyio
from fastapi import APIRouter, Depends, HTTPException, Query, Security
from fastapi.security import HTTPAuthorizationCredentials
from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncSession

from ...auth_core import OrgContext, get_current_identity
from ...auth_security import api_key_hdr, http_bearer, require_account
from ...db import get_session
from ...services.secret_storage import get_saas_secret_backend
from ...services.usage_gateway import UsageGateway

from g_gremlin.heyreach import HeyReachClient, HeyReachAuthError, HeyReachError, HeyReachLinkedInAccount

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/v2/heyreach", tags=["heyreach"])


class ProfileInfo(BaseModel):
    id: str
    label: str
    connected_at: Optional[str] = None


class ProviderStatus(BaseModel):
    configured: bool


class ProfilesResponse(BaseModel):
    profiles: List[ProfileInfo]
    provider_status: ProviderStatus


class CampaignInfo(BaseModel):
    id: str
    name: str
    status: Optional[str] = None


class CampaignsRequest(BaseModel):
    profile_id: str


class CampaignsResponse(BaseModel):
    campaigns: List[CampaignInfo]


class SendersRequest(BaseModel):
    profile_id: str
    keyword: Optional[str] = None


class SenderAccount(BaseModel):
    sender_account_id: str
    email: Optional[str] = None
    name: Optional[str] = None
    status: Optional[str] = None
    is_active: Optional[bool] = None
    auth_is_valid: Optional[bool] = None
    active_campaigns: Optional[int] = None
    is_valid_navigator: Optional[bool] = None
    is_valid_recruiter: Optional[bool] = None


class SendersResponse(BaseModel):
    accounts: List[SenderAccount]


class HealthResponse(BaseModel):
    ok: bool
    status: str
    profile: Optional[Dict[str, Any]] = None
    workspace: Optional[Dict[str, Any]] = None
    message: Optional[str] = None


def _normalize_sender(account: HeyReachLinkedInAccount) -> SenderAccount:
    name_parts = [part for part in [account.first_name, account.last_name] if part]
    name = " ".join(name_parts).strip() if name_parts else None
    if not name:
        name = account.email or None
    status = None
    if account.is_active is False:
        status = "inactive"
    elif account.is_active:
        status = "active"
    if account.auth_is_valid is False:
        status = "auth_invalid" if not status or status == "active" else status
    return SenderAccount(
        sender_account_id=account.id,
        email=account.email,
        name=name,
        status=status,
        is_active=account.is_active,
        auth_is_valid=account.auth_is_valid,
        active_campaigns=account.active_campaigns,
        is_valid_navigator=account.is_valid_navigator,
        is_valid_recruiter=account.is_valid_recruiter,
    )


async def require_heyreach_context(
    bearer: Optional[HTTPAuthorizationCredentials] = Security(http_bearer),
    api_key: Optional[str] = Security(api_key_hdr),
    db: AsyncSession = Depends(get_session),
) -> OrgContext:
    account_id = await require_account(bearer=bearer, api_key=api_key, db=db)
    user_id = "api-key"
    email = None
    if bearer:
        try:
            ident = await get_current_identity(bearer)
            user_id = ident.get("user_id") or user_id
            email = ident.get("email")
        except HTTPException:
            pass
    return OrgContext(account_id=account_id, user_id=user_id, email=email)


async def require_byo_access(org: OrgContext, db: AsyncSession) -> None:
    gateway = UsageGateway(db)
    capabilities = await gateway.get_capabilities(org.account_id)
    byo = capabilities.get("byo") or {}
    if not byo.get("enabled"):
        raise HTTPException(
            status_code=403,
            detail={
                "error": "TIER_REQUIRED",
                "message": "BYO activation requires Unleashed tier or BYO add-on",
                "current_tier": capabilities.get("tier", "free"),
                "required_tier": "unleashed_or_addon",
                "upgrade_url": "/pricing",
            },
        )


async def _get_workspace_id(account_id: str, db: AsyncSession) -> Optional[str]:
    backend = get_saas_secret_backend()
    secret = await backend.get_secret(
        db=db,
        integration="heyreach",
        key="workspace_id",
        workspace_id=account_id,
    )
    if not secret or not secret.value:
        return None
    return str(secret.value).strip() or None


@router.get("/profiles", response_model=ProfilesResponse)
async def list_profiles(
    org: OrgContext = Depends(require_heyreach_context),
    db: AsyncSession = Depends(get_session),
) -> ProfilesResponse:
    await require_byo_access(org, db)

    backend = get_saas_secret_backend()
    secrets = await backend.list_secrets(db, org.account_id, integration="heyreach")
    api_secrets = [s for s in secrets if s.get("key_name") == "api_key"]

    profiles: List[ProfileInfo] = []
    for secret in api_secrets:
        label_suffix = secret.get("key_suffix") or ""
        label = "HeyReach"
        if label_suffix:
            label = f"HeyReach (****{label_suffix})"
        profiles.append(
            ProfileInfo(
                id=str(secret.get("id")),
                label=label,
                connected_at=secret.get("created_at"),
            )
        )

    logger.debug(
        "Listed HeyReach profiles",
        extra={"account_id": org.account_id, "count": len(profiles)},
    )

    return ProfilesResponse(
        profiles=profiles,
        provider_status=ProviderStatus(configured=bool(api_secrets)),
    )


@router.post("/campaigns", response_model=CampaignsResponse)
async def list_campaigns(
    request: CampaignsRequest,
    org: OrgContext = Depends(require_heyreach_context),
    db: AsyncSession = Depends(get_session),
) -> CampaignsResponse:
    await require_byo_access(org, db)

    backend = get_saas_secret_backend()
    secret = await backend.get_secret_by_id(
        db=db,
        secret_id=request.profile_id,
        workspace_id=org.account_id,
        integration="heyreach",
    )
    if not secret or not secret.value:
        logger.warning(
            "HeyReach profile not found",
            extra={"account_id": org.account_id, "profile_id": request.profile_id},
        )
        raise HTTPException(status_code=404, detail="HeyReach profile not found")

    workspace_id = await _get_workspace_id(org.account_id, db)
    logger.debug(
        "Fetching HeyReach campaigns",
        extra={"account_id": org.account_id, "profile_id": request.profile_id},
    )

    client: Optional[HeyReachClient] = None
    try:
        client = HeyReachClient(api_key=str(secret.value), workspace_id=workspace_id)
        campaigns = await anyio.to_thread.run_sync(client.list_campaigns)
        logger.info(
            "Fetched HeyReach campaigns",
            extra={"account_id": org.account_id, "count": len(campaigns)},
        )
    except HeyReachAuthError as exc:
        logger.warning("HeyReach auth error", extra={"error": str(exc)})
        raise HTTPException(status_code=401, detail=str(exc)) from exc
    except HeyReachError as exc:
        logger.error("HeyReach API error", extra={"error": str(exc)})
        raise HTTPException(status_code=502, detail=str(exc)) from exc
    finally:
        if client is not None:
            try:
                client.close()
            except Exception:
                pass

    return CampaignsResponse(
        campaigns=[
            CampaignInfo(id=c.id, name=c.name, status=c.status)
            for c in campaigns
        ]
    )


@router.post("/senders", response_model=SendersResponse)
async def list_senders(
    request: SendersRequest,
    org: OrgContext = Depends(require_heyreach_context),
    db: AsyncSession = Depends(get_session),
) -> SendersResponse:
    await require_byo_access(org, db)

    backend = get_saas_secret_backend()
    secret = await backend.get_secret_by_id(
        db=db,
        secret_id=request.profile_id,
        workspace_id=org.account_id,
        integration="heyreach",
    )
    if not secret or not secret.value:
        logger.warning(
            "HeyReach profile not found for senders",
            extra={"account_id": org.account_id, "profile_id": request.profile_id},
        )
        raise HTTPException(status_code=404, detail="HeyReach profile not found")

    workspace_id = await _get_workspace_id(org.account_id, db)
    logger.debug(
        "Fetching HeyReach sender accounts",
        extra={"account_id": org.account_id, "profile_id": request.profile_id},
    )

    client: Optional[HeyReachClient] = None
    try:
        client = HeyReachClient(api_key=str(secret.value), workspace_id=workspace_id)
        accounts = await anyio.to_thread.run_sync(
            client.list_linkedin_accounts,
            request.keyword,
        )
        logger.info(
            "Fetched HeyReach sender accounts",
            extra={"account_id": org.account_id, "count": len(accounts)},
        )
    except HeyReachAuthError as exc:
        logger.warning("HeyReach auth error for senders", extra={"error": str(exc)})
        raise HTTPException(status_code=401, detail=str(exc)) from exc
    except HeyReachError as exc:
        logger.error("HeyReach API error for senders", extra={"error": str(exc)})
        raise HTTPException(status_code=502, detail=str(exc)) from exc
    finally:
        if client is not None:
            try:
                client.close()
            except Exception:
                pass

    return SendersResponse(accounts=[_normalize_sender(account) for account in accounts])


@router.get("/health", response_model=HealthResponse)
async def health_check(
    profile_id: Optional[str] = Query(None, description="HeyReach profile ID to test"),
    org: OrgContext = Depends(require_heyreach_context),
    db: AsyncSession = Depends(get_session),
) -> HealthResponse:
    await require_byo_access(org, db)

    if not profile_id:
        raise HTTPException(status_code=400, detail="profile_id is required")

    backend = get_saas_secret_backend()
    secret = await backend.get_secret_by_id(
        db=db,
        secret_id=profile_id,
        workspace_id=org.account_id,
        integration="heyreach",
    )
    if not secret or not secret.value:
        logger.warning(
            "HeyReach profile not found for health check",
            extra={"account_id": org.account_id, "profile_id": profile_id},
        )
        raise HTTPException(status_code=404, detail="HeyReach profile not found")

    workspace_id = await _get_workspace_id(org.account_id, db)
    logger.debug(
        "Testing HeyReach connection",
        extra={"account_id": org.account_id, "profile_id": profile_id},
    )

    client: Optional[HeyReachClient] = None
    try:
        client = HeyReachClient(api_key=str(secret.value), workspace_id=workspace_id)
        data = await anyio.to_thread.run_sync(client.test_connection)
        logger.info(
            "HeyReach health check passed",
            extra={"account_id": org.account_id, "profile_id": profile_id},
        )
    except HeyReachAuthError as exc:
        logger.warning("HeyReach auth error during health check", extra={"error": str(exc)})
        raise HTTPException(status_code=401, detail=str(exc)) from exc
    except HeyReachError as exc:
        logger.error("HeyReach API error during health check", extra={"error": str(exc)})
        raise HTTPException(status_code=502, detail=str(exc)) from exc
    finally:
        if client is not None:
            try:
                client.close()
            except Exception:
                pass

    return HealthResponse(
        ok=True,
        status="ok",
        profile=data.get("profile"),
        workspace=data.get("workspace"),
    )
