# -*- coding: utf-8 -*-

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


class Project(models.Model):
    _inherit = 'project.project'

    bill_type = fields.Selection([
        ('customer_task', 'Invoice tasks separately to different clients'),
        ('customer_project', 'Invoice all tasks to a single client')
    ], string="Client Type", default="customer_project",
        help='When billing tasks individually, a Sales Order will be created from each task. It is perfect if you would like to bill different services to different clients at different rates. \n When billing the whole project, a Sales Order will be created from the project instead. This option is better if you would like to bill all the tasks of a given project to a specific client either at a fixed rate, or at an employee rate.')

    pricing_type = fields.Selection([
        ('fixed_rate', 'Fixed rate'),
        ('employee_rate', 'Consultant rate')
    ], string="Pricing", default="fixed_rate",
        help='The fixed rate is perfect if you bill a service at a fixed rate per hour or day worked regardless of the consultant who performed it. The consultant rate is preferable if your employees deliver the same service at a different rate. For instance, junior and senior consultants would deliver the same service (= consultancy), but at a different rate because of their level of seniority.')

    project_type = fields.Selection([
        ('hours_in_consultant', 'Hours are budgeted according to a consultant'),
        ('hours_no_limit', 'Total hours are budgeted without division to consultant'),
    ], string="Project Type", default="hours_in_consultant")

    privacy_visibility = fields.Selection([
        ('followers', 'Invited internal users'),
        ('employees', 'All internal users'),
        ('portal', 'Invited portal users and all internal users'),
    ],
        string='Visibility', required=True,
        default='followers',
        help="Defines the visibility of the tasks of the project:\n"
             "- Invited internal users: employees may only see the followed project and tasks.\n"
             "- All internal users: employees may see all project and tasks.\n"
             "- Invited portal and all internal users: employees may see everything."
             "   Portal users may see project and tasks followed by\n"
             "   them or by someone of their company.")
    allow_billable = fields.Boolean("Billable", default=True, help="Invoice your time and material from tasks.")

    date_start = fields.Date(string='Start Date')
    date = fields.Date(string='End Date', index=True, tracking=True)
    budgeted_hours = fields.Float(string='Total Budgeted Hours', compute='_compute_calc')
    budgeted_hours2 = fields.Float(string='Total Budgeted Hours')
    budgeted_revenue = fields.Float(string='Budgeted Revenue', digits=(16, 2))
    expenses_per = fields.Float(string='Expenses (%)', digits=(16, 2))
    expenses_amt = fields.Float(string='Expenses Amount', digits=(16, 2))
    cost = fields.Float("Total Revenue", compute='onchange_compute_values', store=True)
    consultant_cost = fields.Float("Actual Cost", compute='_compute_calc')
    other_expenses = fields.Float(string='Other Expenses', related='expenses_amt')
    total_expenses = fields.Float(string='Total Expenses', digits=(16, 2), compute='_compute_calc', store=True)
    hourly_rate = fields.Float("Hourly Rate", default=0.0)
    hourly_rate2 = fields.Float("Hourly Ratee")
    budgeted_hour_week = fields.Float("Budgeted Hours(per week)", compute='onchange_compute_values', store=True)
    profit_amt = fields.Float(string='Profit Amount', digits=(16, 2), compute='_compute_calc', store=True)
    profit_per = fields.Float(string='Porfit Percentage', digits=(16, 2), compute='_compute_calc', store=True)
    hour_distribution = fields.Selection([
        ('Manual', 'Manual'),
        ('Percentage', 'Percentage'),
    ], string="Hours Distribution", default="Manual")
    manager_per = fields.Float(string='Manager %', digits=(16, 2))
    employee_per = fields.Float(string='Employee %', digits=(16, 2), compute='compute_percentage_hours', store=True)

    manager_hour = fields.Float(string='Manager Hour')
    employee_hour = fields.Float(string='Employee Hour')

    consultant_timesheet_hrs = fields.One2many('consultant.timesheet.hrs', 'project_id', "Timesheet Hrs",
                                               copy=False, help="Consultant timesheet hours")
    project_cons_hrs = fields.One2many('project.consultant.hrs', 'project_id', 'Consultant Allocation', copy=False)
    comment = fields.Text(string='Comment')

    def _onchange_calculate_timesheet_hours(self):
        self.consultant_timesheet_hrs = [(6, 0, False)]
        if self._origin.id:
            self._cr.execute('''SELECT project_id, employee_id, SUM(unit_amount) FROM account_analytic_line
                            where project_id = %(project_id)s
                            GROUP BY project_id, employee_id''',
                             {'project_id': self._origin.id})
            res = self._cr.fetchall()
            if res:
                for rec in res:
                    self.consultant_timesheet_hrs.create({'project_id': rec[0],
                                                                             'employee_id': rec[1],
                                                                             'timesheet_hour': rec[2]})

    @api.depends('cost', 'expenses_amt', 'budgeted_revenue')
    def _compute_calc(self):
        for record in self:
            consultant_cost = 0.0
            hour = 0.0
            for rec in record.sale_line_employee_ids:
                consultant_cost = consultant_cost + rec.consultant_cost
                hour = hour + rec.budgeted_qty
            if record.pricing_type == 'fixed_rate':
                for rec in record.consultant_timesheet_hrs:
                    consultant_cost = consultant_cost + rec.consultant_cost
            record.consultant_cost = consultant_cost
            record.budgeted_hours = hour
            total_exp = record.consultant_cost + record.expenses_amt
            record.total_expenses = total_exp
            profit_amt = record.budgeted_revenue - total_exp
            record.profit_amt = profit_amt
            if record.profit_amt > 0 and record.budgeted_revenue > 0:
                record.profit_per = (record.profit_amt / record.budgeted_revenue) * 100
            if record.project_type == 'hours_in_consultant' and record.budgeted_hours > 0.0:
                record.hourly_rate = (record.budgeted_revenue / record.budgeted_hours)
            if record.project_type == 'hours_no_limit' and record.budgeted_hours2 > 0.0:
                record.hourly_rate = (record.budgeted_revenue / record.budgeted_hours2)


    @api.depends('manager_per', 'hour_distribution')
    def compute_percentage_hours(self):
        for record in self:
            if record.manager_per > 100:
                raise ValidationError(_("Percentage should be less than or equal to 100"))
            if record.manager_per > 0.0:
                record.employee_per = 100 - record.manager_per
        # if self.manager_per > 100:
        #     raise ValidationError(_("Percentage should be less than or equal to 100"))


    @api.onchange('budgeted_revenue', 'expenses_per')
    def onchange_expenses_per(self):
        if self.budgeted_revenue > 0 and self.expenses_per > 0:
            expense_amount = self.budgeted_revenue * (self.expenses_per / 100)
            self.expenses_amt = expense_amount

    @api.onchange('budgeted_revenue', 'sale_line_employee_ids')
    def onchange_budgeted_hour(self):
        self.sale_line_employee_ids._compute_total_cost()
        hour = 0.0
        for rec in self.sale_line_employee_ids:
            hour = hour + rec.budgeted_qty
        self.budgeted_hours = hour
        if self.budgeted_hours > 0.0:
            self.hourly_rate = (self.budgeted_revenue / self.budgeted_hours)

    @api.depends('sale_line_employee_ids')
    def onchange_compute_values(self):
        for record in self:
            cost = 0.0
            budgeted_hour_week = 0.0
            for rec in record.sale_line_employee_ids:
                cost = cost + rec.cost
                budgeted_hour_week = budgeted_hour_week + rec.budgeted_hour_week
            if record.project_type == 'hours_in_consultant':
                record.cost = cost
            record.budgeted_hour_week = budgeted_hour_week

    # @api.depends('pricing_type')
    def _compute_consultant_timesheet_hour(self):
        for val in self:
            val.consultant_timesheet_hrs = False
            if val._origin.id:
                self._cr.execute('''SELECT project_id, employee_id, SUM(unit_amount) FROM account_analytic_line where project_id = 149
                GROUP BY project_id, employee_id''')
                res = self._cr.fetchone()
                if res:
                    create_timesheet = val.consultant_timesheet_hrs.create({'project_id': res[0],
                                                                            'employee_id': res[1],
                                                                            'timesheet_hour': res[2]})
                else:
                    val.consultant_timesheet_hrs = False
            # val.consultant_timesheet_hrs = False


