# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo import api, fields, models, _
from odoo.exceptions import UserError


class ProjectCreateSalesOrder(models.TransientModel):
    _inherit = 'project.create.sale.order'


    partner_id = fields.Many2one('res.partner', string="Client", required=True, help="Client of the sales order")

    def _make_billable_at_project_rate(self, sale_order):
        self.ensure_one()
        task_left = self.project_id.tasks.filtered(lambda task: not task.sale_line_id)
        ticket_timesheet_ids = self.env.context.get('ticket_timesheet_ids', [])
        budgeted_qty = 0
        for wizard_line in self.line_ids:
            task_ids = self.project_id.tasks.filtered(lambda task: not task.sale_line_id and task.timesheet_product_id == wizard_line.product_id)
            task_left -= task_ids
            # trying to simulate the SO line created a task, according to the product configuration
            # To avoid, generating a task when confirming the SO
            task_id = False
            if task_ids and wizard_line.product_id.service_tracking in ['task_in_project', 'task_global_project']:
                task_id = task_ids.ids[0]

            # create SO line
            sale_order_line = self.env['sale.order.line'].create({
                'order_id': sale_order.id,
                'product_id': wizard_line.product_id.id,
                'price_unit': wizard_line.price_unit,
                'project_id': self.project_id.id,  # prevent to re-create a project on confirmation
                'task_id': task_id,
                'product_uom_qty': wizard_line.budgeted_qty,
            })
            budgeted_qty += wizard_line.budgeted_qty
            if ticket_timesheet_ids and not self.project_id.sale_line_id and not task_ids:
                # With pricing = "project rate" in project. When the user wants to create a sale order from a ticket in helpdesk
                # The project cannot contain any tasks. Thus, we need to give the first sale_order_line created to link
                # the timesheet to this first sale order line.
                # link the project to the SO line
                self.project_id.write({
                    'sale_order_id': sale_order.id,
                    'sale_line_id': sale_order_line.id,
                    'partner_id': self.partner_id.id,
                })

            # link the tasks to the SO line
            task_ids.write({
                'sale_line_id': sale_order_line.id,
                'partner_id': sale_order.partner_id.id,
                'email_from': sale_order.partner_id.email,
            })

            # assign SOL to timesheets
            search_domain = [('task_id', 'in', task_ids.ids), ('so_line', '=', False)]
            if ticket_timesheet_ids:
                search_domain = [('id', 'in', ticket_timesheet_ids), ('so_line', '=', False)]

            self.env['account.analytic.line'].search(search_domain).write({
                'so_line': sale_order_line.id
            })
            #sale_order_line.with_context({'no_update_planned_hours': True}).write({
                #'product_uom_qty': sale_order_line.qty_delivered
            #})

        if ticket_timesheet_ids and self.project_id.sale_line_id and not self.project_id.tasks and len(self.line_ids) > 1:
            # Then, we need to give to the project the last sale order line created
            self.project_id.write({
                'sale_line_id': sale_order_line.id
            })
        else:  # Otherwise, we are in the normal behaviour
            # link the project to the SO line
            self.project_id.write({
                'sale_order_id': sale_order.id,
                'sale_line_id': sale_order_line.id,  # we take the last sale_order_line created
                'partner_id': self.partner_id.id,
            })
        if self.project_id.budgeted_hours <= 0:
            self.project_id.write({
                'budgeted_hours': budgeted_qty,
            })

        if task_left:
            task_left.sale_line_id = False


    def _make_billable_at_employee_rate(self, sale_order):
        # trying to simulate the SO line created a task, according to the product configuration
        # To avoid, generating a task when confirming the SO
        task_id = self.env['project.task'].search([('project_id', '=', self.project_id.id)], order='create_date DESC', limit=1).id
        project_id = self.project_id.id

        lines_already_present = dict([(l.employee_id.id, l) for l in self.project_id.sale_line_employee_ids])

        non_billable_tasks = self.project_id.tasks.filtered(lambda task: not task.sale_line_id)
        non_allow_billable_tasks = self.project_id.tasks.filtered(lambda task: task.non_allow_billable)

        map_entries = self.env['project.sale.line.employee.map']
        EmployeeMap = self.env['project.sale.line.employee.map'].sudo()

        # create SO lines: create on SOL per product/price. So many employee can be linked to the same SOL
        map_product_price_sol = {}  # (product_id, price) --> SOL
        budgeted_qty = 0
        for wizard_line in self.line_ids:
            map_key = (wizard_line.product_id.id, wizard_line.price_unit)
            if map_key not in map_product_price_sol:
                values = {
                    'order_id': sale_order.id,
                    'product_id': wizard_line.product_id.id,
                    'price_unit': wizard_line.price_unit,
                    'product_uom_qty': wizard_line.budgeted_qty,
                }
                budgeted_qty += wizard_line.budgeted_qty
                if wizard_line.product_id.service_tracking in ['task_in_project', 'task_global_project']:
                    values['task_id'] = task_id
                if wizard_line.product_id.service_tracking in ['task_in_project', 'project_only']:
                    values['project_id'] = project_id
                sale_order_line = self.env['sale.order.line'].create(values)
                map_product_price_sol[map_key] = sale_order_line

            if wizard_line.employee_id.id not in lines_already_present:
                map_entries |= EmployeeMap.create({
                    'project_id': self.project_id.id,
                    'sale_line_id': map_product_price_sol[map_key].id,
                    'employee_id': wizard_line.employee_id.id,
                })
            else:
                map_entries |= lines_already_present[wizard_line.employee_id.id]
                lines_already_present[wizard_line.employee_id.id].write({
                    'sale_line_id': map_product_price_sol[map_key].id
                })

        # link the project to the SO
        self.project_id.write({
            'sale_order_id': sale_order.id,
            'sale_line_id': sale_order.order_line[0].id,
            'partner_id': self.partner_id.id,
        })
        if self.project_id.budgeted_hours <= 0:
            self.project_id.write({
                'budgeted_hours': budgeted_qty,
            })
        non_billable_tasks.write({
            'partner_id': sale_order.partner_id.id,
            'email_from': sale_order.partner_id.email,
        })
        non_allow_billable_tasks.sale_line_id = False

        tasks = self.project_id.tasks.filtered(lambda t: not t.non_allow_billable)
        # assign SOL to timesheets
        for map_entry in map_entries:
            search_domain = [('employee_id', '=', map_entry.employee_id.id), ('so_line', '=', False)]
            ticket_timesheet_ids = self.env.context.get('ticket_timesheet_ids', [])
            if ticket_timesheet_ids:
                search_domain.append(('id', 'in', ticket_timesheet_ids))
            else:
                search_domain.append(('task_id', 'in', tasks.ids))
            self.env['account.analytic.line'].search(search_domain).write({
                'so_line': map_entry.sale_line_id.id
            })
            #map_entry.sale_line_id.with_context({'no_update_planned_hours': True}).write({
            #    'product_uom_qty': map_entry.sale_line_id.qty_delivered
            #})

        return map_entries


class ProjectCreateSalesOrderLine(models.TransientModel):
    _inherit= 'project.create.sale.order.line'


    employee_id = fields.Many2one('hr.employee', string="Consultant", help="Consultant that has timesheets on the project.")
    budgeted_qty = fields.Float(string='Budgeted Hour',  digits='Product Unit of Measure', default=1.0)
    budgeted_uom = fields.Many2one('uom.uom', string='Budgeted UOM', related='product_id.uom_id', readonly=True)
    employee_price = fields.Float("Consultant Price")
    price_unit = fields.Float("Hourly rate", help="Unit price of the sales order item.")





