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

import logging
from datetime import datetime, timedelta
from uuid import uuid4

from odoo import _, api, fields, models

_logger = logging.getLogger(__name__)


class VaultShare(models.Model):
    _name = "vault.share"
    _description = _("Vault share outgoing secrets")

    user_id = fields.Many2one("res.users", default=lambda self: self.env.uid)
    name = fields.Char(required=True)
    share_link = fields.Char(
        "Share URL",
        compute="_compute_url",
        store=False,
        help="Using this link and pin people can access the secret.",
    )
    token = fields.Char(readonly=True, required=True, default=lambda self: uuid4())
    secret = fields.Char()
    secret_file = fields.Char()
    filename = fields.Char()
    salt = fields.Char(required=True)
    iterations = fields.Integer()
    iv = fields.Char(required=True)
    pin = fields.Char(required=True, help="The pin needed to decrypt the share.")
    accesses = fields.Integer(
        "Access counter",
        default=5,
        help="Specifies how often a share can be accessed before deletion.",
    )
    expiration = fields.Datetime(
        default=lambda self: datetime.now() + timedelta(days=7),
        help="Specifies how long a share can be accessed until deletion.",
    )
    log_ids = fields.One2many("vault.share.log", "share_id", "Log", readonly=True)

    _sql_constraints = [
        (
            "value_check",
            "CHECK(secret IS NOT NULL OR secret_file IS NOT NULL)",
            _("No value found"),
        ),
    ]

    @api.depends("token")
    def _compute_url(self):
        base_url = self.env["ir.config_parameter"].sudo().get_param("web.base.url")
        for rec in self:
            rec.share_link = f"{base_url}/vault/share/{rec.token}"

    @api.model
    def get(self, token, ip=None):
        rec = self.search([("token", "=", token)], limit=1)
        if not rec:
            return rec

        if datetime.now() < rec.expiration and rec.accesses > 0:
            rec.accesses -= 1
            log = _("The share was accessed by %(name)s via %(ip)s")
            rec.log_ids = [
                (0, 0, {"name": log % {"name": self.env.user.name, "ip": ip or "n/a"}})
            ]
            return rec

        return None

    @api.model_create_multi
    def create(self, vals_list):
        res = super().create(vals_list)
        log = _("The share was created by %(name)s")
        for rec in res:
            rec.log_ids = [(0, 0, {"name": log % {"name": self.env.user.name}})]
        return res

    @api.model
    def clean(self):
        now = datetime.now()
        offset = timedelta(days=self.env.company.vault_share_delay)
        self.search([("expiration", "<=", now + offset)]).unlink()
