
    ɧ-iI                     2   d Z ddlmZmZ ddlZddlZddlmZ ddlZddl	Z	ddl
Z
ddlZ ej        e          Ze	j                            d e ee          j        j                             ddlmZmZmZmZmZ ddlmZ ddlmZ  G d d	          ZdS )
zV
Website Service
Handles website generation and management using DeepSite AI workflow
    )DictAnyN)Path)parse_json_inputformat_website_promptformat_edit_promptsetup_template_copy_logo_files)	AIService)DiffServicec                       e Zd Zd Zdeeef         deeef         fdZdeeef         defdZde	dedefd	Z
deeef         fd
ZdedefdZdedeeef         fdZdedefdZde	deddfdZde	de	ddfdZdS )WebsiteServicec                     t          d          | _        | j                            dd           t                      | _        d S )Nztemplates/generatedT)parentsexist_ok)r   generated_pathmkdirr   
ai_service)selfs    G/var/www/html/web-builder-api.evdpl.com/src/services/website_service.py__init__zWebsiteService.__init__   s>    "#899!!$!>>>#++    datareturnc                   K   	 t          |          }t          |          }t          |           d{V }|d         }t          |d                   }t	          ||           d{V }| j                            |d|            d{V }|                    d          r	|d         }	n|                     |          }	| 	                    |	          \  }
}|
st          d|           |                     |	          }	|                     |	          }	|dz  }|                     ||	           d{V  |	|t          |          |d	S # t          $ r$}t          d
t          |                     d}~ww xY w)zG
        Generate website from data using DeepSite AI workflow
        Nsafe_folder_namedestination_pathwebsite_)promptconversation_idcontentGenerated HTML is incomplete: 
index.html)html_contentfolder_namewebsite_path
logo_fileszWebsite generation failed: )r   r   r	   r   r
   r   generate_sync_responseget_create_basic_html_validate_html_complete	Exception_sanitize_third_party_resources_inject_eatance_footer_write_file_asyncstr)r   r   website_datadeepsite_promptsetup_resultr%   r&   r'   ai_responser$   is_valid	error_msg
index_filees                 r   generate_websitezWebsiteService.generate_website   s     2	D+D11L 4LAAO "0!=!=======L&'9:K-? @AAL  0lKKKKKKKKJ !% F F& 8; 8 8 !G ! !      K y)) E*95#66|DD #'">">|"L"LHi N L L LMMM  ??MML  66|DDL%4J((\BBBBBBBBB !-* #L 1 1(	    	D 	D 	DB#a&&BBCCC	Ds   EE 
E;E66E;r1   c                 8   |                     dd          }|                     dd          }|                     dd          }|                     dd          }|                     dd          }d	| d
| d| d|rd| dnd d|rd| dnd d|rd| dnd dS )z/
        Create basic HTML as fallback
        websiteNamezRestaurant WebsitewebsiteDescriptionzWelcome to our restaurant!restaurantPhone restaurantEmailrestaurantAddressz
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>a  </title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
            background-color: #f5f5f5;
        }
        .container {
            max-width: 800px;
            margin: 0 auto;
            background: white;
            padding: 40px;
            border-radius: 10px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }
        h1 {
            color: #333;
            text-align: center;
            margin-bottom: 20px;
        }
        .description {
            font-size: 18px;
            color: #666;
            text-align: center;
            margin-bottom: 30px;
        }
        .contact-info {
            background: #f8f9fa;
            padding: 20px;
            border-radius: 5px;
            margin-top: 30px;
        }
        .contact-item {
            margin: 10px 0;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>z%</h1>
        <p class="description">zf</p>
        
        <div class="contact-info">
            <h3>Contact Information</h3>
            z2<div class="contact-item"><strong>Phone:</strong> z</div>z
            z2<div class="contact-item"><strong>Email:</strong> z4<div class="contact-item"><strong>Address:</strong> z3
        </div>
    </div>
</body>
</html>
        )r)   )r   r1   website_namedescriptionphoneemailaddresss          r   r*   z!WebsiteService._create_basic_htmlV   s1    $''7KLL"&&';=YZZ  !2B77  !2B77""#6;;: : :\ ]: :^ !,_: :f TY`O%OOOO^`g: :h TY`O%OOOO^`i: :j X_fSGSSSSdfk: : : :	r   r&   r%   c                 f  K   	 t          d          | dz  }|j                            d           |                                rt	          |          S |                     ||           d{V  t	          |          S # t          $ r$}t          dt	          |                     d}~ww xY w)z
        Create ZIP file from website folder asynchronously.

        Simple behavior: if downloads/<folder>.zip exists, reuse it; otherwise create it.
        	downloadsz.zipT)r   NzZIP creation failed: )r   parentr   existsr0   _create_zip_asyncr,   )r   r&   r%   zip_pathr8   s        r   
