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

from odoo import api, exceptions, fields, models, tools, _
from odoo.exceptions import UserError, AccessError, ValidationError
from odoo.osv import expression
import math
from datetime import datetime, time, timedelta
from odoo.tools.float_utils import float_round
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, ustr
import dateutil.parser


class AccountAnalyticLine(models.Model):
    _inherit = 'account.analytic.line'
    # _order = 'date desc, id desc'
    _order = 'date desc, unit_amount'

    @api.depends('project_id', 'employee_id')
    def name_get(self):
        res = []
        for record in self:
            if record.project_id.name:
                name = record.project_id.name + '/' + record.name
            res.append((record.id, name))
        return res

    def _domain_project_id(self):
        today = fields.Date.today()
        # domain = [('allow_timesheets', '=', True), ('is_sub_project', '=', False)]
        domain = [('allow_timesheets', '=', True), ('is_sub_project', '=', False), ('date', '>=', today),
                  ('date_start', '<=', today)]
        if not self.user_has_groups('hr_timesheet.group_timesheet_manager'):
            return expression.AND([domain,
                                   ['|', ('privacy_visibility', '!=', 'followers'),
                                    ('allowed_internal_user_ids', 'in', self.env.user.ids)]
                                   ])
        return domain

    def default_get(self, field_list):
        result = super(AccountAnalyticLine, self).default_get(field_list)
        if self.env.user:
            result['employee_id'] = self.env['hr.employee'].search([('user_id', '=', self.env.user.id)], limit=1).id
        return result

    project_id = fields.Many2one('project.project', 'Project', compute='_compute_project_id', store=True,
                                 readonly=False,
                                 domain=_domain_project_id)
    # start_time = fields.Float(string='Start Time', digits=(16, 2))
    # end_time = fields.Float(string='End Time', digits=(16, 2))
    start_datetime = fields.Datetime("Start Time", required=True)
    end_datetime = fields.Datetime("End Time", required=True)
    date = fields.Date('Date', required=True, index=True, compute='_compute_start_end_date', store=True)
    unit_amount = fields.Float('Duration', default=0.0)
    parent_project = fields.Many2one('project.project', related='project_id.parent_project', string='Parent Project')
    sub_project = fields.Many2one('project.project', domain="[('is_sub_project', '=', True)]",
                                  string='Sub Project')
    active_project = fields.Boolean(related='project_id.active', store=True)
    pricing_type = fields.Selection(related='project_id.pricing_type', store=True)
    project_type = fields.Selection(related='project_id.project_type', store=True)

    @api.onchange('project_id')
    def _onchange_sub_project_id(self):
        self.sub_project = False
        res = {}
        if self.project_id and self.project_id.sub_project:
            res['domain'] = {'sub_project': [('id', 'in', self.project_id.sub_project.ids)]}
        else:
            res['domain'] = {'sub_project': [('id', '=', False)]}
        return res

    def _default_start_datetime(self):
        return fields.Datetime.to_string(datetime.combine(fields.Datetime.now(), datetime.min.time()))

    def _default_end_datetime(self):
        return fields.Datetime.to_string(datetime.combine(fields.Datetime.now(), datetime.max.time()))

    @api.onchange('employee_id', 'project_id')
    def _onchange_employee_id(self):
        project_manager_grp = self.env.ref('project.group_project_manager').users.ids
        project_user_grp = self.env.ref('project.group_project_user').users.ids
        today = fields.Date.today()
        domain = []
        if self.employee_id and self.employee_id.user_id and self.employee_id.user_id.id in project_manager_grp:
            all_projects = self.env['project.project'].search([('allow_timesheets', '=', True),
                                                               ('is_sub_project', '=', False),
                                                               ('date', '>=', today), ('date_start', '<=', today)]).ids
            domain = [('id', 'in', all_projects)]
        else:
            if self.employee_id and self.employee_id.user_id and self.employee_id.user_id.id in project_user_grp:
                manager_id = self.env['project.project'].search(
                    [('user_id', '=', self.employee_id.user_id.id), ('allow_timesheets', '=', True),
                     ('date', '>=', today),('date_start', '<=', today),
                     ('is_sub_project', '=', False),('pricing_type', '=', 'fixed_rate')]).ids
                emp_project_ids = self.env['project.project'].search(
                    [('privacy_visibility', 'in', ('employees', 'portal')), ('allow_timesheets', '=', True),
                     ('date', '>=', today),('date_start', '<=', today),
                     ('is_sub_project', '=', False),('pricing_type', '=', 'fixed_rate')]).ids
                project_ids = self.env['project.project'].search(
                    [('privacy_visibility', '=', 'followers'), ('allow_timesheets', '=', True),
                     ('date', '>=', today),('date_start', '<=', today),
                     ('is_sub_project', '=', False),
                     ('allowed_internal_user_ids', 'in', self.employee_id.user_id.id),('pricing_type', '=', 'fixed_rate')]).ids
                consul_ids = self.env['project.sale.line.employee.map'].search(
                    [('employee_id', '=', self.employee_id.id)])
                consul_project_ids = []
                for rec in consul_ids:
                    if rec.project_id.pricing_type != 'fixed_rate' and rec.project_id.allow_timesheets == True and rec.project_id.is_sub_project == False:
                        if rec.start_date and rec.end_date:
                            if rec.start_date <= today <= rec.end_date:
                                consul_project_ids.append(rec.project_id.id)
                        elif rec.start_date:
                            if rec.start_date <= today:
                                consul_project_ids.append(rec.project_id.id)
                emp_all_project_ids = manager_id + emp_project_ids + project_ids + consul_project_ids
                domain = [('id', 'in', list(set(emp_all_project_ids)))]
        result = {
            'domain': {'project_id': domain},
        }
        return result

    # @api.onchange('employee_id')
    # def _onchange_employee_id(self):
    #     domain = []
    #     if self.employee_id and self.employee_id.user_id:
    #         manager_id = self.env['project.project'].search(
    #             [('user_id', '=', self.employee_id.user_id.id), ('allow_timesheets', '=', True),('is_sub_project', '=', False)]).ids
    #         emp_project_ids = self.env['project.project'].search(
    #             [('privacy_visibility', 'in', ('employees', 'portal')), ('allow_timesheets', '=', True),('is_sub_project', '=', False)]).ids
    #         project_ids = self.env['project.project'].search(
    #             [('privacy_visibility', '=', 'followers'), ('allow_timesheets', '=', True),('is_sub_project', '=', False),
    #              ('allowed_internal_user_ids', 'in', self.employee_id.user_id.id)]).ids
    #         consul_ids = self.env['project.sale.line.employee.map'].search([('employee_id', '=', self.employee_id.id)])
    #         consul_project_ids = [val.project_id.id for val in consul_ids]
    #         emp_all_project_ids = manager_id + emp_project_ids + project_ids + consul_project_ids
    #         domain = [('id', 'in', list(set(emp_all_project_ids)))]
    #     result = {
    #         'domain': {'project_id': domain},
    #     }
    #     return result

    @api.onchange('project_id')
    def _onchange_project_id(self):
        domain = [] if not self.project_id else [('project_id', '=', self.project_id.id)]
        cuser = []
        manager_id = []
        user_ids = []
        consul_project_ids = []
        if not self.project_id:
            cuser = self.env['hr.employee'].search([('user_id', '=', self.env.user.id)]).ids
        if self.project_id:
            consul_ids = self.env['project.sale.line.employee.map'].search([('project_id', '=', self.project_id.id)])
            consul_project_ids = [val.employee_id.id for val in consul_ids]
        if self.project_id and self.project_id.user_id:
            manager_id = self.env['hr.employee'].search([('user_id', '=', self.project_id.user_id.id)]).ids
        if self.project_id and self.project_id.privacy_visibility in ('employees', 'portal'):
            user_ids = self.env['hr.employee'].search([('user_id', '!=', False)]).ids
        if self.project_id and self.project_id.privacy_visibility == 'followers':
            user_ids = self.env['hr.employee'].search(
                [('user_id', 'in', self.project_id.allowed_internal_user_ids.ids)]).ids
        project_all_emp_ids = cuser + manager_id + user_ids + consul_project_ids
        if self.env.user.user_has_groups('cor_custom.group_update_timesheet'):
            result = {
                'domain': {'task_id': domain},
            }
        else:
            result = {
                'domain': {'task_id': domain, 'employee_id': [('id', 'in', project_all_emp_ids)]},
            }
        if self.project_id != self.task_id.project_id:
            # reset task when changing project
            self.task_id = False
        return result

    """_sql_constraints = [
        ('check_start_time_lower_than_24', 'CHECK(start_time <= 24)', 'You cannot have a start hour greater than 24'),
        ('check_start_time_positive', 'CHECK(start_time >= 0)', 'Start hour must be a positive number'),
        ('check_end_time_lower_than_24', 'CHECK(end_time <= 24)', 'You cannot have a end hour greater than 24'),
        ('check_end_time_positive', 'CHECK(end_time >= 0)', 'End hour must be a positive number'),
    ]

    @api.constrains('start_time', 'end_time')
    def _check_validity_start_time_end_time(self):
        for rec in self:
            if rec.start_time and rec.end_time:
                if rec.end_time < rec.start_time:
                    raise exceptions.ValidationError(_('End time cannot be earlier than Start time'))

    @api.onchange('start_time', 'end_time')
    def _onchange_start_end_time(self):
        if self.start_time > 0 and self.end_time > 0:
            res = self.end_time - self.start_time
            if res <= 0:
                raise ValidationError(_("End time cannot be earlier than Start time"))
            self.unit_amount = res"""

    # @api.onchange('start_time', 'end_time')
    # def _onchange_start_end_time(self):
    #     if self.start_time > 0:
    #         dt = datetime.strptime('26 Sep 2012', '%d %b %Y')
    #         print('HHHHHHHH', dt)
    #         newdatetime = dt.replace(hour=11, minute=59)
    #         print('GGGGGGGGGGGGG', newdatetime)

    @api.model
    def export_data(self, fields):
        index = range(len(fields))
        fields_name = dict(zip(fields, index))
        res = super(AccountAnalyticLine, self).export_data(fields)
        for index, val in enumerate(res['datas']):
            # print("task_id", fields_name)
            # if fields_name.get('date') and fields_name.get('date') >= 0:
            if fields_name.get('date') is not None:
                tdateindex = fields_name.get('date')
                tdate = res['datas'][index][tdateindex]
                if tdate:
                    res['datas'][index][tdateindex] = datetime.strftime(tdate, "%d/%m/%Y")
            # if fields_name.get('start_datetime') and fields_name.get('start_datetime') >= 0:
            if fields_name.get('start_datetime') is not None:
                start_datetime_index = fields_name.get('start_datetime')
                start_datetime = res['datas'][index][start_datetime_index]
                if start_datetime:
                    res['datas'][index][start_datetime_index] = datetime.strftime(start_datetime, "%d/%m/%Y %H:%M")
            if fields_name.get('end_datetime') is not None:
                end_datetime_index = fields_name.get('end_datetime')
                end_datetime = res['datas'][index][end_datetime_index]
                if end_datetime:
                    res['datas'][index][end_datetime_index] = datetime.strftime(end_datetime, "%d/%m/%Y %H:%M")
            if fields_name.get('task_id') is not None:
                taskindex = fields_name.get('task_id')
                ttask = res['datas'][index][taskindex]
                if type(ttask) == bool:
                    res['datas'][index][taskindex] = ''
            """if fields_name.get('start_time') is not None:
                starttimeindex = fields_name.get('start_time')
                starttime = float(res['datas'][index][starttimeindex])
                if starttime:
                    start_time = tools.format_duration(starttime)
                    res['datas'][index][starttimeindex] = start_time
            if fields_name.get('end_time') is not None:
                endtimeindex = fields_name.get('end_time')
                endtime = float(res['datas'][index][endtimeindex])
                if endtime:
                    end_time = tools.format_duration(endtime)
                    res['datas'][index][endtimeindex] = end_time"""
            if fields_name.get('unit_amount') is not None:
                durationindex = fields_name.get('unit_amount')
                duration = res['datas'][index][durationindex] and float(res['datas'][index][durationindex])
                if duration:
                    duration_time = round(duration, 2)
                    res['datas'][index][durationindex] = duration_time
                    # duration_time = tools.format_duration(duration)
                    # res['datas'][index][durationindex] = duration_time
        return res

    @api.onchange('start_datetime', 'end_datetime')
    def _onchange_start_end_date_time(self):
        if self.start_datetime and self.end_datetime:
            total_hours = (self.end_datetime - self.start_datetime).total_seconds() / 3600
            self.unit_amount = total_hours

    @api.model
    def create(self, vals):
        # if vals.get('unit_amount') == 0.0:
        #     raise ValidationError(_("Your can not fill 0.0 hour entry"))
        # if vals.get('unit_amount') >= 24.0:
        #     raise ValidationError(_("Your can not fill more than 24.0 hour entry"))
        value = super(AccountAnalyticLine, self).create(vals)
        if value and value.project_id:
            value.project_id._onchange_calculate_timesheet_hours()
            value.project_id._compute_calc()
            value._onchange_start_end_date_time()
            if value.unit_amount == 0.0:
                raise ValidationError(_("Your can not fill 0.0 hour entry"))
            # if value.unit_amount >= 24.0:
            #     raise ValidationError(_("Your can not fill more than 24.0 hour entry"))
        return value

    def write(self, vals):
        if vals.get('unit_amount') == 0.0:
            raise ValidationError(_("Your can not fill 0.0 hour entry"))
        res = super(AccountAnalyticLine, self).write(vals)
        if self.project_id:
            self.project_id._onchange_calculate_timesheet_hours()
        return res

    @api.depends('start_datetime', 'end_datetime')
    def _compute_start_end_date(self):
        for rec in self:
            if rec.start_datetime:
                rec.date = rec.start_datetime.date()

    # @api.constrains('start_datetime', 'end_datetime', 'employee_id')
    # def _check_date(self):
    #     for entry in self.filtered('employee_id'):
    #         domain = [
    #             ('start_datetime', '<', entry.end_datetime),
    #             ('end_datetime', '>', entry.start_datetime),
    #             ('employee_id', '=', entry.employee_id.id),
    #             ('id', '!=', entry.id),
    #         ]
    #         entries = self.search_count(domain)
    #         if entries:
    #             raise ValidationError(
    #                 _('You can not set 2 timesheet entries that overlaps on the same day for the same employee.'))
