U
    - i|                     @   s   d dl Z d dlmZmZ d dlmZmZ d dlmZ d dlm	Z	m
Z
 d dlmZ eje
 e
jZe je
je
jfdZddd	Zd
d Zdd Zdd Zdd Zdd Zdd Zdd ZdS )    N)datetime	timedelta)requestjsonify)closing)connect_to_databaseConfig)app)authc                 C   st   d}d}| r0| |k s| |kr0t d| d| |rX||k sD||krXt d| d| | rp|rp|| krpt ddS )z$Validate timestamps for Razorpay APICm8   V	8 zstart_at must be between z and zexpire_by must be between z expire_by must be after start_atT)
ValueError)start_at	expire_byZmin_tsZmax_ts r   </var/www/html/api-medvista/Services/Billing/Subscriptions.pyvalidate_razorpay_timestamps   s    r   c                  C   s  t  } ddg}|D ](}|| krtd| dddf  S qt }zFzt|jdd}|d| d f | }|r|d	 d
krtddddfW  5 Q R  W W S |d	 dkr|d rzt	j
|d  W n   Y nX |d|d f |d|d f |d| d f | }|sTtddddfW  5 Q R  W W <S t|d dk}|d dkr|s|d stddddfW  5 Q R  W W S t }|tdd |tdd dd|d }	|rd
nd}
|d| d | d ||	|
|d |	f |j}|rd nd!}|r,d"nd#}d$|d% d&| }|d'||||td(d |d |d |d) ||f	 |j}|r|  td*|dd+d,d-fW  5 Q R  W W S ztt  }d.}d/}t|d0 |}|d dkr|d d1kr|d2 }d3}n|d4 }d5}t||}t|| td6|  td7| d8 td9|  |d |d:||t| d t|t||d; d<d=}td>|  t	j
|}|d?|d |f |d@|d |f |d tt|d dA|d; dB| dBdCi|dD}dE}nt	jtt|d dF dA|t| d t|t||d; d<dG}|d@|d |f |d tt|d dA|d; dB| dBdCidH}dI}|  t||||d+dJd-fW W  5 Q R  W W S  tjj k
r } z|!  t|}tdK|  dL|ks dM|ks dN|ks dO|krPtdPd|dQdRf W Y W  5 Q R  W W @S dS|krtdTdddRf W Y NW  5 Q R  W W S tdU| dddRf W Y W  5 Q R  W W S W 5 d}~X Y nF tjj"k
r8 } zH|!  tdVt|  tdWdddRf W Y W  5 Q R  W W dS d}~X Y n t#k
r } zN|!  tdXt|  tdYdt|dQdRf W Y W  5 Q R  W W  S d}~X Y np t$k
r } zP|!  tdZt|  td[t| dddRf W Y W  5 Q R  W W S d}~X Y nX W 5 Q R X W nh t$k
r } zH|rB|!  td\t|  td]t| dddRf W Y W S d}~X Y nX W 5 |r|  X dS )^zS
    Create a new subscription with proper validation and Razorpay integration
    user_id
package_idMissing required field: Tmessageerror  
dictionaryz
                SELECT id, package_id, status, razorpay_subscription_id
                FROM subscriptions 
                WHERE user_id = %s AND status IN ('active', 'pending')
                ORDER BY id DESC LIMIT 1
            statusactivez^You already have an active subscription. Please cancel it before subscribing to a new package.pendingrazorpay_subscription_idz
                        UPDATE subscriptions SET status = 'canceled' 
                        WHERE id = %s
                    idz
                        UPDATE invoices SET status = 'canceled'
                        WHERE subscription_id = %s AND status IN ('draft', 'pending', 'unpaid')
                    z
                SELECT id, billing_cycle, razorpay_plan_id, price, currency_id, 
                       package_name, maximum_bookings, price_after_max
                FROM packages WHERE id = %s AND is_active = TRUE
            zActive package not found  priceg        billing_cycle)monthlyannualrazorpay_plan_idzWThis package is not properly configured for recurring payments. Please contact support.   daysm  N)r$   r%   lifetimez
                INSERT INTO subscriptions (
                    user_id, package_id, start_date, end_date, 
                    status, billing_cycle, next_billing_date
                ) VALUES (%s, %s, %s, %s, %s, %s, %s)
            ZpaidZdraftfreerazorpayzINV-z%Y%m%d%H%M%S-a	  
                INSERT INTO invoices (
                    subscription_id, invoice_number, issue_date, due_date,
                    amount, total_amount, currency_id, status, gateway_type
                ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
               currency_idz(Free subscription activated successfullyF)r   subscription_idpayment_datar      r   r   i,  r$   i$.    i    zCurrent timestamp: zStart at timestamp: z (current + 5 min)zExpire by timestamp:    package_name)r   r1   
