'''
Created on 12-Jul-2021

@author: bthakur
'''
import random
import inspect
import traceback   #        {inspect.stack()[0][3]}

import re
from sympy import (Eq, symbols, Symbol, sqrt, latex,
                   Rational, solve, log, nsimplify, E, exp,  
                   sin, cos, I, series, pi)
from sympy.abc import theta
import sympy


from xv.km.util import latex_fraction
from sympy.core.expr import UnevaluatedExpr as ueval

from xv.util import list_to_str, toIntOrFloat, html_list
from ....util import LatexEquation

# _modelling_layered_business_helper
# ModellingLayeredBusinessHelper

from xv.util import UtilClass

class ModellingLayeredBusinessHelper(UtilClass):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        pass


    def get_random_model(self, **kwargs):
        methods = [self.model_juice_business,
                   ]
        
        method = random.choice(methods)
        model_data = method()
        return model_data
        pass


    def model_juice_business(self):
        p_names = [
            ['John', 'he'],
            ['Mary', 'she'],
            ['Saeed', 'he'],
            ['Marium', 'she'],
            ['Sheldon', 'he'],
            ['Sylvia', 'she'],
            ['Likhith', 'he'],
            ['Rishitha', 'she'],
            ]
        p_name, p_pron = random.choice(p_names)

        prods = ['farm', 'garden', 'tree', 'fruit', 'box']
        prods = [Symbol(f"{prod}") for prod in prods]
        
        per_unit_qtys = [random.randint(2, 10), 
                         random.randint(2, 10), 
                         random.randint(1, 10) * 10, 
                         random.randint(1, 10) * 10, 
                         Rational(1, random.choice([10, 12, 25, 50, 100]))
                         ]
        
        start_idx = random.randint(0, 2)
        prods = prods[start_idx:]
        per_unit_qtys = per_unit_qtys[start_idx:]
        
        currency = random.choice([r"\$"])

        sell_price = random.randint(2, 10)

        
        

        prob_items = []
        prod_stmt = []
        qty_stmt = []
        cum_qtys = []
        qtys = []
        cum_qty = 1
        for idx, prod in enumerate(prods):
            item_qty = per_unit_qtys[idx]
            if item_qty < 1:
                item_qty = Rational(1, 1/item_qty)

            qtys.append(item_qty)
            cum_qty = cum_qty * item_qty
            cum_qtys.append(cum_qty)
            
            if idx == 0:
                qty_stmt.append(f"{item_qty} \\; {prod}")
                prod_stmt.append(f"{p_name} has ${item_qty} \\; {prod}$.")
            else:
                prod_prev = prods[idx - 1]

                if item_qty < 1:
                    cost_item_latex = latex_fraction(f"{prod}", 
                                                     f"{1/item_qty} \\; {prod_prev}")
                    qty_stmt.append(cost_item_latex)
                
                    prod_stmt.append(f"Each ${prod}$ has ${1/item_qty} \\; {prod_prev}$.")
                else:
                    cost_item_latex = latex_fraction(f"{item_qty} \\; {prod}", 
                                                     f"{prod_prev}")
                    qty_stmt.append(cost_item_latex)
                
                    prod_stmt.append(f"Each ${prod_prev}$ has ${item_qty} \\; {prod}$.")
                pass
            pass
        
        
        prod_stmt = " ".join(prod_stmt)
        prob_item = f"""
        {prod_stmt}
        Each {prods[-1]} sells for {currency}{sell_price}.
        """
        prob_items.append(prob_item.replace("\n", "").strip())



        soln_items = []
        
 
        
        soln_item = f"""
        <h3>Let us do calculations:</h3>
        Total sales revenue
        """
        soln_items.append(soln_item.strip())

        last_cum_qty = 1
        cum_stmt = []
        for idx, qty_stmt_item in enumerate(qty_stmt):
            cum_stmt.append(qty_stmt_item)
            
            soln_item = " * ".join(cum_stmt)
            
            #cum_qty_calculated = f" \\qquad \\left\\{{ = {cum_qtys[idx]} \\; {prods[idx]} \\right."
            cum_qty_calculated = f" \\qquad \\qquad \\text{{So, }} {cum_qtys[idx]} \\; {prods[idx]} "
            
            if idx == 0:
                soln_item = f"""$\\displaystyle = {soln_item}$"""
            else:
                soln_item = f"""$\\displaystyle = {soln_item} {cum_qty_calculated}$"""
                pass
            soln_items.append(soln_item.strip())
    
            last_cum_qty = cum_qtys[idx]
            pass
        
        
        
        
        #sell_price
        sell_price_latex = latex_fraction(f"{currency} {sell_price}",
                                          f"{prods[-1]}")
        
        soln_item = " * ".join(cum_stmt)
        soln_item = f"""$\\displaystyle = {soln_item} * {sell_price_latex}$"""
        soln_items.append(soln_item.strip())
        
        sales_revenue_latex = [f"{latex(qty)}" for qty in qtys]
        sales_revenue_latex.append(f"{currency} {sell_price}")
        sales_revenue_latex = " * ".join(sales_revenue_latex)
        
        soln_item = f"""$\\displaystyle = {sales_revenue_latex}$"""
        soln_items.append(soln_item.strip())


        sales_revenue = toIntOrFloat(cum_qtys[-1] * sell_price, 
                                     roundoff = 2)
        
        soln_item = f"""$\\displaystyle = {currency} {sales_revenue}$"""
        soln_items.append(soln_item.strip())
        
        cost_prod_idx = random.randint(0, len(prods) - 3) 
        cost_qty = cum_qtys[cost_prod_idx]
        cost_prod = prods[cost_prod_idx]
        
        #sell_price_per_prod1 = toIntOrFloat(sales_revenue / cost_qty, roundoff = 2)
        sell_price_per_prod1 = toIntOrFloat(sales_revenue / last_cum_qty, roundoff = 2)
        
        sOut = f"""
        sales_revenue = {sales_revenue}
        cost_qty = {cost_qty}
        last_cum_qty = {last_cum_qty}
        
        sales_revenue / last_cum_qty = {sales_revenue/last_cum_qty}
        
        sell_price_per_prod1 = {sell_price_per_prod1}
        
        """
        #print(sOut)

        cost_price_per_prod1 = sell_price_per_prod1 * random.randint(70,90) / 100
        if cost_price_per_prod1 > 2:
            cost_price_per_prod1 = int(cost_price_per_prod1)
        else:
            cost_price_per_prod1 = toIntOrFloat(cost_price_per_prod1,
                                                roundoff = 1)
            pass
        total_cost = cost_qty * cost_price_per_prod1
        
        net_profit = sales_revenue - total_cost

        prob_item = f"""
        The cost of maintaining each {cost_prod} is {currency}{cost_price_per_prod1}.
        """
        prob_items.append(prob_item.strip())


        cost_price_latex = latex_fraction(f"{currency} {cost_price_per_prod1}",
                                          f"{cost_prod}")

        soln_item = f"""
        Cost
        
        $\\displaystyle = {cost_price_latex}$
        
        $\\displaystyle = {cost_price_latex} * {cost_qty} \\; {cost_prod}$
        
        $\\displaystyle = {currency} {total_cost}$
        
        Net Profit 
        = Total Revenue - Total Cost
        
        $\\displaystyle = {currency} {sales_revenue} - {currency} {total_cost}$

        $\\displaystyle = {currency} {net_profit}$
        """
        soln_items.append(soln_item.strip())

        
        model_data = {
            'p_name': p_name,
            'p_pron': p_pron,
            'currency': currency,
            'prods': prods,
            'per_unit_qtys': per_unit_qtys,
            'qtys': qtys,
            'cum_qtys': cum_qtys,
            'sales_revenue': sales_revenue,
            'currency': currency,
            'cost_prod_idx': cost_prod_idx,
            'cost_qty': cost_qty,
            'cost_prod': cost_prod,
            'sell_price_per_prod1': sell_price_per_prod1,
            'cost_price_per_prod1': cost_price_per_prod1,
            'cost_price_latex': cost_price_latex,
            'total_cost': total_cost,
            'net_profit': net_profit,
            }

        qa_data = self.convert_data_to_qa_data(model_data)
        latex_eqs = self.convert_data_to_eqs(model_data)
        latex_eqs_str = self._get_eqs_str(latex_eqs)

        prob_item = f"""
        Answer the following questions:
        {qa_data['q_html_list']}
        """
        prob_items.append(prob_item.strip())


        soln_item = f"""
        <h3>The equation of the question are as follows:</h3>
        {latex_eqs_str}
        """
        soln_items.insert(0, soln_item.strip())
        
        
        soln_item = f"""
        <h3>Now, we can answer the questions:</h3>
        {qa_data['qa_html_list']}
        """
        soln_items.append(soln_item.strip())
        

        prob_s = " ".join(prob_items)
        soln_s = "\n\n".join(soln_items)
        
        answer_s = f"{qa_data['a_html_list']}"
        
        problemTemplate_data = {
            'prob_s': prob_s,
            'soln_s': soln_s,
            'answer_s': answer_s,
            }
        
        model_data.update(qa_data)
        model_data.update(problemTemplate_data)
        
        return model_data 
        pass
    

    def convert_data_to_eqs(self, model_data):
        p_name = model_data['p_name']
        p_pron = model_data['p_pron']
        prods = model_data['prods']
        qtys = model_data['qtys']
        cum_qtys = model_data['cum_qtys']
        currency = model_data['currency']
        sales_revenue = model_data['sales_revenue']
        sell_price_per_prod1 = model_data['sell_price_per_prod1']
        cost_price_per_prod1 = model_data['cost_price_per_prod1']
        cost_price_latex = model_data['cost_price_latex']
        cost_prod_idx = model_data['cost_prod_idx']
        cost_qty = model_data['cost_qty']
        cost_prod = model_data['cost_prod']
        
        currency = Symbol(currency)
        
        latex_eqs = []
        for idx, prod in enumerate(prods):

            if idx == 0:
                prod_prev = Symbol(p_name)
            else:
                prod_prev = prods[idx - 1]
                pass
            
            qty = qtys[idx]
            
            eq = Eq(1 * prod_prev, qty * prod)
            lhs = f"1 \\;  {prod_prev}"
            rhs = f" {latex(qty)} \\; {prod}"
            latex_eq = LatexEquation(lhs, rhs, eq)
            
            latex_eqs.append(latex_eq)
            pass
        
        #sell_price
        eq = Eq(1 * prods[-1], currency * sell_price_per_prod1)
        lhs = f"1 \\;  {prods[-1]}"
        rhs = f" {currency} {sell_price_per_prod1} \\qquad \\qquad \\text{{[sell price]}}"
        latex_eq = LatexEquation(lhs, rhs, eq)
        latex_eqs.append(latex_eq)
        
        #cost_price
        eq = Eq(1 * cost_prod, currency * cost_price_per_prod1)
        lhs = f"1 \\;  {cost_prod}"
        rhs = f" {currency} {cost_price_per_prod1} \\qquad \\qquad \\text{{[cost price]}}"
        latex_eq = LatexEquation(lhs, rhs, eq)
        latex_eqs.append(latex_eq)
        
        return latex_eqs
        pass

    def convert_data_to_qa_data(self, model_data):
        p_name = model_data['p_name']
        p_pron = model_data['p_pron']
        prods = model_data['prods']
        qtys = model_data['qtys']
        cum_qtys = model_data['cum_qtys']
        currency = model_data['currency']
        sales_revenue = model_data['sales_revenue']
        sell_price_per_prod1 = model_data['sell_price_per_prod1']
        cost_price_per_prod1 = model_data['cost_price_per_prod1']
        cost_price_latex = model_data['cost_price_latex']
        total_cost = model_data['total_cost']
        net_profit = model_data['net_profit']
        
        

        
        qas = []

        for idx, prod in enumerate(prods):
            qa = [f"What is the total number of {prod}?",
                  f"$\\displaystyle {cum_qtys[idx]}$"
                  ]
            qas.append(qa)
            pass


        qa = [f"What is the total sales value?",
              f"""$\\displaystyle {currency} {sales_revenue}$"""
              ]
        qas.append(qa)
        

        qa = [f"What is the total cost?",
              f"""$\\displaystyle {currency} {total_cost}$"""
              ]
        qas.append(qa)
        
        qa = [f"What is the net profit?",
              f"""$\\displaystyle {currency} {net_profit}$"""
              ]
        qas.append(qa)
        
        for qa_idx, qa in enumerate(qas):
            if len(qa) == 2:
                qas[qa_idx].append(qa[1])
            pass
        
        q_html_list = html_list([f"{qa[0]}<br/>" for qa in qas], 
                                list_type = "ol")
        
        a_html_list = html_list([f"{qa[2]}<br/><br/>" for qa in qas], 
                                list_type = "ol")
        
        qa_html_list = html_list([f"{qa[0]}<br/>Answer: {qa[1]}<br/><br/>" for qa in qas], 
                                 list_type = "ol")

        qa_data = {
            'qas': qas,
            'q_html_list': q_html_list,
            'a_html_list': a_html_list,
            'qa_html_list': qa_html_list,
            }
        return qa_data
        pass

    def _get_eqs_str(self, latex_eqs):
        eqs_str = [f'$\\displaystyle {latex_eq}$' for latex_eq in latex_eqs]
        eqs_str = "\n\n".join(eqs_str)
        return eqs_str
        pass
    
    def _get_filtered_dict(self, dct, keys):
        return {k:dct[k] for k in keys}
        pass
    
    
    pass
#class ModellingLayeredBusinessHelper:
