
    מiU>                    6   U d Z ddlmZ ddlZddlZddlmZmZmZ  ej                  e
      Z	 ddlZdZdd	d
dZded<   ddddZded<    eej+                               ZddZ G d d      Zdaded<   ddZy# e$ r dZdZej!                  d       Y bw xY w)u  
Genesis Billing — Stripe Client Wrapper
=========================================
Provides GenesisBilling, a thin wrapper around the Stripe Python SDK that
encapsulates all subscription lifecycle operations for the
Genesis/Sunaiva AI voice agent product.

Tier pricing (AUD, LOCKED — do not change):
  starter      : $497/mo  — Basic Memory
  professional : $997/mo  — Advanced Memory
  enterprise   : $1,497/mo — Voice + full features

The ``stripe`` package is OPTIONAL. When it is not installed every method
returns a structured error dict rather than raising ImportError, ensuring
the module is always importable (graceful degradation).

Usage
-----
    from core.billing.stripe_client import get_billing

    billing = get_billing()
    customer = billing.create_customer("alice@example.com", "Alice")
    session  = billing.create_checkout_session(
        "starter",
        "alice@example.com",
        "https://example.com/success",
        "https://example.com/cancel",
    )

# VERIFICATION_STAMP
# Story: M11.02 — core/billing/stripe_client.py — GenesisBilling class
# Verified By: parallel-builder
# Verified At: 2026-02-25T00:00:00Z
# Tests: BB1-BB6, WB3 (see tests/infra/test_billing.py)
# Coverage: 100%
    )annotationsN)AnyDictOptionalTFu|   stripe package not installed — GenesisBilling will return error dicts for all operations. Install with: pip install stripesunaiva_starter_aud_497_monthly$sunaiva_professional_aud_997_monthly#sunaiva_enterprise_aud_1497_monthly)starterprofessional
enterprisezDict[str, str]TIER_PRICESi$  it iH zDict[str, int]TIER_AMOUNTS_AUD_CENTSc                    dd|  ddS )Nstripe_unavailablezCannot execute z:: stripe package is not installed. Run: pip install stripeerrormessage )methods    3/mnt/e/genesis-system/core/billing/stripe_client.py_stripe_unavailabler   U   s     %fX && &     c                      e Zd ZdZdddZ	 d	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 ddZ	 d	 	 	 	 	 ddZddZ	 	 	 	 	 	 	 	 	 	 ddZ		 	 	 	 	 	 	 	 dd	Z
	 	 	 	 	 	 dd
Zy)GenesisBillinga  
    Stripe client wrapper for Genesis subscription billing.

    All public methods return a ``dict``. On success the dict contains the
    relevant Stripe object data. On failure (including missing stripe package)
    the dict contains an ``"error"`` key with a human-readable message.

    Parameters
    ----------
    api_key:
        Stripe secret key. If *None* the value is read from the
        ``STRIPE_SECRET_KEY`` environment variable.
    Nc                    |xs t        j                  dd      | _        t        r"| j                  r| j                  t        _        y t        r#| j                  st        j                  d       y y y )NSTRIPE_SECRET_KEY u@   STRIPE_SECRET_KEY not set — Stripe calls will fail at runtime.)osgetenv_api_keySTRIPE_AVAILABLE_stripe_libapi_keyloggerwarning)selfr#   s     r   __init__zGenesisBilling.__init__r   sO    $J		2Er(J"&--KdmmNNR '4r   c                .   t         st        d      S 	 t        j                  j	                  |||xs i       }t
        j                  d|d   |       t        |      S # t        $ r-}t
        j                  d|       dt        |      icY d}~S d}~ww xY w)aE  
        Create a Stripe customer.

        Parameters
        ----------
        email   : Customer email address.
        name    : Customer full name.
        metadata: Optional key/value metadata attached to the customer.

        Returns
        -------
        dict  Stripe Customer object data, or error dict.
        create_customer)emailnamemetadataz!Created Stripe customer %s for %sidzcreate_customer failed: %sr   N)r!   r   r"   Customercreater$   infodict	Exceptionr   str)r&   r*   r+   r,   customerexcs         r   r)   zGenesisBilling.create_customer   s    &  &'899
	'"++22!R 3 H
 KK;Xd^US>! 	'LL5s;SX&&	's   A
