# © 2021 Florian Kantelberg - initOS GmbH
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

import json
import logging
from datetime import datetime

from odoo import _, api, fields, models

_logger = logging.getLogger(__name__)


class ExportWizard(models.TransientModel):
    _name = "vault.export.wizard"
    _description = _("Export wizard for vaults")

    vault_id = fields.Many2one("vault", "Vault")
    entry_id = fields.Many2one(
        "vault.entry", "Entries", domain="[('vault_id', '=', vault_id)]"
    )
    master_key = fields.Char(related="vault_id.master_key")
    name = fields.Char(default=lambda self: self._default_name())
    content = fields.Binary("Download", attachment=False)
    include_childs = fields.Boolean(default=True)

    @api.onchange("vault_id", "entry_id")
    def _onchange_content(self):
        for rec in self.with_context(skip_log=True):
            rec.content = self._export_content(
                rec.vault_id,
                rec.entry_id,
                rec.include_childs,
            )

    def _default_name(self):
        return datetime.now().strftime("database-%Y%m%d-%H%M.json")

    def _export_content(self, vault=None, entry=None, include_childs=False):
        if entry:
            entries = entry
        elif vault:
            entries = vault.entry_ids.filtered_domain([("parent_id", "=", False)])
        else:
            return json.dumps([])

        data = [self._export_entry(x, include_childs) for x in entries]
        return json.dumps(data)

    @api.model
    def _export_field(self, rec):
        def ensure_string(x):
            return x.decode() if isinstance(x, bytes) else x

        return {f: ensure_string(rec[f]) for f in ["name", "iv", "value"]}

    @api.model
    def _export_entry(self, entry, include_childs=False):
        if include_childs:
            childs = [self._export_entry(x, include_childs) for x in entry.child_ids]
        else:
            childs = []

        return {
            "uuid": entry.uuid,
            "name": entry.name,
            "note": entry.note,
            "url": entry.url,
            "fields": entry.field_ids.mapped(self._export_field),
            "files": entry.file_ids.mapped(self._export_field),
            "childs": childs,
        }
