"""Prisca AI Worker orchestration layer.

Safe-by-default: WordPress reads are allowed; WooCommerce writes create drafts only.
The module is intentionally provider-agnostic so an LLM/research provider can be
plugged in later without changing the business workflow.
"""
import os, json, time
from wordpress_connector import WordPressConnector

class PriscaAIWorker:
    def __init__(self, wp=None):
        self.wp = wp

    def wordpress_audit(self):
        wp = self.wp or WordPressConnector()
        audit = wp.audit()
        findings=[]
        health=audit.get('health',{})
        if not health.get('ok'): findings.append({'severity':'critical','area':'availability','message':'WordPress REST API health check failed.'})
        products=audit.get('products',{}).get('rows',[])
        if len(products) < 10: findings.append({'severity':'info','area':'catalog','message':f'WooCommerce currently exposes {len(products)} products; review destination/package coverage.'})
        for p in products:
            name=((p.get('name') or '') if isinstance(p,dict) else '').strip()
            desc=((p.get('description') or '') if isinstance(p,dict) else '').strip()
            short=((p.get('short_description') or '') if isinstance(p,dict) else '').strip()
            images=(p.get('images') or []) if isinstance(p,dict) else []
            if not desc: findings.append({'severity':'warning','area':'content','product':name,'message':'Product has no main description.'})
            if not images: findings.append({'severity':'warning','area':'media','product':name,'message':'Product has no featured/gallery image.'})
            if not short: findings.append({'severity':'info','area':'content','product':name,'message':'Product has no short description.'})
        audit['ai_findings']=findings
        audit['worker_version']='v1'
        audit['safe_mode']=True
        return audit

    def build_product_payload(self, package):
        """Map the normalized package contract into a WooCommerce draft payload."""
        required=('name','description')
        missing=[x for x in required if not str(package.get(x,'')).strip()]
        if missing: raise ValueError('Missing package fields: '+', '.join(missing))
        payload={
            'name':package['name'].strip(),
            'type':'simple',
            'status':'draft',
            'regular_price':str(package.get('regular_price') or package.get('price') or ''),
            'description':package['description'],
            'short_description':package.get('short_description',''),
            'sku':package.get('sku',''),
            'categories':package.get('categories',[]),
            'images':package.get('images',[]),
            'virtual':False,
            'downloadable':False,
        }
        # Preserve the existing Prisca content model through WooCommerce meta.
        meta=[]
        for key in ('detailed_itinerary','package_inclusions','package_exclusions','faqs','seo_title','seo_description','seo_focus_keyword','package_duration','destination','route','pricing_breakdown'):
            if key in package and package[key] is not None:
                val=package[key]
                if not isinstance(val,str): val=json.dumps(val,ensure_ascii=False)
                meta.append({'key':'_prisca_'+key,'value':val})
        if meta: payload['meta_data']=meta
        return payload

    def create_draft(self, package):
        payload=self.build_product_payload(package)
        wp = self.wp or WordPressConnector()
        status,data=wp.create_product_draft(payload)
        return {'ok':status in (200,201),'status':status,'product':data,'action':'draft_created','publish_blocked':True}

    def package_workflow(self, package):
        """Prepare a package for human approval; creates no WP record until create_draft is called."""
        return {
            'ok':True,
            'stage':'approval_required',
            'publish_allowed':False,
            'package':package,
            'checks':self._qa(package),
            'worker_version':'v1'
        }

    def _qa(self,p):
        checks=[]
        def add(name,ok,msg): checks.append({'check':name,'ok':bool(ok),'message':msg})
        add('name',bool(str(p.get('name','')).strip()),'Package title present.')
        add('description',bool(str(p.get('description','')).strip()),'Main description present.')
        add('itinerary',bool(p.get('detailed_itinerary')),'Day-wise itinerary present.')
        add('inclusions',bool(p.get('package_inclusions')),'Inclusions present.')
        add('exclusions',bool(p.get('package_exclusions')),'Exclusions present.')
        add('price',float(p.get('price') or p.get('regular_price') or 0)>0,'Selling price present.')
        add('images',bool(p.get('images')),'At least one image supplied.')
        return checks


