
    ,i5                        d Z ddlZddlZddlZddlZddlZddlmZ ddlm	Z	 ddl
m
Z
 ddlZ ej                  d      ZdZej                  j!                  dd	      Z	 ej$                  j'                  dd
       ddlmZ es ed      ZdZdZd.dededefdZdedefdZd/dedededefdZ	 	 	 	 	 d0dede	e   dedede	e   de	e   dedede	e   defdZe d k(  r ejB                  ejD                  d!"        e#ejH                        d#kD  rejH                  d#   nd$Z% e&d%e% d&        ee%      Z' e& ejP                  e'd'(              ee%d)d*d+e'd,-      Z) e&d&e)z          yy# e$ r Y w xY w)1uU  
Genesis Clone Pipeline — QA Checker Module
==========================================
Quality assurance checks for cloned websites:
  1. Google PageSpeed Insights API (mobile + desktop scores)
  2. Basic HTML validation (structure checks)
  3. Before/after report generation

Google PageSpeed API is free, no auth required for basic use.
    N)Path)Optional)datetimezclone_pipeline.qa_checkerz:https://www.googleapis.com/pagespeedonline/v5/runPagespeedGOOGLE_PAGESPEED_API_KEY z/mnt/e/genesis-system/core)_get_envU   Z   urlstrategyreturnc                    dddddddddd| |d}t         s"d|d<   t        j                  d|d           |S | |g dt         d}t        j                  d	| d
|         	 t	        j
                  t        |d      }|j                          |j                         }|j                  di       j                  di       }|j                  di       j                  di       }t        |j                  di       j                  d      xs ddz        |d<   t        |j                  di       j                  d      xs ddz        |d<   t        |j                  di       j                  d      xs ddz        |d<   t        |j                  di       j                  d      xs ddz        |d<   |d   |d<   |j                  di       j                  d      }|j                  di       j                  d      }	|j                  di       j                  d      }
|j                  di       j                  d      }|rt        |dz  d      nd|d<   |	rt        |	dz  d      nd|d <   |
rt        |
d!      nd|d"<   |rt        |d      nd|d#<   t        j                  d$| d%|d    d&|d    d'|d           |S # t        j                  j                  $ r$ d(|d<   t        j                  d|d           Y |S t        j                  j                  $ r}|j                  j                  d)v r9d*|j                  j                   d+|d<   t        j                  d|d           n7d,|j                  j                   |d<   t        j                  d|d           Y d}~|S d}~wt         $ r.}d-| |d<   t        j                  d|d           Y d}~|S d}~ww xY w).aC  
    Check PageSpeed score for a URL using Google PageSpeed Insights API.

    Args:
        url: URL to check
        strategy: 'mobile' or 'desktop'

    Returns dict with keys:
        - score: int (0-100, -1 if check failed)
        - performance: int
        - accessibility: int
        - seo: int
        - best_practices: int
        - fcp: float (First Contentful Paint in seconds)
        - lcp: float (Largest Contentful Paint in seconds)
        - cls: float (Cumulative Layout Shift)
        - tbt: float (Total Blocking Time in ms)
        - error: str or None
    N)scoreperformanceaccessibilityseobest_practicesfcplcpclstbterrorr   r   z=Google PageSpeed API key not found. Skipping PageSpeed check.r   z[QA] )r   r   r   best-practices)r   r   categorykeyz[QA] Checking PageSpeed (z): <   )paramstimeoutlighthouseResult
categoriesauditsr   r   r   d   r   r   r   r   zfirst-contentful-paintnumericValuezlargest-contentful-paintzcumulative-layout-shiftztotal-blocking-timei     r   r      r   r   z[QA] PageSpeed (z): Performance=z, Accessibility=z, SEO=zPageSpeed API timeout after 60s)i  i  z,PageSpeed API key issue or rate limit: HTTP zE. Please ensure GOOGLE_PAGESPEED_API_KEY is valid and API is enabled.zPageSpeed API HTTP error: zPageSpeed check failed: )PAGESPEED_API_KEYloggerwarninginforequestsgetPAGESPEED_API_URLraise_for_statusjsonintround
exceptionsTimeout	HTTPErrorresponsestatus_code	Exception)r   r   resultr   respdatar!   r"   r   r   r   r   es                :/mnt/e/genesis-system/scripts/clone_pipeline/qa_checker.pycheck_pagespeedr=   1   s   * F Ywvg/01 M 	F KK+H:S>?32||-fbIyy{XX0"599,K
,b155hC !$^^M2.227;@qCG!
} #&^^OR044W=BcI#
 ^^E2&**738qC?
u $'^^,b155g>C!sJ$
  !/w jj126::>Jjj3R8<<^Ljj2B7;;NKjj.377G03cDj!,u03cDj!,u),c1$u),c1$uxj}8M7N O#O45VF5M?L	
