# -*- coding: utf-8 -*-
##############################################################################
#
#    datenpol gmbh
#    Copyright (C) 2013-TODAY datenpol gmbh ()
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see .
#
##############################################################################
import json
import requests
from odoo.addons.component.core import Component
from odoo import tools, fields, models, api, _
from odoo.exceptions import ValidationError
from odoo.addons.queue_job.job import job
import ssl
try:
    _create_unverified_https_context = ssl._create_unverified_context
except AttributeError:
    # Legacy Python that doesn't verify HTTPS certificates by default
    pass
else:
    # Handle target environment that doesn't support HTTPS verification
    ssl._create_default_https_context = _create_unverified_https_context
class ReportIntrastatCode(models.Model):
    _inherit = "report.intrastat.code"
    active = fields.Boolean(string='Active', default=True, help="If unchecked, it will allow you to hide the code without removing it.")
class ProductTemplate(models.Model):
    _inherit = "product.template"
    intrastat_id = fields.Many2one('report.intrastat.code', string='Intrastat Code')
class ProductXCategory(models.Model):
    _name = 'product.xcategory'
    _description = 'X-Kategorie'
    _order = 'name'
    name = fields.Char(string='Bezeichnung', required=True)
    _sql_constraints = [
        ('name_uniq', 'unique(name)', 'Die Bezeichnung muss eindeutig sein')
    ]
class ProductTemplate(models.Model):
    _name = 'product.template'
    _inherit = ['product.template', 'dp_custom.helper']
    SURFACE_OPTIONS = [
        ('m', 'Maserrichtung'),
        ('u', 'Einfärbig')
    ]
    length = fields.Float(string='Länge in mm')
    width = fields.Float(string='Breite in mm')
    thickness = fields.Float(string='Dicke in mm', help='Echte Dicke in mm')
    height = fields.Float(string='Höhe in mm')
    surface = fields.Selection(SURFACE_OPTIONS, string='Oberfläche')
    is_internal = fields.Boolean()
    xcat_id = fields.Many2one(comodel_name='product.xcategory', string='X-Kategorie')
    material_type_id = fields.Many2one(comodel_name='material.type', string='Materialtyp')
    assembly_line_ids = fields.Many2many(comodel_name='res.line', string='Produktionslinien')
    notes = fields.Text(string='Notizen')
    can_be_sold_unconfigured = fields.Boolean(string='Darf unkonfiguriert verkauft werden')
    manufacturing_number = fields.Char(string='Herstellnummer')
    product_color = fields.Char(string='Farbe')
    suppl_ids = fields.One2many('product.supplierinfo', 'product_tmpl_id')
    @api.onchange('length', 'width', 'thickness', 'height')
    def _onchange_measures(self):
        if self.length>0 and self.width>0 and self.thickness>0:
            self.volume = self.length*self.width*self.thickness / (1000*1000*1000)
        elif self.length>0 and self.width>0 and self.height>0:
            self.volume = self.length*self.width*self.height / (1000*1000*1000)
    @api.model
    def create_product(self, vals):
        """
        SST-10
        :param vals:
        :return:
        """
        self.check_not_specified_fields(vals)
        vals = self.correct_values(vals)
        product_template = self.with_context(active_test=False).search([('default_code', '=', vals['default_code'])])
        pid = 0
        if product_template:
            # default_code may not be changed if there is already an inventory_line (in other company), so we remove it from the dict
            vals.pop('default_code',None)
            if product_template['manufacturing_number']:
                vals.pop('manufacturing_number',None)
            product_template.write(vals)
            pid = product_template.id
        else:
            if vals['active']:
                res = self.create(vals)
                pid = res.id
        return True, pid
    @api.model
    def correct_values(self, vals):
        if vals.get('xcat_id', False):
            xcat = self.env['product.xcategory'].search([('name', '=', vals['xcat_id'])])
            if xcat:
                vals['xcat_id'] = xcat.id
            else:
                raise ValidationError(
                    _("X-Kategorie \'%s\' kann nicht zugeordnet werden") % vals['xcat_id'])
        if vals.get('categ_id', False):
            categ_id = self.env['product.category'].search([('code', '=', vals['categ_id'])])
            if categ_id:
                vals['categ_id'] = categ_id.id
            else:
                raise ValidationError(
                    _("Kategorie \'%s\' kann nicht zugeordnet werden") % vals['categ_id'])
        if vals.get('material_type_id', False):
            material_type = self.env['material.type'].search([('name', '=', vals['material_type_id'])])
            if material_type:
                vals['material_type_id'] = material_type.id
            else:
                raise ValidationError(
                    _("Materialtyp \'%s\' kann nicht zugeordnet werden") % vals['material_type_id'])
        if vals.get('intrastat_id', False):
            intrastat = self.env['report.intrastat.code'].search([('name', '=', vals['intrastat_id'])])
            if intrastat:
                vals['intrastat_id'] = intrastat.id
            else:
                raise ValidationError(
                    _("Intrastat-Code \'%s\' kann nicht zugeordnet werden") % vals['intrastat_id'])
        if vals.get('assembly_line_ids', False):
            assembly_line_ids = []
            for assembly_line_code in vals['assembly_line_ids']:
                assembly_line = self.env['res.line'].search([('name', '=', assembly_line_code)])
                if assembly_line:
                    assembly_line_ids.append(assembly_line.id)
                else:
                    raise ValidationError(
                        _("Produktionslinie \'%s\' kann nicht zugeordnet werden") % assembly_line_code)
            vals['assembly_line_ids'] = [(6, 0, assembly_line_ids)]
        if vals.get('tax', False):
            if vals['tax'] not in ["20% MwSt.", "10% MwSt.", "0% MwSt."]:
                raise ValidationError(_("Die Steuer \'%s\' ist nicht gültig.") % vals['tax'])
            tax = self.env['account.tax'].search([('name', '=', vals['tax'])])
            if tax:
                vals['taxes_id'] = [(6, 0, [tax.id])]
            else:
                raise ValidationError(_("Die Steuer \'%s\' kann nicht zugeordnet werden") % vals['tax'])
        return vals
    @api.model
    def _get_specified_fields(self):
        return ['default_code', 'name', 'length', 'width', 'thickness', 'surface', 'active', 'weight', 'is_internal',
                'xcat_id', 'notes', 'material_type_id', 'intrastat_id', 'sale_ok', 'assembly_line_ids', 'list_price',
                'height', 'categ_id', 'can_be_sold_unconfigured', 'image', 'tax', 'manufacturing_number']
