# Copyright 2021 Le Filament (<http://www.le-filament.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

import base64
import json

from odoo import api, models
from odoo import fields as odooFields
from odoo.addons.cmis_field import fields
from odoo.exceptions import UserError


class AccountInvoice(models.Model):
    _name = 'account.invoice'
    _inherit = ['account.invoice', 'lefilament.alfresco']

    # ------------------------------------------------------
    # Fields declaration
    # ------------------------------------------------------
    project_id = odooFields.Many2one(
        'project.project',
        string='Projet',
        change_default=True,
        readonly=True,
        states={'draft': [('readonly', False)]},
        track_visibility='always',
        ondelete='restrict',)
    num_dossier = odooFields.Char(related="project_id.num_dossier")
    type_convention_id = odooFields.Many2one(
        "adefpat.type.convention",
        related="project_id.type_convention_id",
        string="Type de convention de financement",
    )
    alfresco_file = odooFields.Char("Facture liée")
    cmis_folder = fields.CmisFolder(
        allow_create=True,
        allow_delete=False,
    )
    task_ids = odooFields.One2many(
        "project.task",
        "invoice_id",
        string="Séances liées",
    )
    partner_id_domain = odooFields.Char(
        compute="_compute_partner_id_domain",
        readonly=True,
        store=False,
    )
    task_ids_domain = odooFields.Char(
        compute="_compute_task_ids_domain",
        readonly=True,
        store=False,
    )
    amount_task_total = odooFields.Monetary(
        string='Total Séances', store=True,
        readonly=True, compute='_compute_amount_task_total')

    @api.one
    @api.depends('task_ids', 'task_ids.cout_seance')
    def _compute_amount_task_total(self):
        if self.type == "in_invoice":
            self.amount_task_total = sum(
                line.cout_seance for line in self.task_ids)

    @api.depends('project_id')
    def _compute_partner_id_domain(self):
        """
        Crée un domaine dynamique pour les CF
        """
        if self.type == "in_invoice":
            domain = [('is_consultant_form', '=', True)]
            if self.project_id:
                formateur_ids = self.env["project.task"].search(
                    [("project_id", "=", self.project_id.id)]
                ).mapped("formateur_id")
                domain.append(('id', 'in', formateur_ids.ids))
            self.partner_id_domain = json.dumps(domain)

    @api.depends('project_id', 'partner_id')
    def _compute_task_ids_domain(self):
        """
        Crée un domaine dynamique pour les séances
        """
        if self.type == "in_invoice":
            domain = []
            dom = []
            if self.project_id:
                dom.append(("project_id", "=", self.project_id.id))
            if self.partner_id:
                dom.append(("formateur_id", "=", self.partner_id.id))
            task_ids = self.env["project.task"].search(dom)
            domain.append(('id', 'in', task_ids.ids))
            self.task_ids_domain = json.dumps(domain)

    # ------------------------------------------------------
    # SQL Constraints
    # ------------------------------------------------------

    # ------------------------------------------------------
    # Default methods
    # ------------------------------------------------------

    # ------------------------------------------------------
    # Computed fields / Search Fields
    # ------------------------------------------------------

    # ------------------------------------------------------
    # Onchange / Constraints
    # ------------------------------------------------------

    # ------------------------------------------------------
    # CRUD methods (ORM overrides)
    # ------------------------------------------------------
    @api.model
    def _prepare_refund(self, invoice, date_invoice=None, date=None, description=None, journal_id=None):
        values = super(AccountInvoice, self)._prepare_refund(invoice, date_invoice, date, description, journal_id)
        if invoice.project_id:
            values['project_id'] = invoice.project_id.id
        return values

    # ------------------------------------------------------
    # Actions
    # ------------------------------------------------------
    @api.multi
    def generate_alfresco_file(self):
        """
            Ajoute un fichier sur la GED Alfresco
            @return: fonction get_partner_files() de res.partner
        """
        # Get proof folder nodeRef
        backend = self.env['cmis.backend'].search([], limit=1)
        # Si la facture a déjà été créée, ouvrir dans Alfresco
        if self.alfresco_file:
            prop = backend.get_cmis_repository().getFolder(
                self.alfresco_file).getProperties()
            url = backend.get_content_details_url_from_props(prop)
        # Sinon, la créer, puis la stocker ainsi que les documents liées à la facture dans Alfresco
        else:
            project_folder = self.project_id.cmis_folder
            self.cmis_folder = project_folder

            if not project_folder:
                raise UserError("Le dossier du projet n'est pas configuré")

            # Get Mimetype
            attachment = self.env.ref('account.account_invoices').retrieve_attachment(self)
            if not attachment:
                raise UserError("La facture n'a pas encore été générée. Imprimer la facture pour pouvoir la visualiser dans Alfresco")

            content_type = attachment.mimetype

            path_proj = backend.get_cmis_repository().getFolder(
                project_folder).getPaths()

            # Get template doc Facture
            template_doc = self.env['adefpat.template.doc'].search([
                ('type_temp', '=', 'facture'),
                ('noderef_document', '=', False)])

            # Get doc linked to Facture
            template_doc_ids = self.env['adefpat.template.doc'].search([
                ('type_temp', '=', 'facture'),
                ('noderef_document', '!=', False)])

            # Strore template in Alfresco
            for template in template_doc_ids:
                keys = self.fill_data()
                self._publipostage_documents(template, keys, False)

            path_n0 = path_proj + [template_doc.dossier.name]
            path = '/'.join(path_n0)
            cmis_obj = backend.get_folder_by_path(path)

            file = cmis_obj.createDocument(
                name=attachment.name,
                properties={},
                contentFile=base64.b64decode(attachment.datas),
                contentType=content_type
            )
            file_id = file.getProperties().get('cmis:objectId')
            self.alfresco_file = file.getObjectId()
            prop = backend.get_cmis_repository().getFolder(
                file_id).getProperties()
            url = backend.get_content_details_url_from_props(prop)
        return {
            'type': 'ir.actions.act_url',
            'url': url,
            'target': 'new',
        }
    # ------------------------------------------------------
    # Business methods
    # ------------------------------------------------------
    def fill_data(self):

        parser = [
            ('partner_id:name_benef', ['name']),
            ('partner_id:title_benef', [('title', ['name'])]),
            ('partner_id:zip_benef', ['zip']),
            ('partner_id:city_benef', ['city']),
            ('partner_id:street_benef', ['street']),
            ('project_id:cfd_name', [('user_id', ['name'])]),
            ('project_id:cfd_mobile', [('user_id', ['mobile'])]),
            ('project_id:project_name', ['name']),
            'amount_total:montant',
            'date_invoice:date',
        ]

        keys = self.json_build(parser)[0]
        return keys