# Copyright (C) 2022 Cetmix OÜ
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging

from ansi2html import Ansi2HTMLConverter

from odoo import _, api, fields, models
from odoo.exceptions import AccessError

_logger = logging.getLogger(__name__)

html_converter = Ansi2HTMLConverter(inline=True)


class CxTowerServerLog(models.Model):
    """Server log management.
    Used to track various server logs.
    N.B. Do not mistake for command of flight plan log!
    """

    _name = "cx.tower.server.log"
    _inherit = ["cx.tower.access.mixin", "cx.tower.reference.mixin"]
    _description = "Cetmix Tower Server Log"

    NO_LOG_FETCHED_MESSAGE = _("<log is empty>")

    active = fields.Boolean(default=True)
    server_id = fields.Many2one(
        "cx.tower.server",
        ondelete="cascade",
        compute="_compute_server_id",
        index=True,
        store=True,
        readonly=False,
        copy=False,
    )
    log_type = fields.Selection(
        selection=lambda self: self._selection_log_type(),
        required=True,
        groups="cetmix_tower_server.group_root,cetmix_tower_server.group_manager",
        default=lambda self: self._selection_log_type()[0][0],
    )
    command_id = fields.Many2one(
        "cx.tower.command",
        domain="[('action', 'in', ['ssh_command', 'python_code']), "
        "'|', ('server_ids', 'in', [server_id]), ('server_ids', '=', False)]",
        groups="cetmix_tower_server.group_root,cetmix_tower_server.group_manager",
        help="Command that will be executed to get the log data.\n"
        "Be careful with commands that don't support parallel execution!",
    )
    use_sudo = fields.Boolean(
        groups="cetmix_tower_server.group_root,cetmix_tower_server.group_manager",
        help="Will use sudo based on server settings."
        "If no sudo is configured will run without sudo",
    )
    file_id = fields.Many2one(
        "cx.tower.file",
        domain="[('server_id', '=', server_id)]",
        groups="cetmix_tower_server.group_root,cetmix_tower_server.group_manager",
        help="File that will be executed to get the log data",
        copy=False,
    )
    log_text = fields.Text(readonly=True, copy=False)
    log_html = fields.Html(compute="_compute_log_html")

    # --- Server template related
    server_template_id = fields.Many2one("cx.tower.server.template", ondelete="cascade")
    file_template_id = fields.Many2one(
        "cx.tower.file.template",
        ondelete="cascade",
        groups="cetmix_tower_server.group_root,cetmix_tower_server.group_manager",
        help="This file template will be used to create log files"
        " when server is created from a template",
    )

    # -- Jet Template related
    jet_template_id = fields.Many2one(
        "cx.tower.jet.template",
        ondelete="cascade",
        index=True,
        help="This jet template will be used to create log files when jet is created",
    )

    # -- Jet related
    jet_id = fields.Many2one(
        "cx.tower.jet",
        ondelete="cascade",
        index=True,
    )

    @api.depends("jet_id")
    def _compute_server_id(self):
        for record in self:
            if not record.server_id and record.jet_id:
                record.server_id = record.jet_id.server_id.id

    def _selection_log_type(self):
        """Actions that can be run by a command.

        Returns:
            List of tuples: available options.
        """
        return [
            ("command", "Command"),
            ("file", "File"),
        ]

    @api.depends("log_text")
    def _compute_log_html(self):
        for record in self:
            if record.log_text:
                try:
                    record.log_html = html_converter.convert(record.log_text)
                # We catch all exceptions to avoid breaking the log display
                except Exception as e:
                    _logger.error("Error converting log text to HTML: %s", e)
                    record.log_html = False
            else:
                record.log_html = False

    def copy(self, default=None):
        return super(
            CxTowerServerLog, self.with_context(reference_mixin_skip_self=True)
        ).copy(default)

    def action_open_log(self):
        """
        Open log record in current window
        """
        self.ensure_one()
        self.action_update_log()
        return {
            "type": "ir.actions.act_window",
            "name": self.name,
            "res_model": "cx.tower.server.log",
            "res_id": self.id,  # pylint: disable=no-member
            "view_mode": "form",
            "target": "current",
        }

    def write(self, vals):
        """Override to protect log_text from direct modifications.
        Bypass with context key 'cx_allow_log_text_update' for internal updates.
        """
        if "log_text" in vals and not self.env.context.get("cx_allow_log_text_update"):
            raise AccessError(_("You are not allowed to modify the server log output."))
        return super().write(vals)

    def action_update_log(self):
        """Update log text from source"""

        # We are using `sudo` to override command/file access limitations
        for rec in self.sudo().with_context(cx_allow_log_text_update=True):
            rec.log_text = rec._get_formatted_log_text()

    def _get_log_text(self):
        """
        Get log text from source
        Use this function to get pure log text from source.

        Returns:
            Text: log text
        """
        self.ensure_one()
        if self.log_type == "file" and self.file_id:
            return self._get_log_from_file()
        elif self.log_type == "command" and self.command_id:
            return self._get_log_from_command()

    def _get_formatted_log_text(self):
        """
        Get formatted log text.
        Use this function to get formatted log text.

        Returns:
            Text: formatted log text
        """
        log_text = self._get_log_text()
        if log_text:
            return self._format_log_text(log_text)
        return self.NO_LOG_FETCHED_MESSAGE

    def _format_log_text(self, log_text):
        """
        Format log text.
        Use this function to format log text.

        Returns:
            Text: formatted log text
        """
        # Remove the null bytes
        return log_text.replace("\x00", "")

    def _get_log_from_file(self):
        """Get log from a file.
        Override this function to implement custom log handler

        Returns:
            Text: log text
        """
        self.ensure_one()
        if self.file_id.source == "server":
            self.file_id.download(raise_error=False)
            return self.file_id.code
        if self.file_id.source == "tower":
            result = self.file_id.action_get_current_server_code()
            if isinstance(result, dict):
                return
            return self.file_id.code_on_server

    def _get_log_from_command(self):
        """Get log from a command.
        Returns:
            Text: log text
        """
        self.ensure_one()

        use_sudo = self.use_sudo and self.server_id.use_sudo
        command_result = self.server_id.with_context(no_command_log=True).run_command(
            self.command_id,
            jet=self.jet_id,
            jet_template=self.jet_template_id,
            sudo=use_sudo,
        )
        log_text = self.NO_LOG_FETCHED_MESSAGE
        if command_result:
            response = command_result["response"]
            error = command_result["error"]
            if response:
                log_text = response
            elif error:
                log_text = error
        return log_text

    def _get_copied_name(self, force_name=None):
        # Original name is preserved when log is duplicated
        return force_name or self.name