class ProjectConsultantTimesheetHrs(models.Model):
    _name = 'consultant.timesheet.hrs'
    _description = 'Project Consultant Timesheet Hrs'

    project_id = fields.Many2one('project.project', "Project")
    employee_id = fields.Many2one('hr.employee')
    employee_price = fields.Float(string="Consultant Price", compute='_compute_consultant_timesheet_cost', default=0.0)
    timesheet_hour = fields.Float("Timesheet Hour", default=0.0)
    consultant_cost = fields.Float("Actual Cost", compute='_compute_consultant_timesheet_cost', default=0.0)

    def _compute_consultant_timesheet_cost(self):
        for val in self:
            if val.employee_id.timesheet_cost:
                val.employee_price = val.employee_id.timesheet_cost
            else:
                val.employee_price = 0.0
            if val.timesheet_hour and val.employee_id.timesheet_cost:
                val.consultant_cost = val.timesheet_hour * val.employee_id.timesheet_cost
            else:
                val.consultant_cost = 0.0


class InheritProjectProductEmployeeMap(models.Model):
    _inherit = 'project.sale.line.employee.map'

    budgeted_qty = fields.Float(string='Budgeted Hours')
    budgeted_uom = fields.Many2one('uom.uom', string='Budgeted UOM', related='sale_line_id.product_uom', readonly=True)
    # budgeted_uom = fields.Many2one('uom.uom', string='Budgeted UOM', related='timesheet_product_id.uom_id', readonly=True)
    timesheet_hour = fields.Float("Timesheet Hour", compute='_compute_timesheet_hour', default=0.0)
    employee_price = fields.Monetary(string="Consultant Price", related="employee_id.timesheet_cost", readonly=True)
    budgeted_hour_week = fields.Float("Budgeted Hours per week", compute='_compute_budgeted_hour_week')
    price_unit = fields.Float("Hourly Rate")
    currency_id = fields.Many2one('res.currency', string="Currency", compute='_compute_price_unit', store=True,
                                  readonly=False)
    sale_line_id = fields.Many2one('sale.order.line', "Service", domain=[('is_service', '=', True)])
    cost = fields.Float("Cost", default=0.0, store=True)
    consultant_cost = fields.Float("Actual Cost", compute='_compute_timesheet_hour', default=0.0)

    hour_distribution = fields.Selection(related='project_id.hour_distribution')
    role = fields.Selection([('Manager', 'Manager'),
                             ('Employee', 'Employee'), ], string="Role", default="Employee")
    distribution_per = fields.Float("%")

    def _compute_timesheet_hour(self):
        for val in self:
            self._cr.execute('''SELECT project_id, employee_id, SUM(unit_amount) FROM account_analytic_line
            where project_id = %(project_id)s and employee_id = %(employee_id)s
            GROUP BY project_id, employee_id''',
                             {'project_id': val.project_id._origin.id, 'employee_id': val.employee_id.id, })
            res = self._cr.fetchone()
            if res and res[2]:
                val.timesheet_hour = res[2]
            else:
                val.timesheet_hour = 0.0
            val.consultant_cost = val.timesheet_hour * val.employee_price

    def _compute_budgeted_hour_week(self):
        for val in self:
            if val.employee_id and val.employee_id.budgeted_hour_week > 0 and val.budgeted_qty:
                val.budgeted_hour_week = (val.budgeted_qty / val.employee_id.budgeted_hour_week)
            else:
                val.budgeted_hour_week = 0

    @api.onchange('project_id.budgeted_revenue', 'price_unit', 'distribution_per', 'employee_id', 'role')
    def _compute_total_cost(self):
        for val in self:
            if val.project_id.project_type == 'hours_in_consultant':
                if val.hour_distribution == 'Percentage':
                    if val.role == 'Manager':
                        val.cost = val.project_id.budgeted_revenue * (val.project_id.manager_per / 100) * (
                                val.distribution_per / 100)
                    else:
                        val.cost = val.project_id.budgeted_revenue * (val.project_id.employee_per / 100) * (
                                val.distribution_per / 100)
                    if val.price_unit > 0.0:
                        val.budgeted_qty = val.cost / val.price_unit
                # val.cost = val.budgeted_qty * val.price_unit
            # val.consultant_cost = val.timesheet_hour * val.employee_price
        # self.project_id.onchange_budgeted_hour()

    @api.onchange('price_unit', 'budgeted_qty')
    def _calculate_total_cost(self):
        if self.project_id.project_type == 'hours_in_consultant':
            if self.hour_distribution == 'Manual':
                self.cost = self.price_unit * self.budgeted_qty

    @api.depends('sale_line_id', 'sale_line_id.price_unit', 'timesheet_product_id')
    def _compute_price_unit(self):
        for line in self:
            if line.sale_line_id:
                line.price_unit = line.sale_line_id.price_unit
                line.currency_id = line.sale_line_id.currency_id
            elif line.timesheet_product_id:
                line.price_unit = line.timesheet_product_id.lst_price
                line.currency_id = line.timesheet_product_id.currency_id
            else:
                # line.price_unit = 0
                line.currency_id = False
