# This file is part of Tryton.  The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms. 
from trytond.model import ModelSQL, ModelView, fields, sequence_ordered, ModelSingleton
from trytond.pyson import Eval
from trytond.transaction import Transaction
from trytond.pool import Pool, PoolMeta
from trytond.wizard import Button, StateTransition, StateView, Wizard, StateAction
from decimal import getcontext, Decimal, ROUND_HALF_UP
import jwt
import datetime
import logging
from trytond.exceptions import UserWarning, UserError
import json
import shlex
from datetime import date

logger = logging.getLogger(__name__)

keywords = ["duplicate", "create", "add", "invoice", "reception", "pay", "delivery", "match"]

class DashboardLoader(Wizard):
    'Load Dashboard'
    __name__ = 'purchase.dashboard.loader'

    start = StateAction('purchase_trade.act_dashboard_form')

    def do_start(self, action):
        pool = Pool()
        Dashboard = pool.get('purchase.dashboard')
        user_id = Transaction().user
        if user_id == 0:
            user_id = Transaction().context.get('user', user_id)
        dashboard = Dashboard.search([('user_id', '=', user_id)])
        if not dashboard:
            dashboard, = Dashboard.create([{'user_id': user_id}])
        else:
            dashboard = dashboard[0]
        action['views'].reverse()
        return action, {'res_id': [dashboard.id]}

class DashboardContext(ModelView):
    "Dashboard context"
    __name__ = 'dashboard.context'
    user = fields.Many2One('res.user', 'User')
    company = fields.Many2One('company.company', 'Company', required=True)
    
    @staticmethod
    def default_company():
        return Transaction().context.get('company')

    @staticmethod
    def default_user():
        user_id = Transaction().user
        if user_id == 0:
            user_id = Transaction().context.get('user', user_id)
        return user_id

class Demos(ModelSQL, ModelView):
    'Demos'
    __name__ = 'demos.demos'

    title = fields.Char('Title', required=True)
    category = fields.Char('Category')
    icon = fields.Char('Icon')  # exemple: "🚢" ou "📝"
    active = fields.Boolean('Active')
    video_file = fields.Char('File')
    description = fields.Text('Description')

class News(ModelSQL, ModelView):
    'News'
    __name__ = 'news.news'

    title = fields.Char('Title', required=True)
    category = fields.Char('Category')
    icon = fields.Char('Icon')  # exemple: "🚢" ou "📝"
    active = fields.Boolean('Active')
    publish_date = fields.Date('Publish Date')
    model = fields.Char('Model')      # ex: 'purchase.purchase'
    model_id = fields.Integer('Record ID')