create_zipzWebsiteService.create_zip   s      	>K((k+?+?+??HO!!4!000    %8}}$ ((x@@@@@@@@@x==  	> 	> 	><CFF<<===	>s   AB *B 
B0B++B0c                	  K   	 |                     dd          }t          |          }|rx|                     dd          }|                     dd          }|                     dd          }|r|st          d          |st          d          t          d	|           }|                                st          d
|           |dz  }|                                ryt          j        |dd          4 d{V }	|	                                 d{V }
ddd          d{V  n# 1 d{V swxY w Y   t          	                    d|            n4| j
                            |          }
t                              d           t          |
|          \  }}nkt          |          }d}t          |           d{V }|d         }t          |d                   }	 t!          ||           d{V  n# t          $ r Y nw xY wd}d}d}| j
                            |d| |          2 3 d{V }|                    d          sT|                    d          s?|                    d          s*|                    d          s|                    d          rd|dW V   dS ||z  }|s| j
                            |          }|rmt'          |          |k    rZt'          |          dk    rG||d         }ddl}|                                dz  }||z
  d k    rd!|d"W V  |}t'          |          }6 |r|}d#|v r||                    d#          d         }t-          j        |
|          \  }}}|sdd$| dW V  dS |                     |          \  }}|sdd%| dW V  dS |                     |          }|                     |          }|dz  }|                     ||           d{V  d!|d"W V  n| j
                            |          }|rr|                     |          \  }}|sdd&| dW V  dS |                     |          }|                     |          }|dz  }|                     ||           d{V  d'|sd(nd)|d*W V  dS # t          $ r#}dd+t9          |           dW V  Y d}~dS d}~ww xY w),z
        Generate website with streaming response for live preview.
        Supports both new generation and edit mode with SEARCH/REPLACE diffs.
        editModeForiginalHtmlr>   editInstructionsexistingFolderz4Edit mode requires originalHtml and editInstructionsz!Edit mode requires existingFolderztemplates/generated/zWebsite folder not found: r#   rutf-8encodingNzRead HTML from file: z3index.html not found, using frontend's originalHtmlr   r   r   r   )r   r    system_promptErrorzConnection lostzUnable to connectzRequest timed outzAI service errorerror)typemessaged   i  i  r!   )rY   chunkz<<<<<<< SEARCHzFailed to apply changes: zEdited HTML is incomplete: r"   completezWebsite generation complete!zChanges applied successfully!)rY   rZ   folderzStreaming generation failed: )r)   r   r,   r   rI   aiofilesopenreadloggerinfor   _extract_html_from_responsewarningr   r   r	   r
   generate_streaming_response
startswithlentimefindr   apply_diffsr+   r-   r.   r/   r0   )r   r   	edit_moder1   original_htmlinstructionsr%   r&   r7   fclean_original_htmledit_system_promptr2   r3   accumulated_contentlast_render_timelast_sent_indexr\   r$   new_partri   nowclean_content
final_htmlsuccessr6   r5   validation_errorr8   s                                r   generate_website_streamz&WebsiteService.generate_website_stream   s     
f	U33I ,D11L . $ < <#xx(:B??"hh'7<<$ \L \#$Z[[[" I#$GHHH  $$H;$H$HII#**,, P#$N$N$NOOO *L8
$$&& Z'}ZwOOO = = = = = = =ST45FFHHnnnnnn+= = = = = = = = = = = = = = = = = = = = = = = = = = =KK D
 D DEEEE +//*U*UVc*d*d'NN#XYYY 7II\^j6k6k3"OO
 #8"E"E%)" &4L%A%AAAAAAA*+=>#L1C$DEE*<FFFFFFFFFF    D #% O#JJ& 8; 8 80  K      D  D  D  D  D  D  De ##G,, 0@0@AR0S0S W\WgWgh{W|W|   AF  AQ  AQ  Re  Af  Af   jo  jz  jz  {M  jN  jN  '#(      FF#u,# ! D#'?#N#NOb#c#cL# DL(9(9O(K(K|,,s22'3O4D4D'EH (KKK"&))++"4C"%55<<,5-5'" '" !" !" !" !" 47 025l2C2CA F  ;I !4#':::$78K8P8PQa8b8b8c8c$dM1<1HI\^k1l1l.
GY  '#Jy#J#J      F .2-I-I*-U-U**  '#SAQ#S#S      F "AA*MM
!88DD
 *L8
,,ZDDDDDDDDD &'       "_HHI\]]
 I*.*F*Fz*R*R'Hi# $+'S	'S'S       "&!E!Ej!Q!QJ "&!<!<Z!H!HJ ".!<J00ZHHHHHHHHH #AJo99Po%         	 	 	C3q66CC           	s   C<R(  D-R( -