invoice_idr7   )plan_idtotal_countZcustomer_notifyr   r   notesz*Creating Razorpay subscription with data: z
                        UPDATE subscriptions 
                        SET razorpay_subscription_id = %s 
                        WHERE id = %s
                    z
                        UPDATE invoices
                        SET gateway_order_id = %s
                        WHERE id = %s
                    ZINRemail )r   razorpay_keyamountcurrencynameprefillr:   z&Subscription created, awaiting paymentd   )r?   r@   Zreceiptr;   )razorpay_order_idr>   r?   r@   rA   rB   z(One-time order created, awaiting payment)r   r1   r8   r2   r   zRazorpay BadRequestError: end_time	timestampr   r   z@Subscription timing configuration error. Please contact support.)r   r   details  r9   z4Package configuration error. Please contact support.zPayment gateway error: zRazorpay ServerError: z=Payment gateway is temporarily unavailable. Please try again.zTimestamp validation error: z2Subscription timing error. Please contact support.zPayment creation error: zPayment creation failed: zSubscription creation error: zError creating subscription: )%r   get_jsonr   r   closer   cursorexecutefetchonerazorpay_clientsubscriptioncancelfloatr   nowr   get	lastrowidstrftimecommitintrF   maxminr   printstrcreateRAZORPAY_KEY_IDorderr-   errorsBadRequestErrorrollbackServerErrorr   	Exception)datarequired_fieldsfield
connectionrK   Zexisting_subscriptionpackageis_free
start_dateend_dateZ
sub_statusr1   invoice_statusZgateway_typeZinvoice_numberr8   Zcurrent_timestampZmin_timestampZmax_timestampr   r   r:   Zsubscription_dataZrazorpay_subscriptionr2   r   Zrazorpay_ordereZ	error_msgr   r   r   create_subscription   s   &     	      






 



 
( 
 2,,::rn   c                 C   s  t  }tjd}zz>t|jdd"}d}| g}|rN|d7 }|| |d7 }||t	| |
 }i }d}|D ]}	|	d }
|s|	d	 |	d
 |	d d}|
|kr|	d |	d |	d |	d |	d |	d |	d t|	d |	d g d
||
< |	d rz||
 d |	d |	d |	d d qztt| |dddfW  5 Q R  W W jS Q R X W nZ tk
r } z:tdt|  tdt| ddd f W Y W S d}~X Y nX W 5 |r|  X dS )!z4Get all subscriptions for a user with their invoicesr   Tr   ab  
                SELECT 
                    s.id AS subscription_id,
                    s.razorpay_subscription_id,
                    s.status AS subscription_status,
                    s.start_date,
                    s.end_date,
                    s.next_billing_date,
                    p.package_name,
                    p.price,
                    p.billing_cycle,
                    i.id AS invoice_id,
                    i.status AS invoice_status,
                    i.created_at AS invoice_date,
                    u.email,
                    u.firstname,
                    u.lastname
                FROM subscriptions s
                JOIN packages p ON s.package_id = p.id
                LEFT JOIN invoices i ON s.id = i.subscription_id
                JOIN users u ON s.user_id = u.id
                WHERE s.user_id = %s
             AND s.status = %sz. ORDER BY s.start_date DESC, i.created_at DESCNr1   r<   	firstnamelastname)r<   rp   rq   r   subscription_statusrj   rk   next_billing_dater7   r"   r#   )
r1   r   rr   rj   rk   rs   r7   r"   r#   invoicesr8   rt   rl   invoice_date)r8   rl   ru   F)rd   userr      Error fetching subscriptions: r   rH   )r   r   argsrS   rJ   r   rK   appendrL   tuplefetchallrQ   r   listvaluesrc   rZ   r[   )r   rg   Zstatus_filterrK   ZsqlparamsrecordssubscriptionsZ	user_inforowZsub_idrm   r   r   r   get_user_subscriptionsE  sf    




 :r   c                 C   s  t  }zʐzZt|jdd>}|d| f | }|sbtddddfW  5 Q R  W W tS |d }|d }|rztj	| t
