"""Integration tests for ECMDmsSync.move().

Requires a running ECM server at localhost:4000.

Object hierarchy used in every test:
    folder (Unittest_DMS)
      register1 (Unittest_DMS_Register)
        subregister1 (Unittest_DMS_Subregister)  ← doc starts here
        subregister2 (Unittest_DMS_Subregister)  ← move target
      register2 (Unittest_DMS_Register)          ← move target for register moves
"""

import os
import unittest
from uuid import UUID

from ecmind_blue_client.ecm import ECM
from ecmind_blue_client.pool import SyncPoolClient
from tests.models.Unittest_DMS import (
    Unittest_DMS,
    Unittest_DMS_Document,
    Unittest_DMS_Register,
    Unittest_DMS_Subregister,
)
from tests._test_settings import ECM_SERVERS, ECM_USERNAME, ECM_PASSWORD


class TestEcmDmsMoveSync(unittest.TestCase):
    """Integration tests for ECMDmsSync.move() — requires localhost:4000."""

    def setUp(self):
        self.client = SyncPoolClient(servers=ECM_SERVERS, username=ECM_USERNAME, password=ECM_PASSWORD)
        self.ecm = ECM(self.client)
        uuid = UUID(bytes=os.urandom(16), version=4)

        folder_id, folder_type_id = self.ecm.dms.insert(Unittest_DMS(Name=f"MoveTest_{uuid}"))
        self.folder_id = folder_id
        self.folder_type_id = folder_type_id

        self.register1 = self.ecm.dms.insert_and_get(
            Unittest_DMS_Register(Name=f"MoveReg1_{uuid}"),
            folder_id=folder_id,
        )
        self.register2 = self.ecm.dms.insert_and_get(
            Unittest_DMS_Register(Name=f"MoveReg2_{uuid}"),
            folder_id=folder_id,
        )
        self.subregister1 = self.ecm.dms.insert_and_get(
            Unittest_DMS_Subregister(Name=f"MoveSub1_{uuid}"),
            folder_id=folder_id,
            register_id=self.register1.system.id,
        )
        self.subregister2 = self.ecm.dms.insert_and_get(
            Unittest_DMS_Subregister(Name=f"MoveSub2_{uuid}"),
            folder_id=folder_id,
            register_id=self.register1.system.id,
        )
        self.doc = self.ecm.dms.insert_and_get(
            Unittest_DMS_Document(Name=f"MoveDoc_{uuid}"),
            folder_id=folder_id,
            register_id=self.subregister1.system.id,
        )
        self.subregister1_type_id = self.ecm.dms.get_object_type_by_id(self.subregister1.system.id)
        self.subregister2_type_id = self.ecm.dms.get_object_type_by_id(self.subregister2.system.id)

    def tearDown(self):
        folder = self.ecm.dms.get(Unittest_DMS, self.folder_id, self.folder_type_id)
        self.ecm.dms.delete(folder, hard_delete=True, delete_cascading=True)
        del self.client

    def _get_doc_register_id(self, doc_id: int) -> int | None:
        results = self.ecm.dms.select(Unittest_DMS_Document).where(
            Unittest_DMS_Document["OBJECT_ID"] == doc_id
        ).execute()
        return results[0].system.register_id

    # ------------------------------------------------------------------
    # Move via model instance
    # ------------------------------------------------------------------

    def test_move_document_via_model_to_other_subregister(self):
        self.ecm.dms.move(
            self.doc,
            folder_id=self.folder_id,
            register_id=self.subregister2.system.id,
            register_type=self.subregister2_type_id,
        )

        self.assertEqual(self._get_doc_register_id(self.doc.system.id), self.subregister2.system.id)

    def test_move_register_via_model_to_other_parent(self):
        self.ecm.dms.move(
            self.subregister1,
            folder_id=self.folder_id,
            register_id=self.register2.system.id,
            register_type=self.ecm.dms.get_object_type_by_id(self.register2.system.id),
        )

        self.assertEqual(self._get_doc_register_id(self.doc.system.id), self.subregister1.system.id)

    # ------------------------------------------------------------------
    # Move via plain integer ID + type_id
    # ------------------------------------------------------------------

    def test_move_by_plain_id_and_type_id(self):
        doc_type_id = self.ecm.dms.get_object_type_by_id(self.doc.system.id)
        self.ecm.dms.move(
            self.doc.system.id,
            doc_type_id,
            folder_id=self.folder_id,
            register_id=self.subregister2.system.id,
            register_type=self.subregister2_type_id,
        )

        self.assertEqual(self._get_doc_register_id(self.doc.system.id), self.subregister2.system.id)

    # ------------------------------------------------------------------
    # Move via plain integer ID + internal name
    # ------------------------------------------------------------------

    def test_move_by_plain_id_and_internal_name(self):
        self.ecm.dms.move(
            self.doc.system.id,
            Unittest_DMS_Document._internal_name_,
            folder_id=self.folder_id,
            register_id=self.subregister2.system.id,
            register_type=self.subregister2_type_id,
        )

        self.assertEqual(self._get_doc_register_id(self.doc.system.id), self.subregister2.system.id)

    # ------------------------------------------------------------------
    # Error cases
    # ------------------------------------------------------------------

    def test_move_raises_when_plain_id_without_object_type(self):
        with self.assertRaises(ValueError):
            self.ecm.dms.move(
                self.doc.system.id,
                folder_id=self.folder_id,
                register_id=self.subregister2.system.id,
            )

    def test_move_raises_when_model_has_no_id(self):
        doc_without_id = Unittest_DMS_Document(Name="no_id")
        with self.assertRaises(ValueError):
            self.ecm.dms.move(doc_without_id, folder_id=self.folder_id)