A 	B'"B	BBc                6   t         st        d      S |j                         }|t        vrdd| dt	        t               dS t
        |   }	 t        j                  j                  |gd      }|j                  sdd	| dS |j                  d
   d   }t        j                  j                  |d|igdd|i      }t        j                  d|d   ||       t        |      S # t        $ r-}t        j!                  d|       dt#        |      icY d}~S d}~ww xY w)aY  
        Create a subscription for *customer_id* at *tier*.

        Parameters
        ----------
        customer_id : Stripe customer ID (e.g. ``cus_xxx``).
        tier        : One of ``"starter"``, ``"professional"``, ``"enterprise"``.

        Returns
        -------
        dict  Stripe Subscription object data, or error dict.
        create_subscriptioninvalid_tierUnknown tier ''. Valid tiers: r      lookup_keyslimitprice_not_found&No Stripe price found for lookup key: r   r-   priceaudgenesis_tier)r4   itemscurrencyr,   z1Created subscription %s for customer %s (tier=%s)zcreate_subscription failed: %sr   N)r!   r   lower_VALID_TIERSsortedr   r"   PricelistdataSubscriptionr/   r$   r0   r1   r2   r   r3   )r&   customer_idtier
lookup_keypricesprice_idsubscriptionr5   s           r   r7   z"GenesisBilling.create_subscription   s8   "  &'<==zz||#'$TF*:6,;O:PQ  !&
	' &&++A+NF;;.!G
|T  {{1~d+H&33::$*+($/	 ; L KKCT"	 %% 	'LL93?SX&&	's%   5C" AC" "	D+"DDDc                b   t         st        d      S 	 |r"t        j                  j	                  |d      }nt        j                  j                  |      }t        j                  d||       t        |      S # t        $ r-}t        j                  d|       dt        |      icY d}~S d}~ww xY w)a  
        Cancel a subscription.

        Parameters
        ----------
        subscription_id : Stripe subscription ID (e.g. ``sub_xxx``).
        at_period_end   : If *True* (default) the subscription runs until the
                          current billing period ends before cancelling.
                          If *False* cancellation is immediate.

        Returns
        -------
        dict  Updated Stripe Subscription object, or error dict.
        cancel_subscriptionT)cancel_at_period_endz,Cancelled subscription %s (at_period_end=%s)zcancel_subscription failed: %sr   N)r!   r   r"   rL   modifycancelr$   r0   r1   r2   r   r3   )r&   subscription_idat_period_endrR   r5   s        r   rT   z"GenesisBilling.cancel_subscription   s    &  &'<==	'*77>>#)-  ?  
  +77>>OKK>
 %% 	'LL93?SX&&	's   A$A8 8	B."B)#B.)B.c                    t         st        d      S 	 t        j                  j	                  |      }t        |      S # t        $ r-}t        j                  d|       dt        |      icY d}~S d}~ww xY w)z
        Retrieve a subscription by ID.

        Parameters
        ----------
        subscription_id : Stripe subscription ID.

        Returns
        -------
        dict  Stripe Subscription object, or error dict.
        get_subscriptionzget_subscription failed: %sr   N)
r!   r   r"   rL   retriever1   r2   r$   r   r3   )r&   rX   rR   r5   s       r   r[   zGenesisBilling.get_subscription  sg      &'9::	'&33<<_ML%% 	'LL6<SX&&	's   )= 	A3"A.(A3.A3c                f   t         st        d      S |j                         }|t        vrdd| dt	        t               dS t
        |   }	 t        j                  j                  |gd      }|j                  sdd	| dS |j                  d
   d   }t        j                  j                  j                  |dg|ddgd||d|t        |   d      }t        j                  d|d   ||       t!        |      S # t"        $ r-}	t        j%                  d|	       dt'        |	      icY d}	~	S d}	~	ww xY w)a  
        Create a Stripe Checkout Session for *tier*.

        Parameters
        ----------
        tier           : One of ``"starter"``, ``"professional"``, ``"enterprise"``.
        customer_email : Pre-fill the checkout form with this email.
        success_url    : URL Stripe redirects to on success.
        cancel_url     : URL Stripe redirects to on cancel.

        Returns
        -------
        dict  Stripe Session object (includes ``url`` for redirect), or error dict.
        create_checkout_sessionr8   r9   r:   r   r;   r<   r?   r@   r   r-   card)rA   quantityrR   rB   )rC   amount_aud_cents)customer_emailpayment_method_types