d	|  W nl tjjk
r } zt
d
t|  W 5 d}~X Y n6 tk
r } zt
dt|  W 5 d}~X Y nX |dt t | f |dt | f |  tddddfW  5 Q R  W W xS Q R X W nh tk
r } zH|r|  t
dt|  tdt| dddf W Y W S d}~X Y nX W 5 |r|  X dS )z3Cancel a subscription in both Razorpay and databaseTr   z
                SELECT razorpay_subscription_id, status, user_id
                FROM subscriptions
                WHERE id = %s AND status IN ('active', 'pending')
            z2No active or pending subscription found to cancel.r   r!   r   r   z!Cancelled Razorpay subscription: zRazorpay cancellation warning: NzRazorpay cancellation error: z
                UPDATE subscriptions 
                SET status = 'canceled', end_date = %s, updated_at = %s
                WHERE id = %s
            z
                UPDATE invoices 
                SET status = 'canceled', updated_at = %s
                WHERE subscription_id = %s AND status IN ('draft', 'unpaid', 'pending')
            z#Subscription canceled successfully.Frw   zError canceling subscription: rH   )r   rJ   r   rK   rL   rM   r   rN   rO   rP   rZ   r-   r_   r`   r[   rc   r   rR   rV   ra   )r1   rg   rK   rO   Zrazorpay_sub_idZprevious_statusrm   r   r   r   cancel_subscription  sX    "$
 :r   c           
      C   s  t  }zz@t|jdd$}|d|| f | }|sdtddddfW  5 Q R  W W JS |d|f | }|D ]>}|d|d	 f | }||d
< |d r~t|d |d< q~|d	 |d |d |d |d |d |	d|d |d rt|d ndt|d |d |d}t|dddfW  5 Q R  W W jS Q R X W nZ t
k
r }	 z:tdt|	  tdt|	 dddf W Y W S d}	~	X Y nX W 5 |r|  X dS )zBGet detailed subscription information including usage and invoicesTr   a6  
                SELECT s.*, 
                       p.package_name, p.maximum_bookings, 
                       p.price_after_max, p.price, p.currency_id
                FROM subscriptions s
                JOIN packages p ON s.package_id = p.id
                WHERE s.id = %s AND s.user_id = %s
            Subscription not foundr   r!   a  
                SELECT id, invoice_number, total_amount, status, due_date, issue_date,
                       gateway_order_id, gateway_type
                FROM invoices
                WHERE subscription_id = %s
                ORDER BY issue_date DESC
            a  
                    SELECT id, amount, payment_method, transaction_id, payment_date, status
                    FROM payments
                    WHERE invoice_id = %s
                    ORDER BY payment_date DESC
                    LIMIT 1
                r    Zlatest_paymenttotal_amountr7   r#   r   rj   rk   rs   maximum_bookingsprice_after_maxNr"   r   )r1   r7   r#   r   rj   rk   rs   r   r   r"   r   rt   Frd   r   rw   z%Error fetching subscription details: rH   )r   rJ   r   rK   rL   rM   r   r|   rQ   rS   rc   rZ   r[   )
