from __future__ import annotations
import base64, html, os, textwrap, uuid
from pathlib import Path
import httpx

ROOT = Path(__file__).resolve().parents[2]
OUT = ROOT / 'data' / 'generated_images'
OUT.mkdir(parents=True, exist_ok=True)

STYLES = {
    'Cinematic': 'cinematic digital illustration, polished lighting, immersive, detailed',
    'Realistic': 'realistic digital portrait/illustration, natural lighting, detailed',
    'Anime': 'anime-inspired 2D illustration, expressive, clean linework',
    'Painterly': 'painterly digital illustration, soft brushwork, atmospheric',
    'Graphic': 'clean graphic illustration, strong silhouette, polished poster design',
}

def _mock_svg(prompt: str, aspect: str, style: str) -> str:
    dims={'1:1':(768,768),'4:5':(768,960),'16:9':(1024,576)}
    w,h=dims.get(aspect,(768,768))
    words=' '.join(prompt.split())[:380]
    lines=textwrap.wrap(words, 44)[:8]
    y=h*0.60
    text=''.join(f'<text x="{w/2}" y="{y+i*30}" text-anchor="middle" fill="#ebe7ff" font-size="18" font-family="Arial">{html.escape(line)}</text>' for i,line in enumerate(lines))
    svg=f'''<svg xmlns="http://www.w3.org/2000/svg" width="{w}" height="{h}" viewBox="0 0 {w} {h}"><defs><linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#151331"/><stop offset=".5" stop-color="#4338ca"/><stop offset="1" stop-color="#0b1736"/></linearGradient><radialGradient id="r"><stop stop-color="#c4b5fd" stop-opacity=".55"/><stop offset="1" stop-color="#312e81" stop-opacity="0"/></radialGradient></defs><rect width="100%" height="100%" rx="30" fill="url(#g)"/><circle cx="{w*.5}" cy="{h*.38}" r="{min(w,h)*.28}" fill="url(#r)"/><text x="{w/2}" y="{h*.18}" text-anchor="middle" fill="#fff" font-size="42" font-weight="700" font-family="Arial">MelumiyaChat 2D</text><text x="{w/2}" y="{h*.24}" text-anchor="middle" fill="#c4b5fd" font-size="22" font-family="Arial">{html.escape(style)} · Local Mock Preview</text>{text}<text x="{w/2}" y="{h-34}" text-anchor="middle" fill="#a5b4fc" font-size="15" font-family="Arial">Connect an image provider for real AI artwork</text></svg>'''
    name=f'img_{uuid.uuid4().hex}.svg'; (OUT/name).write_text(svg,encoding='utf-8'); return f'/generated-images/{name}'

def generate(prompt: str, style: str='Cinematic', aspect: str='1:1', target: str='character') -> dict:
    style_text=STYLES.get(style, style)
    framing={'persona':'single-person avatar portrait, shoulders/head visible','character':'character portrait, clear face and silhouette','scenario':'story scenario cover art, environment and mood, no text'}.get(target,'2D illustration')
    final=f'{framing}. {style_text}. {prompt}. No text, no watermark.'
    base=os.getenv('IMAGE_API_BASE','').strip().rstrip('/')
    key=os.getenv('IMAGE_API_KEY','').strip(); model=os.getenv('IMAGE_API_MODEL','').strip()
    if not (base and key and model):
        return {'url':_mock_svg(final,aspect,style),'mode':'mock','prompt':final,'plain':'Offline/development preview only. Normal signed-in use generates artwork through the MelumiyaChat cloud service.'}
    size={'1:1':'1024x1024','4:5':'1024x1280','16:9':'1536x1024'}.get(aspect,'1024x1024')
    try:
        with httpx.Client(timeout=120) as client:
            r=client.post(f'{base}/images/generations',headers={'Authorization':f'Bearer {key}','Content-Type':'application/json'},json={'model':model,'prompt':final,'size':size,'n':1})
            r.raise_for_status(); data=r.json(); item=(data.get('data') or [{}])[0]
            if item.get('url'): return {'url':item['url'],'mode':'provider','prompt':final,'plain':'Image generated.'}
            b64=item.get('b64_json') or item.get('base64')
            if b64:
                raw=base64.b64decode(b64); name=f'img_{uuid.uuid4().hex}.png'; (OUT/name).write_bytes(raw)
                return {'url':f'/generated-images/{name}','mode':'provider','prompt':final,'plain':'Image generated.'}
            raise RuntimeError('Image provider returned no image URL/data.')
    except Exception as e:
        return {'url':_mock_svg(final,aspect,style),'mode':'fallback','prompt':final,'plain':f'Offline/development image provider failed ({e}). Showing a local preview instead.'}
