import re
from fastapi import FastAPI,Header,HTTPException
from pydantic import BaseModel,Field
from app.config import settings
app=FastAPI(title='AI Restaurant Menu Service')
class Analyze(BaseModel):
 menu_item_id:int|None=None; name:str; description:str|None=None; price:float|None=None; category:str|None=None; photo_url:str|None=None
class Item(BaseModel):
 id:int; name:str; description:str|None=None; category:str|None=None; price:float; calories_min:int|None=None; calories_max:int|None=None; protein:float|None=None; ingredients:list[str]=[]; allergens:list[str]=[]; dietary_tags:list[str]=[]
class Search(BaseModel):
 restaurant_id:int; message:str=Field(min_length=1,max_length=600); items:list[Item]
def auth(authorization:str|None):
 if authorization!=f'Bearer {settings.ai_service_token}': raise HTTPException(401,'Invalid token')
def base(text):
 m={'salmon':(520,40,30,22),'chicken':(560,45,45,20),'beef':(650,42,40,32),'salad':(330,12,32,18),'pasta':(680,22,95,22),'sandwich':(620,28,66,26),'juice':(140,2,32,0),'cake':(480,6,65,22),'tofu':(410,24,42,16)}
 for k,v in m.items():
  if k in text:return k,v
 return '',(520,25,55,22)
@app.get('/health')
def health():return {'status':'ok'}
@app.post('/v1/menu/analyze')
def analyze(p:Analyze,authorization:str|None=Header(None)):
 auth(authorization);t=f'{p.name} {p.description or ""} {p.category or ""}'.lower();k,(c,pr,carb,fat)=base(t);s=max(50,round(c*.12));
 ingredients=[x for x in ['salmon','chicken','beef','tofu','rice','pasta','bread','lettuce','tomato','cheese','milk','butter','egg','nuts','lemon','vegetables','sauce'] if x in t]
 amap={'milk':'milk','butter':'milk','cheese':'milk','egg':'eggs','bread':'wheat','pasta':'wheat','salmon':'fish','shrimp':'shellfish','nuts':'tree nuts'};allergens=sorted({a for w,a in amap.items() if w in t});tags=[]
 if c<=500:tags.append('low calorie')
 if pr>=30:tags.append('high protein')
 if 'vegetarian' in t or 'tofu' in t:tags.append('vegetarian')
 return {'improved_description':(p.description or p.name).rstrip('.')+' — prepared as a flavorful restaurant-style selection.','calories_min':max(0,c-s),'calories_max':c+s,'protein':pr,'carbohydrates':carb,'fat':fat,'ingredients':ingredients or ([k] if k else []),'allergens':allergens,'dietary_tags':tags,'confidence':'medium' if p.description else 'low'}
@app.post('/v1/menu/search')
def search(p:Search,authorization:str|None=Header(None)):
 auth(authorization);q=p.message.lower();pm=re.search(r'(?:under|below|less than)\s*\$?\s*(\d+(?:\.\d+)?)',q);cm=re.search(r'(?:under|below|less than|max(?:imum)?)\s*(\d{2,4})\s*(?:cal|calories|kcal)',q);mxp=float(pm.group(1)) if pm else None;mxc=int(cm.group(1)) if cm else None;ex=re.findall(r'(?:without|no|exclude)\s+([a-z\- ]+?)(?:,|\.| and | under | below |$)',q);rows=[]
 for i in p.items:
  h=' '.join([i.name,i.description or '',i.category or '',' '.join(i.ingredients),' '.join(i.dietary_tags)]).lower()
  if mxp is not None and i.price>mxp:continue
  if mxc is not None and i.calories_max and i.calories_max>mxc:continue
  if any(x.strip() in h for x in ex):continue
  if 'vegetarian' in q and not any(x.lower() in {'vegetarian','vegan'} for x in i.dietary_tags):continue
  score=0
  if any(x in q for x in ['low calorie','light','diet']) and i.calories_max:score+=max(0,900-i.calories_max)/10
  if any(x in q for x in ['cheap','low price']) :score+=max(0,50-i.price)
  if 'high protein' in q and i.protein:score+=i.protein
  for w in ['salmon','beef','chicken','salad','sandwich','drink','dessert','spicy']:
   if w in q and w in h:score+=18
  rows.append((score,i))
 rows.sort(key=lambda x:x[0],reverse=True);sel=[i for _,i in rows[:4]];rec=[{'id':i.id,'name':i.name,'price':i.price,'reason':'This item best matches your request.'} for i in sel]
 return {'answer':f'I found {len(rec)} matching option(s).' if rec else 'I could not find an exact match.','recommended_item_ids':[x['id'] for x in rec],'recommendations':rec}
