# (c) cavaliba.com - test / factory reset / demo data load

import os
import tempfile
from unittest import mock

from django.core.cache import cache as cache_django
from django.test import TestCase, override_settings

import app_home.cache as cache
from app_data.models import DataInstance
from app_home.factory import DEMO_FOLDER, factory_reset, load_demo

DEMO_YAML = """
- classname: user
  keyname: demoyaml
  displayname: Demo Yaml User
  description: created by the demo loader test
"""

DEMO_CSV = "_schema,keyname,displayname\nuser,democsv,Demo Csv User\n"


class TestFactoryResetDemo(TestCase):
    def setUp(self):
        cache.clear()
        cache_django.clear()
        self.tmpdir = tempfile.mkdtemp()
        self.demodir = tempfile.mkdtemp()
        with open(os.path.join(self.demodir, "010_user.yml"), "w") as f:
            f.write(DEMO_YAML)
        with open(os.path.join(self.demodir, "020_user.csv"), "w") as f:
            f.write(DEMO_CSV)

    def _reset(self, with_demo=True):
        with override_settings(
            CAVALIBA_FILESTORE=self.tmpdir,
            CAVALIBA_EXPORT_FOLDER=self.tmpdir,
            CAVALIBA_MAIL_FOLDER=self.tmpdir,
            CAVALIBA_SMS_FOLDER=self.tmpdir,
        ):
            return factory_reset(
                aaa={"username": "unittest"}, with_demo=with_demo, demo_folder=self.demodir
            )

    def test_demo_objects_are_loaded(self):
        report = self._reset(with_demo=True)

        self.assertEqual(report["errors"], [])
        self.assertEqual(report["demo"]["files"], 2)
        self.assertEqual(report["demo"]["objects"], 2)
        self.assertTrue(DataInstance.objects.filter(classname="user", keyname="demoyaml").exists())
        self.assertTrue(DataInstance.objects.filter(classname="user", keyname="democsv").exists())

    def test_no_demo_when_not_requested(self):
        report = self._reset(with_demo=False)

        self.assertIsNone(report["demo"])
        self.assertFalse(DataInstance.objects.filter(keyname="demoyaml").exists())

    def test_unknown_filetype_is_reported_not_raised(self):
        with open(os.path.join(self.demodir, "readme.txt"), "w") as f:
            f.write("not data")

        report = load_demo(folder=self.demodir)

        self.assertEqual(report["files"], 2)
        self.assertEqual(len(report["errors"]), 1)
        self.assertIn("readme.txt", report["errors"][0])

    def test_missing_folder_is_reported_not_raised(self):
        report = load_demo(folder="/nonexistent/cavaliba/demo")

        self.assertEqual(report["files"], 0)
        self.assertEqual(len(report["errors"]), 1)

    def test_builtin_demo_csv_declares_its_schema(self):
        # a plain directory load applies no pipeline, so the CSV must carry the
        # "_schema" column load_file_csv() maps to classname - without it the
        # whole demo user set is rejected and demo groups/sites point nowhere
        csvfile = os.path.join(DEMO_FOLDER, "010_user.csv")
        self.assertTrue(os.path.isfile(csvfile))
        with open(csvfile, encoding="utf-8") as f:
            header = f.readline()
        self.assertTrue(header.startswith("_schema,"), header)

    @mock.patch("app_home.factory.DEMO_FOLDER", "/nonexistent/cavaliba/demo")
    def test_demo_folder_is_patchable(self):
        report = load_demo()
        self.assertEqual(report["folder"], "/nonexistent/cavaliba/demo")