r   r1   rg   rK   rO   rt   invoicepaymentresponse_datarm   r   r   r   get_user_subscription_details  sZ    	&
 :r   c               
   C   s  t jd} t jjddtd}t jjddtd}t }z` zt|jdd}d	}g }| rn|d
7 }||  d| d}|	|| |
 d }|d7 }|||d | g |	|| | }	|	D ]>}
|	d|
d f |
 }||
d< |
d rt|
d |
d< qt|	|||dddfW  5 Q R  W W jS Q R X W nZ tk
r } z:tdt|  tdt| dddf W Y W S d}~X Y nX W 5 |r|  X dS )z&Get all subscriptions (admin endpoint)r   pager6   )defaulttypelimit
   Tr   a  
                SELECT 
                    s.id, s.user_id, s.package_id, s.status, s.start_date, s.end_date, s.billing_cycle,
                    s.razorpay_subscription_id, s.created_at,
                    p.package_name, p.price,
                    u.email, u.firstname, u.lastname
                FROM subscriptions s
                JOIN packages p ON s.package_id = p.id
                JOIN users u ON s.user_id = u.id
                WHERE 1=1
            ro   zSELECT COUNT(*) as total FROM (z) AS subquerytotalz. ORDER BY s.start_date DESC LIMIT %s OFFSET %sz
                    SELECT id, invoice_number, total_amount, status, issue_date
                    FROM invoices
                    WHERE subscription_id = %s
                    ORDER BY issue_date DESC
                    LIMIT 1
                r    latest_invoicer"   F)rd   r   r   per_pager   rw   rx   r   rH   N)r   ry   rS   rW   r   rJ   r   rK   rz   rL   rM   extendr|   rQ   r   rc   rZ   r[   )r   r   r   rg   rK   Z
base_queryr   count_queryr   r   subr   rm   r   r   r   get_all_subscriptions,  sP    
 :r   c            
      C   s  t  } ddg}|D ](}|| krtd| dddf  S qt }zzBt|jdd&}|d| d f | }|std	ddd
fW  5 Q R  W W XS z*t	j
| d }|d dkrt }d}|d dkr|tdd }n|d dkr
|tdd }|d|||t | d f |dt | d f |d| d t t|| d f |  tdddddfW W  5 Q R  W W fS td|d  |d dddfW W  5 Q R  W W .S W n tjjk
r* }	 z6tdt|	 dddf W Y W  5 Q R  W W S d}	~	X Y nV tk
r~ }	 z6tdt|	 dddf W Y W  5 Q R  W W S d}	~	X Y nX W 5 Q R X W nh tk
r }	 zH|r|  tdt|	  td t|	 dddf W Y W S d}	~	X Y nX W 5 |r|  X dS )!z1Verify Razorpay payment and activate subscription
payment_idr1   r   Tr   r   r   z
                SELECT s.*, p.package_name, p.billing_cycle
                FROM subscriptions s
                JOIN packages p ON s.package_id = p.id
                WHERE s.id = %s
            r   r!   r   ZcapturedNr#   r$   r'   r(   r%   r*   z
                        UPDATE subscriptions 
                        SET status = 'active', start_date = %s, end_date = %s, 
                            next_billing_date = %s, updated_at = %s
                        WHERE id = %s
                    z
                        UPDATE invoices 
                        SET status = 'paid', updated_at = %s
                        WHERE subscription_id = %s AND status IN ('draft', 'pending', 'unpaid')
                    a  
                        INSERT INTO payments (
                            invoice_id, amount, payment_method, transaction_id, 
                            payment_date, status, gateway_response
                        ) SELECT 
                            i.id, i.total_amount, 'razorpay', %s,
                            %s, 'completed', %s
                        FROM invoices i
                        WHERE i.subscription_id = %s AND i.status = 'paid'
                        ORDER BY i.id DESC LIMIT 1
                    z8Payment verified and subscription activated successfullyF)r   Zpayment_statusr   rw   zPayment not captured. Status: zInvalid payment ID: zPayment verification failed: rH   zPayment verification error: zError verifying payment: )r   rI   r   r   rJ   r   rK   rL   rM   rN   r   fetchr   rR   r   r[   rV   r-   r_   r`   rc   ra   rZ   )
rd   re   rf   rg   rK   rO   r   rj   rk   rm   r   r   r   verify_payments  s    &
*::r   c              
   C   s
  t  }zzt|jddv}|d| f | }|D ]4}|d rRt|d |d< |d r6t|d |d< q6t|dddfW  5 Q R  W W hS Q R X W nX tk
r } z:t	d	t
|  td	t
| dd
df W Y W S d}~X Y nX W 5 |r|  X dS )z,Get all invoices for a specific subscriptionTr   aU  
                SELECT 
                    i.*,
                    p.payment_method, p.transaction_id, p.payment_date, p.status as payment_status
                FROM invoices i
                LEFT JOIN payments p ON i.id = p.invoice_id
                WHERE i.subscription_id = %s
                ORDER BY i.issue_date DESC
            r?   r   Fr   rw   zError fetching invoices: r   rH   N)r   rJ   r   rK   rL   r|   rQ   r   rc   rZ   r[   )r1   rg   rK   rt   r   rm   r   r   r   get_subscription_invoices  s.    
 :r   )NN)r-   r   r   flaskr   r   
contextlibr   confr   r   r	   configfrom_objectr]   ClientRAZORPAY_KEY_SECRETrN   r   rn   r   r   r   r   r   r   r   r   r   r   <module>   s$   
  *ZBKGg