# 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 unittest import mock

import responses
from parameterized import parameterized
from responses import matchers

from . import WebCase

TICKET_CREATE_URL = 'https://znuny.example.com/otrs/nph-genericinterface.pl/Webservice/rest-api/TicketCreate'


class CommonRequestHandlerTest(WebCase):

    login = True

    default_config = {
        'znuny-ticket-create-url': TICKET_CREATE_URL,
        'znuny-userlogin': 'myuser',
        'znuny-password': 'test123',
    }

    @parameterized.expand(
        [
            (
                'valid_wlan',
                {'resource': 'WLAN', 'reason': 'something'},
                'SSP: LNI Network - Request access to WLAN',
                'LNI Network',
            ),
            (
                'valid_vpn',
                {'resource': 'VPN', 'reason': 'something'},
                'SSP: LNI Infrastructure - Request access to VPN',
                'LNI Infrastructure',
            ),
            (
                'valid_ssh_jumphost',
                {'resource': 'SSH Jumphost', 'reason': 'something'},
                'SSP: LNI Infrastructure - Request access to SSH Jumphost',
                'LNI Infrastructure',
            ),
            (
                'valid_nextcloud',
                {'resource': 'Nextcloud', 'reason': 'something'},
                'SSP: LNI Compute - Request access to Nextcloud',
                'LNI Compute',
            ),
            (
                'valid_ssp',
                {'resource': 'Self-Service Portal', 'reason': 'something'},
                'SSP: LNI Compute - Request access to Self-Service Portal',
                'LNI Compute',
            ),
            (
                'invalid_empty_reason',
                {'resource': 'Nextcloud', 'reason': ''},
                False,
                False,
            ),
            (
                'invalid_resource',
                {'resource': 'invalid', 'reason': 'something'},
                False,
                False,
            ),
            (
                'invalid_reason',
                {'resource': 'Nextcloud', 'reason': 'too long' * 100},
                False,
                False,
            ),
        ]
    )
    def test_request_access(self, name, data, expected_subject, expected_service):
        # Mock ticket creation for valid Service.
        self.responses.add(
            responses.POST,
            TICKET_CREATE_URL,
            json={'TicketID': '1234', 'TicketNumber': '0987654321'},
            status=200,
            match=[
                matchers.json_params_matcher(
                    {"Ticket": {"Title": expected_subject, "Service": expected_service}}, strict_match=False
                )
            ],
        )
        # Given a user
        # When user request a new compute
        self.getPage(
            "/dashboard/request-access",
            body=data,
            method='POST',
        )
        # Then user is redirect
        self.assertStatus(303)
        self.assertHeaderItemValue('Location', f'{self.baseurl}/dashboard')
        # Then an email get send to ITS
        if expected_subject:
            # Then dashboard page show success
            self.getPage("/dashboard/")
            self.assertStatus(200)
            self.assertInBody(
                'Success! Your request has been logged as ticket <a href="https://znuny.example.com/otrs/index.pl?Action=AgentTicketZoom;TicketID=1234" target="_blank">#0987654321</a>. A copy has been emailed to you.'
            )
            # Then a request was sent to znuny
            self.responses.assert_all_requests_are_fired = True
            # Then email send to the user it self.
            self.listener.send_mail.assert_called_once_with(
                to='test@example.com',
                cc=None,
                reply_to=None,
                subject=f"[Ticket#0987654321] {expected_subject}",
                message=mock.ANY,
            )
        else:
            self.responses.assert_all_requests_are_fired = False
            # Then email are not sent.
            self.assertEqual(self.listener.send_mail.call_count, 0)
            # Then dashboard page show failure
            self.getPage("/dashboard/")
            self.assertStatus(200)
            self.assertNotInBody("Success! Your request has been logged as")
            self.assertInBody("alert alert-danger")

    @parameterized.expand(
        [
            (
                'valid_resource',
                {'resource': 'something', 'resource_service': 'LNI Network', 'message': 'something'},
                'SSP: LNI Network - Support Request',
                'LNI Network',
            ),
            (
                'invalid_service',
                {'resource': 'VPN', 'resource_service': 'LNI Invalid', 'message': 'something'},
                False,
                False,
            ),
            (
                'invalid_empty_message',
                {'resource': 'VPN', 'resource_service': 'LNI Network', 'message': ''},
                False,
                False,
            ),
        ]
    )
    def test_request_support(self, name, data, expected_subject, expected_service):
        # Mock ticket creation for valid Service.
        self.responses.add(
            responses.POST,
            TICKET_CREATE_URL,
            json={'TicketID': '1234', 'TicketNumber': '0987654321'},
            status=200,
            match=[
                matchers.json_params_matcher(
                    {"Ticket": {"Title": expected_subject, "Service": expected_service}}, strict_match=False
                )
            ],
        )
        # Given a user
        # When user request a new compute
        self.getPage(
            "/dashboard/request-support",
            body=data,
            method='POST',
        )
        # Then user is redirect
        self.assertStatus(303)
        self.assertHeaderItemValue('Location', f'{self.baseurl}/dashboard')
        # Then an email get send to ITS
        if expected_subject:
            # Then dashboard page show success
            self.getPage("/dashboard/")
            self.assertStatus(200)
            self.assertInBody(
                'Success! Your request has been logged as ticket <a href="https://znuny.example.com/otrs/index.pl?Action=AgentTicketZoom;TicketID=1234" target="_blank">#0987654321</a>. A copy has been emailed to you.'
            )
            # Then email send to the user it self.
            self.listener.send_mail.assert_called_once_with(
                to='test@example.com',
                cc=None,
                reply_to=None,
                subject=f"[Ticket#0987654321] {expected_subject}",
                message=mock.ANY,
            )
        else:
            self.responses.assert_all_requests_are_fired = False
            # Then email are not sent.
            self.assertEqual(self.listener.send_mail.call_count, 0)
            # Then dashboard page show failure
            self.getPage("/dashboard/")
            self.assertStatus(200)
            self.assertNotInBody(
                "Success! Your request has been logged as ticket #0987654321. A copy has been emailed to you."
            )
            self.assertInBody("alert alert-danger")
