from flask import url_for
from flask_jwt_extended import create_access_token

from dm.domain.entities import Orchestration, ActionTemplate, ActionType
from dm.domain.entities.bootstrap import set_initial
from dm.network.auth import HTTPBearerAuth
from dm.web import create_app, db
from tests.helpers import TestCaseLockBypass


class Test(TestCaseLockBypass):


    def setUp(self):
        """Create and configure a new app instance for each test."""
        # create the app with common test config
        self.app = create_app('test')
        self.app_context = self.app.app_context()
        self.app_context.push()
        self.client = self.app.test_client()
        self.auth = HTTPBearerAuth(create_access_token('00000000-0000-0000-0000-000000000001'))
        set_initial()
        self.at = ActionTemplate(name='action_name', version=1, action_type=ActionType.SHELL, code='')
        self.o = Orchestration(name='name', version=1)
        self.s1 = self.o.add_step(undo=False, action_template=self.at)
        self.s2 = self.o.add_step(undo=False, action_template=self.at, parents=[self.s1])
        self.s3 = self.o.add_step(undo=False, action_template=self.at, parents=[self.s2])
        db.session.add_all([self.at, self.o])
        db.session.commit()

    def tearDown(self) -> None:
        db.session.remove()
        db.drop_all()
        self.app_context.pop()

    def test_get(self):
        resp = self.client.get(url_for('api_1_0.steprelationshipparents', step_id=str(self.s1.id)),
                               headers=self.auth.header)

        self.assertEqual(200, resp.status_code)
        self.assertDictEqual(dict(parent_step_ids=[]), resp.get_json())

        resp = self.client.get(url_for('api_1_0.steprelationshipparents', step_id=str(self.s2.id)),
                               headers=self.auth.header)

        self.assertEqual(200, resp.status_code)
        self.assertDictEqual(dict(parent_step_ids=[str(self.s1.id)]), resp.get_json())

    def test_patch(self):
        resp = self.client.patch(url_for('api_1_0.steprelationshipparents', step_id=str(self.s3.id)),
                                 json={'parent_step_ids': [str(self.s1.id)]},
                                 headers=self.auth.header)

        self.assertEqual(200, resp.status_code)
        self.assertDictEqual(dict(parent_step_ids=[str(self.s1.id)]), resp.get_json())
        self.assertListEqual([self.s1], self.s3.parents)

    def test_post(self):
        resp = self.client.post(url_for('api_1_0.steprelationshipparents', step_id=str(self.s3.id)),
                                json={'parent_step_ids': [str(self.s1.id)]},
                                headers=self.auth.header)

        self.assertEqual(200, resp.status_code)
        expected = [str(self.s2.id), str(self.s1.id)]
        expected.sort()
        actual = resp.get_json()['parent_step_ids']
        actual.sort()
        self.assertListEqual(expected, actual)
        self.assertIn(self.s1, self.s3.parents)
        self.assertIn(self.s2, self.s3.parents)

    def test_delete(self):
        resp = self.client.delete(url_for('api_1_0.steprelationshipparents', step_id=str(self.s3.id)),
                                  json={'parent_step_ids': [str(self.s2.id)]},
                                  headers=self.auth.header)

        self.assertEqual(200, resp.status_code)
        self.assertDictEqual(dict(parent_step_ids=[]), resp.get_json())
        self.assertEqual(0, len(self.s3.parents))