class ProductCategory(models.Model):
    _inherit = 'product.category'
    code = fields.Char(string='Code')
class ProductPricelistItemEventListener(Component):
    _name = 'product.pricelist.item.listener'
    _inherit = 'base.event.listener'
    _apply_on = ['product.pricelist.item']
#    pricelist_mode = 'partner'
    @api.model
    def on_record_write(self, record, fields=None):
        pricelist_mode = self.env['ir.config_parameter'].sudo().get_param('pricelist_mode')
        if pricelist_mode == 'partner':
            self.env['product.pricelist.item'].with_delay().job_mark_partner_for_export(record.pricelist_id.id)
        else:
#            self.env['product.pricelist.item'].with_delay().job_export_portal_pricelist(record.pricelist_id.id)
            self.env['product.pricelist.item'].job_export_portal_pricelist(record.pricelist_id.id)
    @api.model
    def on_record_create(self, record, fields=None):
        pricelist_mode = self.env['ir.config_parameter'].sudo().get_param('pricelist_mode')
        if pricelist_mode == 'partner':
            self.env['product.pricelist.item'].with_delay().job_mark_partner_for_export(record.pricelist_id.id)
        else:
            #            self.env['product.pricelist.item'].with_delay().job_export_portal_pricelist(record.pricelist_id.id)
            self.env['product.pricelist.item'].job_export_portal_pricelist(record.pricelist_id.id)
    @api.model
    def on_record_unlink(self, record):
        pricelist_mode = self.env['ir.config_parameter'].sudo().get_param('pricelist_mode')
        if pricelist_mode == 'partner':
            self.env['product.pricelist.item'].with_delay().job_mark_partner_for_export(record.pricelist_id.id)
        else:
            #            self.env['product.pricelist.item'].with_delay().job_export_portal_pricelist(record.pricelist_id.id)
            self.env['product.pricelist.item'].job_export_portal_pricelist(record.pricelist_id.id)
class ProductPricelistItem(models.Model):
    _inherit = 'product.pricelist.item'
    applied_on = fields.Selection(selection=[
        ('3_global', 'Global'),
        ('2_product_category', ' Product Category'),
        ('0_product_variant', 'Product Variant')])
    @api.multi
    @job
    def job_mark_partner_for_export(self, pricelist_id):
        partners = self.env['res.partner'].search([('portal_id', '!=', False)])
        todo_partner = self.env['res.partner']
        for partner in partners:
            # Search ist auf die Preisliste nicht möglich, daher wird jeder Partner einzeln verglichen
            if partner.property_product_pricelist.id == pricelist_id and partner.company_type == 'company':
                todo_partner |= partner
        todo_partner.write({
            'portal_export_pending': True
        })
    @api.multi
    @job
    def job_export_portal_pricelist(self, pricelist_id):
        """
        SST-02a
        :param pricelist_id:
        :return:
        """
        pricelist = self.env['product.pricelist'].search([('id', '=', pricelist_id)])
        data_pos = []
        for item in pricelist.item_ids:
            if item.compute_price == 'percentage' and item.applied_on in ['3_global', '2_product_category',
                                                                          '0_product_variant']:
                code = False
                if item.applied_on == '2_product_category':
                    code = item.categ_id.code
                if item.applied_on == '0_product_variant':
                    code = item.product_id.product_tmpl_id.default_code
                data_pos.append({
                    'code': code,
                    'name': item.name,
                    'discount': 1 - (item.percent_price / 100)
                })
        if data_pos:
            data = {'pricelist_id': pricelist.id,
                'pricelist_name': pricelist.name,
                'items': data_pos}
            portal_url = tools.config.get('portal_url')
            application_id = tools.config.get('portal_secret')
            response = requests.post(portal_url + '/api/v1/update-pricelist/?secret=' + application_id,
                                     data=json.dumps(data))
            if response.status_code != 200:
                try:
                    data = response.json()
                    error_string = data.get('errors', [])
                except:
                    error_string = response.reason
                raise ValidationError(_('Meldung vom Portal: Rabatt konnte nicht gesetzt werden. '
                                        'Status Code: %s, Reason: %s') % (response.status_code, error_string))