class Dashboard(ModelSQL, ModelView):
    "Dashbot"
    __name__ = "purchase.dashboard"
    
    stock = fields.One2Many('lot.lot','dashboard',"STOCK")
    stock2 = fields.One2Many('lot.lot','dashboard',"PRODUCT")
    stock3 = fields.One2Many('lot.lot','dashboard',"CURVE")
    transit = fields.One2Many('stock.shipment.in','dashboard',"VESSEL IN TRANSIT")
    document = fields.One2Many('document.incoming','dashboard',"Documents received")
    html_content = fields.Function(fields.Text('HTML Content'),'get_news')
    demos = fields.Function(fields.Text('Demos'),'get_demos')
    #metabase = fields.Function(fields.Text("",states={'invisible': ~Eval('metabase',False)}),'gen_url')
    metabase = fields.Text("",states={'invisible': ~Eval('metabase',False)})
    chatbot = fields.Text("")
    input = fields.Text("")
    bi_id = fields.Integer("")
    user = fields.Function(fields.Char(""), 'get_user')
    fake = fields.Char("",readonly=True)
    res_id = fields.Integer("Res id")
    action_return = fields.Char("Action return")
    actions = fields.One2Many('bot.action','dashboard',"Actions")
    user_request = fields.Char("User request")
    user_id = fields.Many2One('res.user',"User")
    tremor = fields.Function(fields.Text(""),'get_tremor')

    @classmethod
    def default_bi_id(cls):
        return 38

    @classmethod
    def default_res_id(cls):
        return 0

    @fields.depends('input')
    def on_change_input(self):
        logger.info("ENTERONCHANGE",self.input)
        Lot = Pool().get('lot.lot')
        self.metabase = None
        if self.input is None:
            self.chatbot = 'chatbot:' + json.dumps([{"type": "bot", "content": "🧠 Hi Admin, how can I help you?"}], ensure_ascii=False)
        else:
            dial = json.loads(self.input)
            last_content = dial[-1]["content"]
            last_type = dial[-1]["type"]
            logger.info("ON_CHANGE_INPUT:%s",last_content)
            message = ''
            if "display" in last_content.lower() and "clients" in last_content.lower():
                dial.append({"type": "bot", "content": "Clients displayed below"})
                if self.bi_id != 7:
                    self.bi_id = 7
                    self.metabase = self.gen_url()
            elif "display" in last_content.lower() and "sales" in last_content.lower():
                dial.append({"type": "bot", "content": "Sales displayed below"})
                if self.bi_id != 41:
                    self.bi_id = 41
                    self.metabase = self.gen_url()
            elif "display" in last_content.lower() and "products" in last_content.lower():
                dial.append({"type": "bot", "content": "Products displayed below"})
                if self.bi_id != 38:
                    self.bi_id = 38
                    self.metabase = self.gen_url()
            elif "open" in last_content.lower() and "shipment" in last_content.lower():
                sh = self.FindInContent('shipment',last_content)
                if sh:
                    dial.append({"type": "bot", "content": "Ok shipment opened in new tab"})
                    dial.append({"type": "do", "content": "open,stock.shipment.in," + str(sh.id) + ",0"})
                else:
                    dial.append({"type": "bot", "content": "No shipment found"})
            elif "where" in last_content.lower() and "vessel" in last_content.lower():
                sh = self.FindInContent('shipment',last_content)
                if sh:
                    dial.append({"type": "bot", "content": "Look at the map below"})
                    self.metabase = f"imo:{sh.vessel.vessel_imo}"
            elif "graph" in last_content.lower() and "lot" in last_content.lower():
                g,l,i = last_content.split()
                lot = Lot(i)
                if lot:
                    dial.append({"type": "bot", "content": "Graph displayed below"})
                    self.metabase = lot.get_flow_graph()
            elif "pivot" in last_content.lower() and "lot" in last_content.lower():
                g,l,i = last_content.split()
                lot = Lot(i)
                if lot:
                    dial.append({"type": "bot", "content": "Pivot displayed below"})
                    self.metabase = lot.get_pivot()
            elif "display" in last_content.lower() and "map" in last_content.lower():
                dial.append({"type": "bot", "content": "Map displayed below"})
                self.metabase = self.get_map()
            elif any(k in last_content.lower() for k in keywords):
                logger.info("ACTION_RETURN:%s",self.action_return)
                if "help" in last_content.lower():
                    if "duplicate" in last_content.lower():
                        dial.append({"type": "bot", "content": "duplicate [purchase/sale]* [party]* [qt]* [plan] [period] [price]"})
                elif self.action_return:
                    model,res_id, res_nb = self.action_return.split(",")
                    z,keyword = model.split(".")
                    message = {
                        "type": "bot",
                        "content": (
                            f'Action done. '
                            f'<a href="#" class="tryton-link" data-model="{model}" '
                            f'data-id="{res_id}" data-view="form">Open {keyword} {res_nb}</a>'
                        )
                    }
                    dial.append(message)
                else:
                    if "match" in last_content.lower():
                        dial.append({"type": "bot", "content": "Matching done"})
                    else:  
                        dial.append({"type": "bot", "content": "Not done"})
            else:
                dial.append({"type": "bot", "content": "Ok done"})
            self.chatbot = 'chatbot:' + json.dumps(dial, ensure_ascii=False)
        logger.info("EXITONCHANGE",self.chatbot)

    @staticmethod
    def _empty_fx_rates():
        return (None, None, None, None, None, None, None, None, None, None)

    @classmethod
    def _find_currency_by_code(cls, code):
        Currency = Pool().get('currency.currency')
        currencies = Currency.search([('name', '=', code)], limit=1)
        if not currencies:
            currencies = Currency.search([('code', '=', code)], limit=1)
        return currencies[0] if currencies else None

    def get_last_five_fx_rates(self, from_code='USD', to_code='EUR'):
        """
        Retourne (dernier_taux, avant_dernier_taux) pour le couple de devises.
        """
        CurrencyRate = Pool().get('currency.currency.rate')

        # Récupérer les devises EUR et USD
        from_currency = self._find_currency_by_code(from_code)
        to_currency = self._find_currency_by_code(to_code)
        if not from_currency or not to_currency:
            return self._empty_fx_rates()

        # Recherche des taux de la devise de base (ex: USD)
        rates = CurrencyRate.search(
            [('currency', '=', to_currency.id)],
            order=[('date', 'DESC')],
            limit=5,
        )

        if not rates:
            return self._empty_fx_rates()

        # Calcul du taux EUR/USD
        # Si la devise principale de la société est EUR, et que le taux stocké est
        # "1 USD = X EUR", on veut l'inverse pour avoir EUR/USD
        f1 = rates[0].rate
        f2 = rates[1].rate if len(rates) > 1 else None
        f3 = rates[2].rate if len(rates) > 2 else None
        f4 = rates[3].rate if len(rates) > 3 else None
        f5 = rates[4].rate if len(rates) > 4 else None
        d1 = rates[0].date
        d2 = rates[1].date if len(rates) > 1 else None
        d3 = rates[2].date if len(rates) > 2 else None
        d4 = rates[3].date if len(rates) > 3 else None
        d5 = rates[4].date if len(rates) > 4 else None

        # if from_currency != to_currency:
        #     last_rate = 1 / last_rate if last_rate else None
        #     prev_rate = 1 / prev_rate if prev_rate else None

        return (
            round(1/f1,6) if f1 else None,
            round(1/f2,6) if f2 else None,
            round(1/f3,6) if f3 else None,
            round(1/f4,6) if f4 else None,
            round(1/f5,6) if f5 else None,
            d1, d2, d3, d4, d5)

    def get_tremor(self,name):
        Date = Pool().get('ir.date')
        Configuration = Pool().get('gr.configuration')
        config = Configuration.search(['id','>',0])[0]
        Shipment = Pool().get('stock.shipment.in')
        DocumentIncoming = Pool().get('document.incoming')
        Fee = Pool().get('fee.fee')
        WR = Pool().get('weight.report')
        if config.automation:
            shipment = Shipment.search([('state','!=','received')])
            shipment_trend = [sh for sh in shipment if sh.create_date == Date.today()]
            controller = Shipment.search([('controller','!=',None)])
            controller_trend = [co for co in controller if co.create_date == Date.today()]
            instruction = Shipment.search([('result','!=',None)])
            instruction_trend = [si for si in instruction if si.create_date == Date.today()]
            id_received = Shipment.search([('returned_id','!=',None)])
            id_received_trend = [i for i in id_received if i.create_date == Date.today()]
            wr = WR.search([('id','>',0)])
            wr_trend = [w for w in wr if w.create_date == Date.today()]
            so = Fee.search(['id','=',25])
            so_trend = [s for s in so if s.create_date == Date.today()]
            di = DocumentIncoming.search(['id','>',0])
            di_trend = [d for d in di if d.create_date == Date.today()]
            return (
            config.dashboard + 
            "/dashboard/index.html?shipment="
            + str(len(shipment))
            + "&shipment_trend="
            + str(len(shipment_trend))
            + "&controller="
            + str(len(controller))
            + "&controller_trend="
            + str(len(controller_trend))
            + "&instruction="
            + str(len(instruction))
            + "&instruction_trend="
            + str(len(instruction_trend))
            + "&wr="
            + str(len(wr))
            + "&wr_trend="
            + str(len(wr_trend))
            + "&so="
            + str(len(so))
            + "&so_trend="
            + str(len(so_trend))
            + "&di="
            + str(len(di))
            + "&di_trend="
            + str(len(di_trend))
            + "&id_received="
            + str(len(id_received))
            + "&id_received_trend="
            + str(len(id_received_trend)))
        
        f1,f2,f3,f4,f5,d1,d2,d3,d4,d5 = self.get_last_five_fx_rates()
        Valuation = Pool().get('valuation.valuation')
        last_total,last_variation = Valuation.get_totals()
        pnl_amount = "{:,.0f}".format(round(last_total,0))
        pnl_variation = 0
        if last_total and last_variation:
            pnl_variation = "{:,.2f}".format(round((last_variation/last_total)*100,0))
        Open = Pool().get('open.position')
        opens = Open.search(['id','>',0])
        exposure = "{:,.0f}".format(round(sum([e.net_exposure for e in opens]),0))
        ToPay = Pool().get('account.invoice')
        topays = ToPay.search(['type','=','in'])
        amounts = ToPay.get_amount_to_pay(topays)
        total = sum(amounts.values(), Decimal(0))
        topay = "{:,.0f}".format(round(total,0))
        ToReceive = Pool().get('account.invoice')
        toreceives = ToReceive.search(['type','=','out'])
        amounts = ToPay.get_amount_to_pay(toreceives)
        total = sum(amounts.values(), Decimal(0))
        toreceive = "{:,.0f}".format(round(total,0))
        Purchase = Pool().get('purchase.purchase')
        draft = Purchase.search(['state','=','draft'])
        draft_p = len(draft)
        val = Purchase.search(['state','=','quotation'])
        val_p = len(val)
        conf = Purchase.search(['state','=','confirmed'])
        conf_p = len(conf)
        Sale = Pool().get('sale.sale')
        draft = Sale.search(['state','=','draft'])
        draft_s = len(draft)
        val = Sale.search(['state','=','quotation'])
        val_s = len(val)
        conf = Sale.search(['state','=','confirmed'])
        conf_s = len(conf)
        
        draft = Shipment.search(['state','=','draft'])
        shipment_d = len(draft)
        val = Shipment.search(['state','=','started'])
        shipment_s = len(val)
        conf = Shipment.search(['state','=','received'])
        shipment_r = len(conf)
        Lot = Pool().get('lot.lot')
        lots = Lot.search([('sale_line','!=',None),('line','!=',None),('lot_type','=','physic')])
        lot_m = len(lots)
        val = Lot.search([('sale_line','=',None),('line','!=',None),('lot_type','=','physic')])
        lot_a = len(val)
        Invoice = Pool().get('account.invoice')
        invs = Invoice.search(['type','=','in'])
        inv_p = len(invs)
        invs = Invoice.search([('type','=','in'),('state','=','paid')])
        inv_p_p = len(invs)
        invs = Invoice.search([('type','=','in'),('state','!=','paid')])
        inv_p_np = len(invs)
        invs = Invoice.search(['type','=','out'])
        inv_s = len(invs)
        invs = Invoice.search([('type','=','out'),('state','=','paid')])
        inv_s_p = len(invs)
        invs = Invoice.search([('type','=','out'),('state','!=','paid')])
        inv_s_np = len(invs)
        AccountMove = Pool().get('account.move')
        accs = AccountMove.search([('journal','=',3),('state','!=','posted')])
        pay_val = len(accs)
        accs = AccountMove.search([('journal','=',3),('state','=','posted')])
        pay_posted = len(accs)
        
        return (
            config.dashboard + 
            "/dashboard/index.html?pnl_amount="
            + str(pnl_amount)
            + "&pnl_variation="
            + str(pnl_variation)
            + "&exposure="
            + str(exposure)
            + "&topay="
            + str(topay)
            + "&toreceive="
            + str(toreceive)
            + "&eurusd="
            + str(f1)
            + "&eurusd="
            + str(f2)
            + "&eurusd="
            + str(f3)
            + "&eurusd="
            + str(f4)
            + "&eurusd="
            + str(f5)
            + "&eurusd_date="
            + str(d1)
            + "&eurusd_date="
            + str(d2)
            + "&eurusd_date="
            + str(d3)
            + "&eurusd_date="
            + str(d4)
            + "&eurusd_date="
            + str(d5)
            + "&draft_p="
            + str(draft_p)
            + "&val_p="
            + str(val_p)
            + "&conf_p="
            + str(conf_p)
            + "&draft_s="
            + str(draft_s)
            + "&val_s="
            + str(val_s)
            + "&conf_s="
            + str(conf_s)
            + "&shipment_d="
            + str(shipment_d)
            + "&shipment_s="
            + str(shipment_s)
            + "&shipment_r="
            + str(shipment_r)
            + "&lot_m="
            + str(lot_m)
            + "&lot_a="
            + str(lot_a)
            + "&inv_p="
            + str(inv_p)
            + "&inv_p_p="
            + str(inv_p_p)
            + "&inv_p_np="
            + str(inv_p_np)
            + "&inv_s="
            + str(inv_s)
            + "&inv_s_p="
            + str(inv_s_p)
            + "&inv_s_np="
            + str(inv_s_np)
            + "&pay_val="
            + str(pay_val)
            + "&pay_posted="
            + str(pay_posted)
        )

    
    def get_news(self, name):
        News = Pool().get('news.news')
        Date = Pool().get('ir.date')
        news_list = News.search([('active', '=', True)], limit=5, order=[('publish_date', 'DESC')])
        last_rate, prev_rate = self.get_last_five_fx_rates()[:2]
        if last_rate and prev_rate:
            variation = ((last_rate - prev_rate) / prev_rate) * 100 if prev_rate else 0
            direction = "📈" if variation > 0 else "📉"

            # 🆕 Création d’une “fake news” locale
            forex_news = News()
            forex_news.icon = direction
            forex_news.category = "Forex"
            # Détermine la direction et le style couleur
            if variation > 0:
                arrow = "⬆️"
                color = "#28a745"  # vert
            elif variation < 0:
                arrow = "⬇️"
                color = "#dc3545"  # rouge
            else:
                arrow = "➡️"
                color = "#6c757d"  # gris neutre
            
            # Contenu HTML enrichi
            forex_news.title = (
                f"EUR/USD: {last_rate:.4f}"
                f"<span style='color:{color}; font-weight:bold;'>"
                f"   {variation:+.2f}%"
                f"</span> "
            )

            forex_news.publish_date = Date.today()
            forex_news.model = 'currency.currency'       # par exemple 'forex.forex'
            forex_news.model_id = 2
            forex_news.active = True

            # On insère la “news” au début de la liste
            news_list.insert(0, forex_news)
        html_parts = [
            '<div class="last-news">',
            '  <div class="last-news-title">Last news</div>'
        ]

        for n in news_list:
            icon = n.icon or "📰"
            category = n.category or "General"
            title = n.title or ""
            # content = (n.content or "").replace('\n', '<br/>') <div class="last-news-content">{content}</div>
            publish_date = n.publish_date.strftime('%d-%m-%Y') if n.publish_date else ""

            # Génération du lien Tryton
            if n.model and n.model_id:
                # 🆕 lien JS pour ouvrir un tab interne Tryton
                js_link = (
                    f"javascript:Sao.Tab.create({{"
                    f"model: '{n.model}', "
                    f"res_id: {n.model_id}, "
                    f"mode: ['form'], "
                    f"target: 'new'"
                    f"}});"
                )
                title_html = (
                    f'<a href="{js_link}" style="text-decoration:none; color:#2a5db0;">'
                    f'{title}</a>'
                )
            else:
                title_html = f'<span>{title}</span>'

            html_parts.append(f'''
              <div class="last-news-item" style="margin-bottom: 8px;">
                <div class="last-news-category">{icon} {category}</div>
                <div class="last-news-header" style="display:flex; justify-content:space-between; align-items:center;">
                  <div class="last-news-title-item"><strong>{title_html}</strong></div>
                  <div class="last-news-date" style="color:#666; font-size:0.9em;">{publish_date}</div>
                </div>
              </div>
            ''')

        html_parts.append('</div>')
        return "\n".join(html_parts)
    
    def get_demos(self, name):
        Demos = Pool().get('demos.demos')
        html_parts = [
            '<div class="demos" style="background-color:#f5f5f5; padding:12px; border-radius:12px;>',
            '  <div class="demos-title" style="font-size:1.2em; font-weight:bold; margin-bottom:10px;">🎬 Available Demo</div>'
        ]

        demos = Demos.search([('active', '=', True)],order=[('id', 'DESC')])
        for n in demos:
            icon = n.icon or "📰"
            category = n.category or "General"
            title = n.title or "Sans titre"
            description = n.description or ""
            # suppose que n.video_path contient un chemin du type '/videos/demo1.mp4'
            video_url = f"/videos/{n.video_file}" if getattr(n, 'video_file', None) else None

            # lien vers le lecteur vidéo du navigateur
            video_link = (
                f'<a href="{video_url}" target="_blank" '
                'style="color:#007bff; text-decoration:none;">Play the video 🎥</a>'
                if video_url else
                '<span style="color:gray;">No available video</span>'
            )

            html_parts.append(f'''
            <div class="demo-item" style="margin-bottom: 12px; border-bottom:1px solid #eee; padding-bottom:8px;">
                <div class="demo-category" style="font-size:0.9em; color:#666;">{icon} {category}</div>
                <div class="demo-header" style="display:flex; justify-content:space-between; align-items:center;">
                <div class="demo-title" style="font-weight:bold;">{title}</div>
                <div class="demo-link">{video_link}</div>
                </div>
                <div class="demo-description" style="font-size:0.85em; color:#555;">{description}</div>
            </div>
            ''')

        html_parts.append('</div>')
        return "\n".join(html_parts)

    def get_map(self):
        departure = { "name":"SANTOS","lat": str(-23.9), "lon": str(-46.3) }
        arrival = { "name":"ISTANBUL","lat": str(41), "lon": str(29) }
        data = {
            "highlightedCountryNames": [{"name":"Turkey"},{"name":"Brazil"}],
            "routes": [[
                { "lon": -46.3, "lat": -23.9 },
                { "lon": -30.0, "lat": -20.0 },
                { "lon": -30.0, "lat": 0.0 },
                { "lon": -6.0,  "lat": 35.9 },
                { "lon": 15.0,  "lat": 38.0 },
                { "lon": 29.0,  "lat": 41.0 }
                ]],
            "boats": [{
                "name": "CARIBBEAN 1",
                "imo": "1234567",
                "lon": -30.0,
                "lat": 0.0,
                "status": "En route",
                "links": [
                    { "text": "Voir sur VesselFinder", "url": "https://www.vesselfinder.com" },
                    { "text": "Détails techniques", "url": "https://example.com/tech" }
                ],
                "actions": [
                    { "type": "track", "id": "123", "label": "Suivre ce bateau" },
                    { "type": "details", "id": "123", "label": "Voir détails" }
                ]
            }],
            "cottonStocks": [
                { "name":"Mali","lat": 12.65, "lon": -8.0, "amount": 300 },
                { "name":"Egypte","lat": 30.05, "lon": 31.25, "amount": 500 },
                { "name":"Irak","lat": 33.0,  "lon": 44.0,  "amount": 150 }
            ],
            "departures": [departure],
            "arrivals": [arrival]
        }

        return "d3:" + json.dumps(data)
        
    def FindInContent(self,what,content):
        if what == 'shipment':
            Shipment = Pool().get('stock.shipment.in')
            shipments = Shipment.search([('id','>',0),('vessel','!=',None)],order=[('create_date', 'DESC')])
            if shipments:
                for sh in shipments:
                    if sh.vessel.vessel_name.lower() in content.lower():
                        return sh
        elif what == 'purchase':
            Purchase = Pool().get('purchase.purchase')
            purchases = Purchase.search([('id','>',0)],order=[('create_date', 'DESC')])
            if purchases:
                for pu in purchases:
                    if pu.party.name.lower() in content.lower():
                        return pu

    def gen_url(self,name=None):
        Configuration = Pool().get('gr.configuration')
        config = Configuration.search(['id','>',0])[0]
        payload = {
            "resource": {"dashboard": self.bi_id},
            "params": {},
            "exp": datetime.datetime.utcnow() + datetime.timedelta(minutes=30),
        }
        token = jwt.encode(payload, config.payload, algorithm="HS256")
        logger.info("TOKEN:%s",token)
        return f"metabase:http://vps107.geneva.hosting:3000/embed/dashboard/{token}#bordered=true&titled=true"
    
    # @fields.depends('input')
    # def on_change_with_metabase(self):
    #     return self.gen_url()

    # @classmethod
    # def default_html_content(cls):
    #     return 'http://62.72.36.116:3000/question/41-sales-by-clients-and-suppliers'

    def get_user(self,name):
        User = Pool().get('res.user')
        user = User(Transaction().user)
        return "Welcome " + user.name + " !"    