D77R( :D7;B,R( (G? >R( ?
H	R( H)R( 5M;A3R( 0CR( %R( 7BR( AR( (
S2SShtmlc                     |s|S t          j        dd|t           j                  }d|vr.d|                                v rt          j        dd|d	          }|S )
zReplace known external kit/script tags with safer CDN links.

        Currently converts Font Awesome kit scripts to the stable cdnjs stylesheet.
        z[<script[^>]*src=[\"']https?:\\/\\/kit\.fontawesome\.com\/[\w.-]+\.js[\"'][^>]*>\s*</script>r>   )flagsz+cdnjs.cloudflare.com/ajax/libs/font-awesomez<head>z(?i)(<head[^>]*>)zt\1\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css\">   )count)resub
IGNORECASElower)r   r|   s     r   r-   z.WebsiteService._sanitize_third_party_resources_  s    
  	K vtvxz~  GI  GT  U  U  U 9DD4::<<''v2  5l  nr  z{  |  |  |r   r$   c                    ddl } |j        t                    }r%t                                                    dk     r3d}|                    d| drt                    nd d           d|fS d	d                                         }|rY|                    d
          sDd|v r@d
||                    d          d         vr!d}|                    d| d|            d|fS g d}fd|D             }|r4dd                    |           }|                    d|            d|fS |	                    d           dS )z
        Validate that HTML content is complete and well-formed.
        
        Returns:
            tuple: (is_valid, error_message)
        r   Nr[   z"HTML content is too short or emptyzHTML validation failed: z
 (length: )Fi><z4HTML appears to be truncated (incomplete tag at end)z, last 100 chars: )z<htmlz</html>z<headz</head>z<body</body>c                 d    g | ],}|                                                                  v*|-S  )r   ).0tagr$   s     r   
<listcomp>z:WebsiteService._validate_html_complete.<locals>.<listcomp>  s7    ```		<K]K]K_K_8_8_8_8_8_r   zMissing required HTML tags: z, zHTML validation passed)Tr>   )
logging	getLogger__name__rh   striprX   endswithrindexjoinrc   )r   r$   r   rb   r6   last_100_charsrequired_tagsmissing_tagss    `      r   r+   z&WebsiteService._validate_html_completer  s    	""8,, 	$s<#5#5#7#7883>><ILLtItt^jIq\IZIZIZpqtttuuu)## &dee,2244 	(."9"9#">"> 	(n$$N>CXCXY\C]C]C^C^4_)_)_R	e	eeUceefffi'' UTT````}``` 	$Ptyy7N7NPPILL?I??@@@)##,---xr   c                 V    d|v r|S d}d|v r|                     d|dz             S ||z   S )zF
        Inject 'Powered by Eatance' footer into HTML content
        zPowered by EatanceaX  
<div
  style="position: fixed; bottom: 20px; left: 20px; z-index: 1000; background: rgba(0,0,0,0.7); color: white; padding: 8px 12px; border-radius: 4px; font-size: 12px; text-decoration: none;"
>
  <a
    href="https://eatanceapp.com/"
    target="_blank"
    style="color: white; text-decoration: none;"
    >Powered by Eatance</a
  >
</div>r   z
</body>)replace)r   r$   eatance_footers      r   r.   z%WebsiteService._inject_eatance_footer  sO    
  <//

 $$''	>K3OPPP.00r   	file_pathr!   Nc                    K   t          j        |dd          4 d{V }|                    |           d{V  ddd          d{V  dS # 1 d{V swxY w Y   dS )z%Write content to file asynchronously.wrS   rT   N)r_   r`   write)r   r   r!   ro   s       r   r/   z WebsiteService._write_file_async  s      =C'BBB 	# 	# 	# 	# 	# 	# 	#a'''"""""""""	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	#s   A
AAsource_pathrK   c                 t   K   fd}t          j                                        d|           d{V  dS )zCreate ZIP file asynchronously.c                  *   t          j        dt           j                  5 }                     d          D ]A}|                                r+|                              }|                     ||           B	 d d d            d S # 1 swxY w Y   d S )Nr   *)zipfileZipFileZIP_DEFLATEDrglobis_filerelative_tor   )zipfr   arcnamer   rK   s      r   _create_zipz5WebsiteService._create_zip_async.<locals>._create_zip  s    30DEE 7!,!2!23!7!7 7 7I ((** 7"+"7"7"D"D

9g66677 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7s   ABBBN)asyncioget_event_looprun_in_executor)r   r   rK   r   s    `` r   rJ   z WebsiteService._create_zip_async  s_      	7 	7 	7 	7 	7 	7 $&&66t[IIIIIIIIIIIr   )r   
__module____qualname__r   r   r0   r   r9   r*   r   rL   r{   r-   tupleboolr+   r.   r/   rJ   r   r   r   r   r      s       & & &
6D4S> 6Dd38n 6D 6D 6D 6DpDtCH~ D# D D D DL>T > > > > > >,k$sCx. k k k kZC C    &"C "E$)<L " " " "H13 13 1 1 1 16# # # # # # #

J4 
J4 
JD 
J 
J 
J 
J 
J 
Jr   r   )__doc__typingr   r   r   r   pathlibr   r   sysr   r_   r   r   rb   pathinsertr0   __file__rH   services.website_data_utilsr   r   r   r	   r
   services.ai_servicer   services.diff_servicer   r   r   r   r   <module>r      sq   
         				         



  		8	$	$ 33ttH~~,344 5 5 5 F  F  F  F  F  F  F  F  F  F  F  F  F  F ) ) ) ) ) ) - - - - - -hJ hJ hJ hJ hJ hJ hJ hJ hJ hJr   