& M && 2;wvg/01 M (( 6::!!Z/ LQZZMcMcLd  ej  kF7ONNU6'?"345 :1::;Q;Q:RSF7ONNU6'?"345
 M	  24QC8wvg/011M	2s,   !IJ; ;=O;OBN%%O1#OOc                     t         j                  d|         t        | d      }t        j                  d       t        | d      }||| |d   t
        k\  xs |d   t        k\  dS )zo
    Run PageSpeed checks for both mobile and desktop.

    Returns dict with 'mobile' and 'desktop' keys.
    z#[QA] Running full PageSpeed audit: mobile)r   r%   desktopr   )r?   r@   r   passed)r(   r*   r=   timesleepTARGET_MOBILE_SCORETARGET_DESKTOP_SCORE)r   r?   r@   s      r<   check_pagespeed_bothrF      sp     KK5cU;<S84FJJqMcI6G 7O22 8w#77     htmlbusiness_namephonec                 8  	 g 	dt         dt        dt         dt         f	fd}| j                         } |dd|v dd	        |d
d|v dd        |dd|v xr d|v dd        |dd|v xr d|v dd        |dd|v dd        |dd|v dd        |d d!|v d"d#        |d$d%|v xs d&|v d'd(        |d)d*|v d+d,       |r# |d-|j                         |v d.| d/d.| d0       |r@d1j                  d2 |D              } |d3|| v xs || v d4| d5d4| d6        |d7d8|v d9d:        |d;d<|v xs d=|v xs d>|j	                  d?d1      v d@dA        |dBdC|v dDdE       t        dF 	D              }	rt        |t        	      z  dGz        ndH}|dIk\  }|	||t        	      dJS )Kz
    Basic structural validation of the generated HTML.

    Returns dict with:
        - valid: bool
        - checks: list of (check_name, passed, message) tuples
        - score: int (0-100)
    name	conditionpass_msgfail_msgc                 8    j                  | ||r|n|d       y )N)rL   rA   message)append)rL   rM   rN   rO   checkss       r<   checkzvalidate_html.<locals>.check   s!    #,x(
 	rG   DOCTYPEz<!doctype html>zDOCTYPE presentzMissing <!DOCTYPE html>zHTML tagz<htmlzHTML tag presentzMissing <html> tagzHead sectionz<headz</head>zHead section presentzMissing <head> sectionzBody sectionz<bodyz</body>zBody section presentzMissing <body> sectionz	Title tagz<title>zTitle tag presentzMissing <title> tagzMeta viewportzname="viewport"z$Viewport meta present (mobile-ready)zMissing viewport meta tagz
H1 headingz<h1zH1 heading presentzMissing H1 headingzTailwind CSStailwindcsstailwindzTailwind CSS includedzTailwind CSS not foundzMeta descriptionzname="description"zMeta description presentzMissing meta descriptionzBusiness namezBusiness name 'z' foundz' not found in HTMLr   c              3   B   K   | ]  }|j                         s|  y w)N)isdigit.0cs     r<   	<genexpr>z validate_html.<locals>.<genexpr>   s     >A!))+a>s   zPhone numberzPhone z found in HTMLz not found in HTMLzClick-to-callztel:z!Click-to-call (tel: link) presentzMissing click-to-call linkzChatbot widgetzgenesis-chatgenesis_chatgenesisinit zChatbot widget snippet foundzChatbot widget not injectedzSchema markupz
schema.orgzSchema.org markup presentz"Missing schema.org structured datac              3   ,   K   | ]  }|d    s	d  yw)rA      N rZ   s     r<   r]   z validate_html.<locals>.<genexpr>   s     8QAhKq8s   
r#   r   F   )validrS   r   rA   total)strboollowerjoinreplacesumr0   len)
rH   rI   rJ   rT   
html_lowerclean_phonepassed_countr   re   rS   s
            @r<   validate_htmlrq      s    FC D C 3  J 
)&*4
68	*g+
24	.'Z/KI4K
 ":<	.'Z/KI4K
 ":<	+yJ.
46	/,
:
02MO	,+
 46	.-:5Qz9Q
!#;= 

2j@
$&@B o}224
Bg6.AB	D gg>>>netmB{d/Bug^,ug/0	2 	ov313O	Q 

Nj8 :Nj<X :j00b99
(*GI
 
/<:5
%'KM 8&88L7=CF+s231ERKE V rG   original_urlnew_urlclient_slugpagespeed_scoreshtml_validationextraction_methodelapsed_seconds
output_dirc	                    t        j                         j                  d      }	d}
|r|j                  di       }|j                  di       }|j                  dd      }|j                  dd      }|t        k\  rdn|dk\  rd	nd
}|t
        k\  rdn|dk\  rd	nd
}dj                  g d| d| d| d| d|j                  dd       d|j                  dd       d|j                  dd       d|j                  dd       d|j                  dd       d|j                  dd       d|j                  dd       d|j                  dd       d|j                  dd       d|j                  dd       d|j                  dd       d|j                  dd       d|j                  dd       d |j                  dd       d!t         d"t
         d#|j                  d$      rd%nd& d'      }
