# Cherrypy-foundation
# Copyright (C) 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/>.
import importlib
import os
from unittest import skipIf, skipUnless

import cherrypy
from cherrypy.test import helper
from parameterized import parameterized

import cherrypy_foundation.tools.jinja2  # noqa
from cherrypy_foundation.components import StaticMiddleware
from cherrypy_foundation.tests import SeleniumUnitTest
from cherrypy_foundation.url import url_for

HAS_JINJAX = importlib.util.find_spec("jinjax") is not None

VENDOR_TEST = os.environ.get('VENDOR_TEST', None)

env = cherrypy.tools.jinja2.create_env(
    package_name=__package__,
)


class Static:

    components = StaticMiddleware()


@cherrypy.tools.sessions()
@cherrypy.tools.jinja2(on=False, env=env)
class Root:

    static = Static()

    @cherrypy.expose
    def index(self, **kwargs):
        return 'OK'

    @cherrypy.expose
    @cherrypy.tools.jinja2(template='test_datatable_static.html')
    def datatable_static(self):
        return {}

    @cherrypy.expose
    @cherrypy.tools.jinja2(template='test_datatable_ajax.html')
    def datatable_ajax(self):
        return {}

    @cherrypy.expose
    @cherrypy.tools.json_out()
    def data_json(self, **kwargs):
        return {
            'status': 200,
            'data': [
                {
                    "id": 1,
                    "name": "John Doe",
                    "email": "johndoe@example.com",
                    "age": 28,
                },
                {
                    "id": 2,
                    "name": "Jane Smith",
                    "email": "janesmith@example.com",
                    "age": 34,
                },
                {
                    "id": 3,
                    "name": "Bob Johnson",
                    "email": "bobjohnson@example.com",
                    "age": 45,
                },
            ],
        }


@skipUnless(HAS_JINJAX, reason='Required jinjax')
@skipIf(VENDOR_TEST == '0', reason='Datatable test disabled')
class DatatableTest(SeleniumUnitTest, helper.CPWebCase):
    interactive = False

    @classmethod
    def setup_server(cls):
        cherrypy.tree.mount(Root(), '/')

    @parameterized.expand(
        [
            ('/datatable_static',),
            ('/datatable_ajax',),
        ]
    )
    def test_get_page(self, page):
        # Given a page with datatable
        self.getPage(url_for(page))
        self.assertStatus(200)
        # Then page is render using datatable
        self.assertInBody('<table ')

    @parameterized.expand(
        [
            ('/datatable_static',),
            ('/datatable_ajax',),
        ]
    )
    def test_get_page_selenium(self, page):
        # Given  page with datatable
        with self.selenium() as driver:
            # When querying the page
            driver.get(url_for(page))
            # Then page load without error
            self.assertFalse(driver.get_log('browser'))
            # Then page contains our table
            table = driver.find_element('css selector', 'table')
            self.assertTrue(table)
            # Then the table contains our data.
            driver.find_element('xpath', "//td[text()='Bob Johnson']")

    @parameterized.expand(
        [
            ('.buttons-csv', '.csv'),
            ('.buttons-excel', '.xlsx'),
            ('.buttons-pdf', '.pdf'),
        ]
    )
    def test_export_selenium(self, btn, expected_file_ext):
        # Given page with datatable
        with self.selenium() as driver:
            driver.get(url_for('/datatable_ajax'))
            self.assertFalse(driver.get_log('browser'))
            # When user click on "Export" menu & "Download CSV"
            more_menu = driver.find_element('css selector', '.test-export-menu')
            more_menu.click()
            download_btn = driver.find_element('css selector', btn)
            download_btn.click()
            # Then a file get downloaded
            fn = self.assertSeleniumDownload()
            self.assertEqual(fn, f'test-datatable{expected_file_ext}')

    def test_filter_selenium(self):
        # Given page with datatable
        with self.selenium() as driver:
            driver.get(url_for('/datatable_ajax'))
            self.assertFalse(driver.get_log('browser'))
            table = driver.find_element('css selector', '.table')
            self.assertIn('John Doe', table.text)
            self.assertIn('Jane Smith', table.text)
            self.assertIn('Bob Johnson', table.text)
            # When user click on age filter
            more_menu = driver.find_element('css selector', '.test-filter-menu')
            more_menu.click()
            filter_btn = driver.find_element('css selector', '.test-filter-age-20')
            filter_btn.click()
            # Then the table get filtered
            self.assertFalse(driver.get_log('browser'))
            self.assertIn('John Doe', table.text)
            self.assertNotIn('Jane Smith', table.text)
            self.assertNotIn('Bob Johnson', table.text)


if __name__ == '__main__':
    cherrypy.quickstart(Root())
