# BFH Science Self-Service Portal
# Copyright (C) 2025-2026 IKUS Software
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.

from datetime import datetime
from email.utils import formataddr

import cherrypy
from cherrypy.process.plugins import SimplePlugin
from cherrypy_foundation.tools.i18n import gettext as _

UNDEFINED = object()


def _format_recipient(value):
    """
    Make sure to ouput a valid recipient address that include `Name <address>`.
    """
    if not value:
        return None
    elif isinstance(value, str):
        return value
    elif hasattr(value, 'email') and hasattr(value, 'name'):
        # User object
        return formataddr((value.name, value.email))
    elif isinstance(value, list):
        return ', '.join([_format_recipient(v) for v in value if v])
    raise TypeError('expect a string, a user object or list of user object: %r' % (value,))


class NotifiationPlugin(SimplePlugin):
    """
    Plugin responsible to handle request send by email or directly to ITS (Znuny).
    """

    env = None

    def start(self):
        self.bus.log('Start Notification plugins')

    def stop(self):
        self.bus.log('Stop Notification plugins')

    def _render_subject_and_html_body(
        self, user, form, request_date, external=False, ticket_number=None, ticket_url=None
    ):
        # Format subject
        subject = str(getattr(form, 'subject', _("Request from user {username}").format(username=user.username)))
        service = getattr(form, 'service', 'undefined')
        if ticket_number:
            full_subject = _("[Ticket#{ticket_number}] SSP: {service} - {subject}").format(
                service=service, subject=subject, ticket_number=ticket_number
            )
        else:
            full_subject = _("SSP: {service} - {subject}").format(service=service, subject=subject)
        # Render email template
        tmpl = self.env.get_template("email_request.html")
        body = tmpl.render(
            user=user,
            form=form,
            request_date=request_date,
            external=external,
            ticket_number=ticket_number,
            ticket_url=ticket_url,
        )
        return full_subject, body

    def send_request(self, user, form):
        request_date = datetime.today()
        custom_recipient = getattr(form, 'recipient', False)

        # Send request to ITS Or group managers.
        if custom_recipient:
            # For custom recipient, we skip ITS.
            # We only send emails to everybody.
            subject, body = self._render_subject_and_html_body(user, form, request_date, external=True)
            self._send_mail(
                to=custom_recipient,
                subject=subject,
                body=body,
                cc=user,
                reply_to=user,
            )
        else:
            # Step 1 - Send ticket creation to custom recipient or ITS.
            subject, body = self._render_subject_and_html_body(user, form, request_date)
            service = getattr(form, 'service', "LNI Compute")
            response = cherrypy.znuny.create_ticket(
                title=subject,
                queue="ITS::LNI",
                state="new",
                priority="3 normal",
                type="ServiceRequest",
                customer_user=user.username,
                service=service,
                body=body,
                mime_type="text/html",
                sender_type="customer",
                is_visible_for_customer=1,
                communication_channel='Email',
                _from=user.email,
                to=user.email,
            )
            # Step 2 - Send copy of the request to the requester With TicketNumber
            subject, body = self._render_subject_and_html_body(
                user,
                form,
                request_date,
                external=True,
                ticket_number=response.ticket_number,
                ticket_url=response.ticket_url,
            )
            self._send_mail(to=user, subject=subject, body=body)
            return response

    def _send_mail(self, subject, body, to=None, cc=None, reply_to=None):
        """
        Send email to the given recipient. Wrapper arround smtp `send_mail` to format recipient using User object.
        """
        self.bus.publish(
            'send_mail',
            to=_format_recipient(to),
            cc=_format_recipient(cc),
            reply_to=_format_recipient(reply_to),
            subject=subject,
            message=body,
        )


cherrypy.notification = NotifiationPlugin(cherrypy.engine)
cherrypy.notification.subscribe()

cherrypy.config.namespaces['notification'] = lambda key, value: setattr(cherrypy.notification, key, value)