d}|rw|j                  d$d(      }|j                  d)d(      }|j                  dd(      }d*| d+| d,| d-}|j                  d.g       D ]   }|d$   rdnd
}|d/|d0    d1| d2|d3    d4z  }" d5|	 d6| d7| d8|  d9|xs d: d;| d<|d=d>|
 d'| d?|xs d@ dA|	 dB}|rC|j                  dCdCD       |dEz  }|j                  |dFG       t        j                  dH|        |S )Iz
    Generate a markdown before/after comparison report.

    Returns the markdown report string, and optionally saves to output_dir.
    z%Y-%m-%d %H:%Mr   r?   r@   r   r   PASS2   WARNFAILzb
## PageSpeed Scores

| Metric | Mobile | Desktop |
|--------|--------|---------|
| Performance | z/100 [z] | z] |
| Accessibility | r   -z/100 | z/100 |
| SEO | r   z/100 |
| Best Practices | r   z/100 |
| FCP | r   zs | zs |
| LCP | r   zs |
| CLS | r   z | z |
| TBT | r   zms | zms |

Target: Mobile >= z, Desktop >= z	
Result: rA   PASSEDzNEEDS IMPROVEMENT
r   rf   z
## HTML Validation

Score: z/100 (/z7 checks passed)

| Check | Status |
|-------|--------|
rS   z| rL   z | [z] rQ   z |
z*# Genesis Website Clone Report
Generated: z

## Client: z
- **Slug**: z
- **Original URL**: z
- **New URL**: z Saved locally (no Netlify token)z
- **Extraction Method**: z
- **Processing Time**: z.1fz	 seconds
aG  
## Delivery Checklist

- [ ] Review all business information is accurate
- [ ] Phone number is correct and click-to-call works
- [ ] Services listed are complete and accurate
- [ ] Brand colours are appropriate
- [ ] Chatbot widget responds correctly
- [ ] Mobile display tested on real device
- [ ] Point client's domain to: z
local filea  

## Upsell Opportunities

- Talking Voice Widget: $197-$597/mo (Telnyx NaturalHD voice AI)
- ReceptionistAI: Handles all inbound calls 24/7 from $497/mo
- Monthly SEO package: Ongoing content and ranking improvement

---
*Report generated by Genesis Clone Pipeline | z*
T)parentsexist_okzclone_report.mdzutf-8)encodingz[QA] Report saved: )r   nowstrftimer,   rD   rE   rj   mkdir
write_textr(   r*   )rr   rs   rI   rt   ru   rv   rw   rx   ry   	timestampps_textr?   r@   mobile_scoredesktop_scoremobile_icondesktop_iconval_textrA   rf   r   r\   statusreportreport_paths                            r<   generate_reportr   	  s     ''(89I G!%%h3"&&y"5zz'2.GR0 ,0C CfT`dfTf&lr!.2F!FvWdhjWjVpv   
 
 %
 &1M
 26
 7D_
 EK
 LX.
Y ::os34 5< =DKKY\<];^_	 
E3	  !( )0E3(?'@A JJ/56 7> ?FkkJZ\_>`=ab	 
E3	  !% &-[[%<$=>	 
E3	  !% &-[[%<$=>	 
E3	  !$ %,KKs$;#<=	 
E3	  !& '.kk%&=%>? '' (5 6J4JK	 &))(39LMN& H $$Xq1##GQ/##GQ/ 	wfVHAeW % !$$Xr2 	IA {VF"QvYKtF82a	l^4HHH	I; ? M !N #==> ?+, -', -	 
	
 	! ")!8L 9 	:/ 09k :9F> 5 #44v8)+78MrG   __main__z%(levelname)s %(message)s)levelformatrb   zhttps://example.comz
Checking PageSpeed for: r   r%   )indentzhttps://test.netlify.appzTest Businessztest-businessg     @E@)rr   rs   rI   rt   ru   rx   )r?   )r   r   )NNunknownr   N)*__doc__ossysr/   rB   loggingpathlibr   typingr   r   r+   	getLoggerr(   r-   environr,   r'   pathinsertsecrets_loaderr   r7   rD   rE   rg   dictr=   rF   rq   floatr   __name__basicConfigINFOrm   argvr   printscoresdumpsr   rc   rG   r<   <module>r      s1  	 
 
       			6	7 Q JJNN#=rB 	HHOOA34'$%?@   f f f4 fRc d 6M MC MS M$ Mr (,&*&!%ggc]g g 	g
 tng d^g g g g 	g\ zGgll3NOSXX*#((1+0EC	&se2
./!#&F	*$**VA
&'*%#F 
$-# c
  		s   ,E* *E21E2