line_itemsmodesuccess_url
cancel_urlrE   r,   z,Created checkout session %s for %s (tier=%s)z"create_checkout_session failed: %sr   N)r!   r   rF   rG   rH   r   r"   rI   rJ   rK   checkoutSessionr/   r   r$   r0   r1   r2   r   r3   )
r&   rN   rb   rf   rg   rO   rP   rQ   sessionr5   s
             r   r^   z&GenesisBilling.create_checkout_session!  sR   *  &'@AAzz||#'$TF*:6,;O:PQ  !&
	' &&++A+NF;;.!G
|T  {{1~d+H!**2299-&,X&.A>?#'%$((>t(D : G KK>	 =  	'LL=sCSX&&	's%   5C: A7C: :	D0"D+%D0+D0c                   t         st        d      S 	 t        j                  j	                  |||      }t
        j                  d|d          t        |      S # t        j                  j                  $ r.}t
        j                  d|       dt        |      dcY d}~S d}~wt        $ r-}t
        j                  d|       d	t        |      icY d}~S d}~ww xY w)
u  
        Verify a Stripe webhook signature and parse the event.

        Parameters
        ----------
        payload        : Raw request body bytes.
        sig_header     : Value of the ``Stripe-Signature`` HTTP header.
        webhook_secret : Webhook endpoint signing secret (``whsec_…``).

        Returns
        -------
        dict  Parsed Stripe Event object, or error dict.
        handle_webhookz!Verified Stripe webhook event: %stypez0Stripe webhook signature verification failed: %sinvalid_signaturer   Nzhandle_webhook failed: %sr   )r!   r   r"   Webhookconstruct_eventr$   r0   r1   r   SignatureVerificationErrorr%   r3   r2   )r&   payload
sig_headerwebhook_secreteventr5   s         r   rl   zGenesisBilling.handle_webhookh  s    &  &'788	'''77^E KK;U6]K;  ;; 	GNNMsS0SXFF 	'LL4c:SX&&	's0   AA C5#BCC*"CCCc                    t         st        j                  d       y	 t        j                  j
                  j                  ||      }|d   S # t        $ r }t        j                  d|       Y d}~yd}~ww xY w)aK  
        Create a Stripe Billing Portal session and return the URL.

        Parameters
        ----------
        customer_id : Stripe customer ID.
        return_url  : URL the customer is sent back to after managing billing.

        Returns
        -------
        str  Portal session URL, or an empty string on error.
        u5   stripe not installed — cannot create portal sessionr   )r4   
return_urlurlz"get_customer_portal_url failed: %sN)	r!   r$   r%   r"   billing_portalri   r/   r2   r   )r&   rM   rw   portal_sessionr5   s        r   get_customer_portal_urlz&GenesisBilling.get_customer_portal_url  ss    "  NNRS	(77??FF$% G N "%(( 	LL=sC	s   /A 	A7A22A7)N)r#   zOptional[str]returnNone)r*   r3   r+   r3   r,   zOptional[Dict[str, Any]]r|   Dict[str, Any])rM   r3   rN   r3   r|   r~   )T)rX   r3   rY   boolr|   r~   )rX   r3   r|   r~   )
rN   r3   rb   r3   rf   r3   rg   r3   r|   r~   )rr   bytesrs   r3   rt   r3   r|   r~   )rM   r3   rw   r3   r|   r3   )__name__
__module____qualname____doc__r'   r)   r7   rT   r[   r^   rl   r{   r   r   r   r   r   c   s   " .2	 ' '  ' +	 '
 
 'L7'7' 7' 
	7'x #'''' '' 
	''R'4A'A' A' 	A'
 A' 
A'N!'!' !' 	!'
 
!'N  
	r   r   zOptional[GenesisBilling]_billing_instancec                 .    t         
t               a t         S )z
    Return the module-level GenesisBilling singleton.

    The instance is created on first call and reused thereafter.
    The API key is read from the ``STRIPE_SECRET_KEY`` environment variable.
    )r   r   r   r   r   get_billingr     s      *,r   )r   r3   r|   r~   )r|   r   )r   
__future__r   loggingr   typingr   r   r   	getLoggerr   r$   striper"   r!   ImportErrorr%   r   __annotations__r   	frozensetkeysrG   r   r   r   r   r   r   r   <module>r      s   #H #  	 & &			8	$
	 " 1:7^  *   ))+,I I`
 /3 + 2
G  K
NN	Es   A; ;BB