# Copyright © 2023 Garazd Creation (https://garazd.biz)
# @author: Yurii Razumovskyi (support@garazd.biz)
# @author: Iryna Razumovska (support@garazd.biz)
# License OPL-1 (https://www.odoo.com/documentation/15.0/legal/licenses.html).

from typing import List

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


class PrintProductLabel(models.TransientModel):
    _inherit = "print.product.label"

    report_id = fields.Many2one(
        default=lambda self: self.env.ref('garazd_product_label.action_report_product_label_from_template'),
    )
    template_id = fields.Many2one(
        comodel_name='print.product.label.template',
        # flake8: noqa: E501
        default=lambda self: self.env.user.print_label_template_id or self.env['print.product.label.template'].search([], limit=1),
    )
    allowed_template_ids = fields.Many2many(
        comodel_name='print.product.label.template',
        compute='_compute_allowed_template_ids',
        help='Technical field to restrict allowed label templates.',
    )
    allowed_template_count = fields.Integer(compute='_compute_allowed_template_ids', help='Technical field.')
    template_preview_html = fields.Html(
        compute='_compute_template_preview_html',
        compute_sudo=True,
    )
    label_template_preview = fields.Boolean(help='Show Label Template Sample.')
    pricelist_id = fields.Many2one(
        comodel_name='product.pricelist',
    )
    sale_pricelist_id = fields.Many2one(
        comodel_name='product.pricelist',
        string='Sales Pricelist',
        help='Specify this second pricelist to put one more product price to a label.',
    )
    skip_place_count = fields.Integer(
        string='Skip Places',
        default=0,
        help='Specify how many places for labels should be skipped on printing. This can'
             ' be useful if you are printing on a sheet with labels already printed.',
    )
    label_type_id = fields.Many2one(
        help='You can filter label templates by selecting their type. It makes sense if you use '
             'additional extensions to print labels not for products only but for other objects as well. '
             'Like as Stock Packages, Sales Orders, Manufacturing Orders, etc. '
             '>>> To view available extensions go to the "Actions" menu and click to the "Get Label Extensions".',
        # default=lambda self: self.env.ref('garazd_product_label.type_product'),
        # required=True,
    )
    show_template_limit = fields.Integer(compute='_compute_allowed_template_ids')

    @api.depends('label_type_id')
    def _compute_allowed_template_ids(self):
        for wizard in self:
            user_allowed_templates = self.env['print.product.label.template']._get_user_allowed_templates()
            allowed_templates = user_allowed_templates.filtered(lambda lt: lt.type_id == wizard.label_type_id)
            ## Add templates without the specified type
            # if wizard.mode == 'product.product':
            #     allowed_templates += user_allowed_templates.filtered(lambda lt: not lt.type_id)
            wizard.allowed_template_ids = [Command.set(allowed_templates.ids)]
            wizard.allowed_template_count = len(allowed_templates)
            # flake8: noqa: E501
            wizard.show_template_limit = self.env['ir.config_parameter'].sudo().get_param('garazd_product_label.show_label_template_limit', 7)

    @api.depends('template_id', 'pricelist_id', 'sale_pricelist_id', 'lang')
    def _compute_template_preview_html(self):
        for wizard in self:
            products = wizard.label_ids.mapped('product_id')
            wizard.template_id.with_context(print_product_id=products[:1].id)._compute_preview_html()
            wizard.template_preview_html = wizard.with_context(**{
                'print_wizard_id': wizard.id,  # It allows previewing real products on label designing
                'preview_mode': True,  # It's used to avoid generating of a shorten URL
                'pricelist_id': wizard.pricelist_id.id,  # It's used for previewing on label designing
                'sale_pricelist_id': wizard.sale_pricelist_id.id,  # It's used for previewing on label designing
                'lang': wizard.lang or self._context.get('lang'),
            }).template_id.preview_html

    @api.onchange('label_type_id')
    def _onchange_label_type_id(self):
        for wizard in self:
            user_template = self.env.user.print_label_template_id
            if user_template and user_template.id in wizard.allowed_template_ids.ids:
                wizard.template_id = user_template.id
            else:
                wizard.template_id = wizard.allowed_template_ids[0].id if wizard.allowed_template_ids else False
            wizard._compute_template_preview_html()

    def _get_label_data(self):
        self.ensure_one()
        labels = self.get_labels_to_print()
        if not self.is_template_report:
            return {'ids': labels.ids, 'data': {}}
        if not self.template_id:
            raise UserError(_('Select the label template to print.'))
        self.template_id._set_paperformat()
        label_data = {
            'ids': labels.ids,
            'data': {
                'rows': self.template_id.rows,
                'cols': self.template_id.cols,
                'row_gap': self.template_id.row_gap,
                'col_gap': self.template_id.col_gap,
                'label_style':
                    'overflow: hidden;'
                    'font-family: "Arial";'
                    'width: %(width).2fmm;'
                    'height: %(height).2fmm;'
                    'padding: %(padding_top).2fmm %(padding_right).2fmm'
                    ' %(padding_bottom).2fmm %(padding_left).2fmm;'
                    'border: %(border)s;'
                    '%(custom_style)s' % {
                        'width': self.template_id.width,
                        'height': self.template_id.height,
                        'padding_top': self.template_id.padding_top,
                        'padding_right': self.template_id.padding_right,
                        'padding_bottom': self.template_id.padding_bottom,
                        'padding_left': self.template_id.padding_left,
                        'border': "%dpx solid #EEE" % self.border_width
                        if self.border_width else 0,
                        'custom_style': self.template_id.label_style or '',
                    },
                'skip_places': self.skip_place_count,
            },
        }
        # Add extra styles for multi labels
        if self.template_id.cols != 1 or self.template_id.rows != 1:
            label_data['data']['label_style'] += 'float: left;'
        return label_data

    def _get_report_action_params(self):
        ids, data = super(PrintProductLabel, self)._get_report_action_params()
        if self.is_template_report:
            ids = None
            data = self._get_label_data()
        return ids, data

    @api.model
    def get_quick_report_action(
            self, model_name: str, ids: List[int], qty: int = None, template=None,
            force_direct: bool = False, close_window: bool = False,
    ):
        """ Overwritten completely to use with custom label templates. """
        template = template or self.env.user.print_label_template_id
        if not template:
            raise UserError(_('Specify a label template for the current user to print custom labels.'))
        wizard = self.with_context(**{
            'active_model': model_name,
            f'default_{model_name.replace(".", "_")}_ids': ids,
        }).create({
            'report_id': self.env.ref('garazd_product_label.action_report_product_label_from_template').id,
            'template_id': template.id,
        })

        if isinstance(qty, int):
            wizard.label_ids.write({'qty': qty, 'qty_initial': qty})

        report_action = wizard.action_print()
        if close_window:
            report_action.update({'close_on_report_download': True})

        return wizard.action_print_direct() if self.env.user.print_label_directly or force_direct else report_action

    def action_add_template(self):
        self.ensure_one()
        return {
            'name': _('Add a New Label Template'),
            'type': 'ir.actions.act_window',
            'res_model': 'print.product.label.template.add',
            'view_mode': 'form',
            'target': 'new',
        }

    def action_edit_template(self):
        self.ensure_one()
        return {
            'type': 'ir.actions.act_window',
            'res_model': self.template_id._name,
            'res_id': self.template_id.id,
            'view_mode': 'form',
        }

    def action_reset_skip(self):
        """Reset the skip empty places count value. """
        self.ensure_one()
        self.write({'skip_place_count': 0})

    @api.model
    def open_extension_app_list(self):
        return {
            'type': 'ir.actions.act_url',
            'url': 'https://apps.odoo.com/apps/browse?repo_maintainer_id=119796&search=garazd_product_label_',
            'target': 'new',
            'target_type': 'public',
        }

    @api.model
    def _pdf_preview(self, label_data: bytes):
        preview = self.env['print.product.label.preview'].sudo().create({'label_pdf': label_data})
        return {
            'name': _('Label Preview'),
            'type': 'ir.actions.act_window',
            'view_mode': 'form',
            'res_model': preview._name,
            'res_id': preview.id,
            'target': 'new',
        }

    def action_pdf_preview(self):
        self.ensure_one()
        return self._pdf_preview(self.get_pdf())