class PackageGenerationEngine:
    """Deterministic package planner. It creates structured drafts from a destination
    brief; factual attraction/route validation must be supplied by a research provider
    before approval. It never publishes to WordPress.
    """
    DEFAULT_VARIANTS = [
        ('Budget Escape','Budget'),('Classic Highlights','Mid Budget'),('Romantic Getaway','Mid Budget'),
        ('Family Holiday','Mid Budget'),('Premium Escape','Luxury'),('Luxury Signature','Luxury'),
        ('Adventure Explorer','Mid Budget'),('Relax & Unwind','Mid Budget'),('Weekend Express','Budget'),
        ('Slow Travel','Mid Budget'),('Honeymoon Special','Luxury'),('Friends Getaway','Mid Budget'),
        ('Senior Friendly','Mid Budget'),('Nature & Scenic','Mid Budget'),('Culture & Heritage','Mid Budget'),
        ('Food & Local Life','Mid Budget'),('Photography Trail','Mid Budget'),('Wellness Escape','Luxury'),
        ('Festive Holiday','Mid Budget'),('Grand Family Vacation','Luxury')
    ]

    def __init__(self, pricing=None):
        self.pricing = pricing

    def generate(self, destination, nights=3, base_route=None, count=20, brief=None):
        destination=(destination or '').strip()
        if not destination: raise ValueError('destination is required')
        count=max(1,min(int(count or 20),50))
        nights=max(1,int(nights or 3))
        route=base_route or [destination]
        out=[]
        for i,(theme,segment) in enumerate(self.DEFAULT_VARIANTS[:count],1):
            duration=f'{nights} Nights / {nights+1} Days'
            title=f'{destination} {theme} | {duration}'
            itinerary=self._itinerary(destination,nights,route,theme)
            p={
                'name':title,
                'short_description':f'{duration} {destination} holiday focused on {theme.lower()}, with a practical day-wise plan and flexible hotel options.',
                'description':f'<h2>{destination} {theme}</h2><p>A {duration.lower()} package designed for {theme.lower()}. Final attractions, timings, route feasibility and supplier rates must be validated before approval.</p>',
                'destination':destination,
                'route':' → '.join(route),
                'package_duration':duration,
                'detailed_itinerary':itinerary,
                'package_inclusions':['Accommodation as selected','Transfers as per approved route','Sightseeing as listed in the final itinerary'],
                'package_exclusions':['Personal expenses','Items not explicitly listed in inclusions','Any attraction/activity fee not included in the approved costing'],
                'faqs':['Can this package be customized? Yes, subject to availability and revised costing.','Is the itinerary fixed? It is a planning draft until route and supplier validation is completed.'],
                'seo_title':f'{destination} {theme} Package | Prisca Holidays',
                'seo_description':f'Plan a {duration.lower()} {destination} holiday with a {theme.lower()} itinerary from Prisca Holidays.',
                'seo_focus_keyword':f'{destination} holiday package',
                'segment':segment,
                'variant_number':i,
                'research_status':'needs_validation',
                'qa_status':'draft',
                'pricing_status':'needs_supplier_costs',
                'brief':brief or {}
            }
            out.append(p)
        return {'ok':True,'destination':destination,'count':len(out),'research_required':True,'pricing_required':True,'publish_blocked':True,'packages':out,'generation_version':'v19'}

    def _itinerary(self,destination,nights,route,theme):
        days=[]
        for d in range(1,nights+2):
            if d==1:
                items=[f'Arrive in {destination} / designated starting point.', 'Transfer to the selected hotel or stay.', f'Check-in and begin the {theme.lower()} experience.']
                title=f'Arrival & {destination}'
            elif d==nights+1:
                items=['Breakfast and check-out.', 'Transfer to the approved departure point.', 'Tour ends.']
                title='Departure'
            else:
                items=[f'Breakfast at the selected stay.', f'Explore the approved {destination} sightseeing plan for the day.', 'Return to the hotel and evening at leisure.']
                title=f'{destination} Sightseeing – Day {d}'
            days.append({'day':d,'title':title,'items':items})
        return days
