class GmailClient:
    """Authenticated Gmail client for one account (API or XOAUTH2 SMTP)."""

    def __init__(self, account_email: str, access_token: str, refresh_token: str,
                 client_config: dict, sending_method: str = "api", token_expiry=None):
        self.account_email = account_email
        self.client_config = client_config
        self.method = sending_method if sending_method in ("api", "smtp") else "api"
        creds = gcred.Credentials(
            token=access_token,
            refresh_token=refresh_token or None,
            token_uri=GOOGLE_TOKEN_URL,
            client_id=client_config["client_id"],
            client_secret=client_config["client_secret"],
            scopes=GMAIL_SCOPES,
        )
        self._creds = creds
        self._service = None
        self.token_expiry = token_expiry

    def _ensure_valid(self):
        request = google.auth.transport.requests.Request()
        if not self._creds.valid:
            self._creds.refresh(request)
        return self._creds.token

    def _api(self):
        if self._service is None:
            self._ensure_valid()
            self._service = build("gmail", "v1", credentials=self._creds, cache_discovery=False)
        else:
            self._ensure_valid()
        return self._service

    # -- API send ------------------------------------------------------------
    def send_mime_api(self, mime_message) -> dict:
        """Send via Gmail API users.messages.send. Returns real provider response."""
        service = self._api()
        raw = base64.urlsafe_b64encode(mime_message.as_bytes()).decode()
        body = {"raw": raw}
        sent = service.users().messages().send(userId="me", body=body).execute()
        return {"ok": True, "message_id": sent.get("id", ""), "thread_id": sent.get("threadId", ""),
                "label_ids": sent.get("labelIds", []), "raw_response": sent}

    # -- SMTP send (XOAUTH2, no password) -------------------------------------
    def send_mime_smtp(self, mime_message) -> dict:
        import smtplib
        from email.utils import parseaddr
        self._ensure_valid()
        access_token = self._creds.token
        auth_string = f"user={self.account_email}\x01auth=Bearer {access_token}\x01\x01"
        with smtplib.SMTP("smtp.gmail.com", 587, timeout=30) as smtp:
            smtp.ehlo()
            smtp.starttls(context=__import__("ssl").create_default_context())
            smtp.ehlo()
            code, response = smtp.docmd("AUTH", "XOAUTH2 " + base64.b64encode(auth_string.encode()).decode())
            refused = smtp.sendmail(self.account_email, [parseaddr(mime_message["To"])[1]], mime_message.as_bytes())
        if refused:
            return {"ok": False, "error": f"SMTP refused recipients: {refused}", "error_class": "permanent"}
        return {"ok": True, "message_id": "", "thread_id": "", "raw_response": f"250 SMTP accepted ({code} {response.decode(errors='replace')})"}

    # -- Health / profile ------------------------------------------------------
    def get_profile(self) -> dict:
        service = self._api()
        prof = service.users().getProfile(userId="me").execute()
        return {"email_address": prof.get("emailAddress"), "history_id": prof.get("historyId"),
                "messages_total": prof.get("messagesTotal"), "threads_total": prof.get("threadsTotal")}

    def verify_connection(self) -> dict:
        try:
            prof = self.get_profile()
            return {"ok": True, "email_address": prof.get("email_address"), "detail": "Gmail API connection verified."}
        except Exception as e:
            return {"ok": False, "detail": str(e)[:400]}


def build_gmail_client_from_account(account, oauth_token, client_config=None) -> GmailClient:
    """Build a GmailClient from DB rows (sync session context - worker uses sync ORM)."""
    cfg = client_config or resolve_client_config_for_account(account)
    return GmailClient(
        account_email=account.email,
        access_token=oauth_token.access_token,       # decrypted
        refresh_token=oauth_token.refresh_token,     # decrypted
        client_config=cfg,
        sending_method=account.sending_method,
        token_expiry=oauth_token.expires_at,
    )


def resolve_client_config_for_account(account) -> dict:
    """Resolve client config for an account: its imported config row or server default."""
    # Called from sync or async context; imports DB lazily.
    from app.db.session import SyncSession
    from app.models import OAuthClientConfig
    if account.oauth_config_id:
        with SyncSession() as s:
            cfg = s.get(OAuthClientConfig, account.oauth_config_id)
            if cfg and cfg.is_active:
