import json
import os
import tempfile
import unittest
from contextlib import contextmanager

from checkmate.lib.models import Project
from checkmate.settings import Settings
from checkmate.management.commands.init import Command as InitCommand
from checkmate.contrib.plugins.git.commands.init import Command as GitInitCommand
from checkmate.contrib.plugins.git.models import GitRepository


class InitCommandTests(unittest.TestCase):
    def test_init_default_sqlite_creates_config(self):
        settings = Settings()
        with tempfile.TemporaryDirectory() as tmpdir:
            cmd = InitCommand(project=None, settings=settings, backend=None, args=["--path", tmpdir])
            result = cmd.run()
            self.assertEqual(result, 0)

            config_path = os.path.join(tmpdir, ".checkmate", "config.json")
            self.assertTrue(os.path.exists(config_path))
            config = json.loads(open(config_path, "r").read())
            self.assertEqual(config["backend"]["driver"], "sqlite")
            self.assertIn(".checkmate/database.db", config["backend"]["connection_string"])

    def test_init_sql_backend_creates_config(self):
        settings = Settings()
        with tempfile.TemporaryDirectory() as tmpdir:
            conn = "postgresql+psycopg2://user:pass@localhost/db"
            cmd = InitCommand(
                project=None,
                settings=settings,
                backend=None,
                args=["--path", tmpdir, "--backend", "sql", "--backend-opts", conn],
            )
            result = cmd.run()
            self.assertEqual(result, 0)

            config_path = os.path.join(tmpdir, ".checkmate", "config.json")
            config = json.loads(open(config_path, "r").read())
            self.assertEqual(config["backend"]["driver"], "sql")
            self.assertEqual(config["backend"]["connection_string"], conn)

    def test_git_init_saves_repository(self):
        settings = Settings()
        with tempfile.TemporaryDirectory() as tmpdir:
            os.makedirs(os.path.join(tmpdir, ".git"))
            class _Backend:
                def __init__(self):
                    self.saved = []

                @contextmanager
                def transaction(self):
                    yield

                def get(self, cls, query):
                    raise cls.DoesNotExist()

                def save(self, obj):
                    self.saved.append(obj)

                def commit(self):
                    return None

            backend = _Backend()
            project = Project({"project_id": "test"})
            project.pk = "test"
            project.backend = backend

            cmd = GitInitCommand(project=project, settings=settings, backend=backend, args=["--path", tmpdir])
            result = cmd.run()
            self.assertIsNone(result)

            self.assertEqual(len(backend.saved), 1)
            repo = backend.saved[0]
            self.assertIsInstance(repo, GitRepository)
            self.assertEqual(repo.path, tmpdir)
            self.assertEqual(repo.project, project)