class Incoming(metaclass=PoolMeta):
    __name__ = 'document.incoming'

    dashboard = fields.Many2One('purchase.dashboard',"Dashboard")

class BotWizard(Wizard):
    "Bot wizard"
    __name__ = "bot.wizard"

    start = StateTransition()
    
    def get_model(self,keyword):
        if keyword == 'purchase':
            return 'purchase.purchase'
        elif keyword == 'sale':
            return 'sale.sale'
        elif 'prepayment' in keyword:
            return 'account.invoice'

    def transition_start(self):
        Dashboard = Pool().get('purchase.dashboard')
        Party = Pool().get('party.party')
        Account = Pool().get('account.account')
        Currency = Pool().get('currency.currency')
        Purchase = Pool().get('purchase.purchase')
        Sale = Pool().get('sale.sale')
        Invoice = Pool().get('account.invoice')
        InvoiceLine = Pool().get('account.invoice.line')
        StockMove = Pool().get('stock.move')
        ExecutionPlan = Pool().get('workflow.plan')
        DelPeriod = Pool().get('product.month')
        Lot = Pool().get('lot.lot')
        LotQt = Pool().get('lot.qt')
        LotAdd = Pool().get('lot.add.line')
        Date = Pool().get('ir.date')
        d = Dashboard(self.records[0])
        context = Transaction().context
        if d:
            d.action_return = ""
            Dashboard.save([d])
            parts = shlex.split(context['user_request'])
            do_, mo, cp, fl, un, un2, un3 = (parts + [None]*7)[:7]
            if do_ in keywords:
                logger.info("BOT_WIZARD:%s",fl)
                parties = Party.search(['id','>',0])
                party = None
                model = self.get_model(mo)
                if cp:
                    for p in parties:
                        if cp.lower() == p.name.lower():
                            party = p
                            break
                if do_ == "duplicate":
                    if mo == "help":
                        return 'end'
                    if mo == "purchase" or mo == "sale":
                        if party:
                            Model = Pool().get(model)
                            if fl:
                                line_price = None
                                line_period = None
                                if un:
                                    plan = ExecutionPlan.search(['name','=', un])
                                    if plan:
                                        models = Model.search([('party','=',party.id),('plan','=',plan[0].id)],order=[('create_date', 'DESC')])
                                        if un3:
                                            line_price = Decimal(un3)
                                            line_period = DelPeriod.search(['month_name','=',un2])[0]
                                        else:
                                            if un2.isdigit():
                                                line_price = Decimal(un2)
                                    else:
                                        periods = DelPeriod.search(['month_name','=',un])
                                        if periods:
                                            line_period = periods[0]
                                            if un2.isdigit():
                                                line_price = Decimal(un2)
                                        else:
                                            if un.isdigit():
                                                line_price = Decimal(un)
                                else:
                                    models = Model.search([('party','=',party.id)],order=[('create_date', 'DESC')])
                                if models:
                                    model_id = models[0].id
                                    new_model, = Model.copy([model_id], default={})
                                    Model.save([new_model])
                                    Model.quote([new_model])
                                    logger.info("BOT_WIZARD:%s",new_model.lines)
                                    if new_model.lines and fl:
                                        line = new_model.lines[0]
                                        line.quantity = Decimal(fl)
                                        line.quantity_theorical = Decimal(fl)
                                        line.premium = Decimal(0)
                                        if line_period:
                                            line.del_period = line_period
                                        if line_price:
                                            if line.linked_price > 0:
                                                line.linked_price = line_price
                                                line.unit_price = line.get_price_linked_currency()
                                            else:
                                                line.unit_price = line_price
                                        Pool().get(mo + '.line').save([line])
                                    d.action_return = model + ',' + str(new_model.id) + ',' + str(new_model.number)
                                    Dashboard.save([d])
                elif do_ == "match":
                    Lml = Pool().get('lot.matching.lot')
                    lmp = Lml()
                    lms = Lml()
                    p = Purchase.search(['number','=',mo])
                    if p:
                        p = p[0]
                        s = Sale.search(['number','=',cp])
                        if s:
                            s = s[0]
                            lp = p.lines[0].lots[1]
                            lmp.lot_id = lp.id
                            lqt = lp.getLotQt()
                            lmp.lot_r_id = lqt[0].id if lqt else None 
                            lmp.lot_matched_qt = lp.lot_quantity
                            ls = s.lines[0].lots[0]
                            lms.lot_r_id = ls.getLotQt()[0].id
                            lms.lot_matched_qt = lp.lot_quantity
                            lms.lot_sale = s
                            Lot = Pool().get('lot.lot')
                            with Lot.skip_quantity_consistency():
                                LotQt.match_lots([lmp],[lms])
                            Lot.assert_lines_quantity_consistency(
                                [p.lines[0], s.lines[0]])
                            Sale._process_shipment([s])

                elif do_ == "add":
                    if mo == "lot":
                        purchase = Purchase.search([('number','=',cp)])
                        if purchase:
                            purchase = purchase[0]
                            vlot = purchase.lines[0].lots[0]
                            lqt = LotQt.search([('lot_p','=',vlot.id)])
                            if lqt and vlot.lot_quantity > 0:
                                lqt = lqt[0]
                                l = LotAdd()
                                l.lot_qt = vlot.lot_quantity
                                l.lot_unit = purchase.lines[0].unit
                                l.lot_unit_line = l.lot_unit
                                l.lot_quantity = l.lot_qt
                                l.lot_gross_quantity = l.lot_qt
                                l.lot_premium = Decimal(0)
                                l.lot_chunk_key = None
                                lot_id = LotQt.add_physical_lots(lqt,[l])
                                d.action_return = 'lot.lot,' + str(lot_id) + ',' + str(lot_id)
                                Dashboard.save([d])
                elif do_ == "reception":
                    if mo == "lot":
                        lot = Lot(int(cp))
                        if lot.lot_move:
                            StockMove.do([lot.lot_move[0].move])
                            d.action_return = 'stock.move,' + str(lot.lot_move[0].move.id) + ',' + str(lot.lot_move[0].move.id)
                            Dashboard.save([d])
                elif do_ == "delivery":
                    if mo == "lot":
                        lot = Lot(int(cp))
                        if lot.lot_move:
                            StockMove.do([lot.lot_move[1].move])
                            d.action_return = 'stock.move,' + str(lot.lot_move[1].move.id) + ',' + str(lot.lot_move[1].move.id)
                            Dashboard.save([d])
                elif do_ == "invoice":
                    if mo == "lot":
                        lot = Lot(int(cp))
                        Purchase._process_invoice([lot.line.purchase],[lot],'prov')
                        if lot.invoice_line_prov:
                            invoice = Invoice(lot.invoice_line_prov.invoice.id)
                            invoice.invoice_date = Date.today()
                            if fl == "prepayment":
                                if un:
                                    invoice.call_deposit(Account(748),un)
                                else:
                                    invoice.call_deposit(Account(748),'Deposit')
                            Invoice.validate_invoice([invoice])
                            d.action_return = 'account.invoice,' + str(lot.invoice_line_prov.invoice.id) + ',' + str(lot.invoice_line_prov.invoice.number)
                            Dashboard.save([d])
                elif do_ == "pay":
                    if mo == "invoice":
                        #PayInvoice = Pool().get('account.invoice.pay')
                        PaymentMethod = Pool().get('account.invoice.payment.method')
                        inv = Invoice.search(['number','=',cp])
                        if inv:
                            pm = PaymentMethod.search(['id','>',0])[0]
                            inv = inv[0]
                            lines = inv.pay_invoice(
                                inv.amount_to_pay, pm, Date.today(),
                                'Payment of invoice ' + inv.number, 0, party=inv.party.id)
                            if lines:
                                d.action_return = 'account.invoice,' + str(inv.id) + ',' + inv.number
                                Dashboard.save([d])
                elif do_ == "create":
                    if mo == "prepaymentP" or mo == "prepaymentS":
                        if party:
                            if party.addresses:
                                invoice = Invoice()
                                invoice.type = 'in' if mo == "prepaymentP" else 'out'
                                invoice.journal = 2 if mo == "prepaymentP" else 1#invoice.set_journal()
                                logger.info("WIZARD_PREPAY:%s",invoice.journal)
                                invoice.invoice_date = Date.today() 
                                invoice.party = party.id
                                invoice.invoice_address = party.addresses[0]
                                invoice.account = party.account_payable_used if mo == "prepaymentP" else party.account_receivable_used
                                invoice.payment_term = 6
                                invoice.description = 'Prepayment supplier' if mo == "prepaymentP" else 'Prepayment client'
                                if un:
                                    curr = Currency.search(['name','=', un])
                                    if curr:
                                        invoice.currency = curr[0].id
                                line = InvoiceLine()
                                line.account = 748
                                line.quantity = 1
                                line.unit_price = Decimal(fl)
                                invoice.lines = [line]
                                Invoice.save([invoice])
                                Invoice.post([invoice])
                                d.action_return = model + ',' + str(invoice.id)+ ',' + str(invoice.number)
                                Dashboard.save([d])

        return 'end'

class BotAction(ModelSQL, ModelView):
    "Bot Action"
    __name__ = "bot.action"
    
    dashboard = fields.Many2One('purchase.dashboard',"Dashboard")
    type = fields.Selection([
            ('duplicate', 'duplicate'),
            ('invoice', 'invoice'),
            ('receive', 'receive'),
            ('add physic', 'add physic'),
            ('match', 'match'),
            ('link', 'link'),
            ('create', 'create')])
    model = fields.Char("Model")
    am_qt = fields.Numeric("Amount/Quantity")
    unit = fields.Char("Unit/Currency")
    keyword = fields.Char("Keyword")
    cp = fields.Char("Party")
    model_id = fields.Integer("Model id")
    res_id = fields.Integer("Res id")
    state = fields.Selection([
            ('todo', 'todo'),
            ('done', 'done'),
    ])

    @classmethod
    def state_default(cls):
        return 'todo'

    @classmethod
    def state_dashboard(cls):
        return 1
