"""
Strategy Module — API Integration Tests.

تست‌های یکپارچگی برای API ماژول مدیریت راهبرد و حاکمیت.
"""
import uuid
from datetime import date, timedelta
from decimal import Decimal

import pytest

pytestmark = pytest.mark.django_db

BASE = "/api/v1/strategy"


# ═══════════════════════════════════════════════════
# 1) Vision API
# ═══════════════════════════════════════════════════

class TestVisionAPI:
    URL = f"{BASE}/visions/"

    def test_list(self, auth_client, vision):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client):
        data = {
            "title": "چشم‌انداز جدید",
            "description": "توضیحات",
            "status": "draft",
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_retrieve(self, auth_client, vision):
        resp = auth_client.get(f"{self.URL}{vision.pk}/")
        assert resp.status_code == 200

    def test_update(self, auth_client, vision):
        resp = auth_client.patch(f"{self.URL}{vision.pk}/", {"title": "ویرایش"}, format="json")
        assert resp.status_code == 200

    def test_delete(self, auth_client, vision):
        resp = auth_client.delete(f"{self.URL}{vision.pk}/")
        assert resp.status_code in (200, 204)

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 2) Strategic Theme API
# ═══════════════════════════════════════════════════

class TestStrategicThemeAPI:
    URL = f"{BASE}/strategic-themes/"

    def test_list(self, auth_client, theme):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client, vision):
        data = {
            "vision": str(vision.pk),
            "name": "تم جدید",
            "priority": "medium",
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_retrieve(self, auth_client, theme):
        resp = auth_client.get(f"{self.URL}{theme.pk}/")
        assert resp.status_code == 200

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 3) Objective API
# ═══════════════════════════════════════════════════

class TestObjectiveAPI:
    URL = f"{BASE}/objectives/"

    def test_list(self, auth_client, objective):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client, theme):
        data = {
            "theme": str(theme.pk),
            "title": "هدف جدید",
            "level": "enterprise",
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_retrieve(self, auth_client, objective):
        resp = auth_client.get(f"{self.URL}{objective.pk}/")
        assert resp.status_code == 200

    def test_update(self, auth_client, objective):
        resp = auth_client.patch(f"{self.URL}{objective.pk}/", {"title": "ویرایش"}, format="json")
        assert resp.status_code == 200

    def test_delete(self, auth_client, objective):
        resp = auth_client.delete(f"{self.URL}{objective.pk}/")
        assert resp.status_code in (200, 204)

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 4) Key Result API
# ═══════════════════════════════════════════════════

class TestKeyResultAPI:
    URL = f"{BASE}/key-results/"

    def test_list(self, auth_client, key_result):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client, objective):
        data = {
            "objective": str(objective.pk),
            "title": "نتیجه کلیدی جدید",
            "metric_type": "number",
            "target_value": "100",
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_retrieve(self, auth_client, key_result):
        resp = auth_client.get(f"{self.URL}{key_result.pk}/")
        assert resp.status_code == 200

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 5) Check-In API
# ═══════════════════════════════════════════════════

class TestCheckInAPI:
    URL = f"{BASE}/check-ins/"

    def test_list(self, auth_client, check_in):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client, key_result):
        data = {
            "key_result": str(key_result.pk),
            "value": "20.00",
            "confidence": "high",
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 6) KPI Definition API
# ═══════════════════════════════════════════════════

class TestKPIDefinitionAPI:
    URL = f"{BASE}/kpi-definitions/"

    def test_list(self, auth_client, kpi_definition):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client):
        data = {
            "name": "شاخص جدید",
            "code": "KPI-NEW",
            "direction": "higher_is_better",
            "frequency": "quarterly",
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_retrieve(self, auth_client, kpi_definition):
        resp = auth_client.get(f"{self.URL}{kpi_definition.pk}/")
        assert resp.status_code == 200

    def test_update(self, auth_client, kpi_definition):
        resp = auth_client.patch(f"{self.URL}{kpi_definition.pk}/", {"name": "ویرایش"}, format="json")
        assert resp.status_code == 200

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 7) KPI Target API
# ═══════════════════════════════════════════════════

class TestKPITargetAPI:
    URL = f"{BASE}/kpi-targets/"

    def test_list(self, auth_client, kpi_target):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client, kpi_definition):
        data = {
            "kpi": str(kpi_definition.pk),
            "target_value": "90.00",
            "period_start": str(date.today()),
            "period_end": str(date.today() + timedelta(days=90)),
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 8) KPI Actual API
# ═══════════════════════════════════════════════════

class TestKPIActualAPI:
    URL = f"{BASE}/kpi-actuals/"

    def test_list(self, auth_client, kpi_actual):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client, kpi_definition):
        data = {
            "kpi": str(kpi_definition.pk),
            "actual_value": "82.00",
            "period_start": str(date.today()),
            "period_end": str(date.today() + timedelta(days=30)),
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 9) KPI Assignment API
# ═══════════════════════════════════════════════════

class TestKPIAssignmentAPI:
    URL = f"{BASE}/kpi-assignments/"

    def test_list(self, auth_client, kpi_assignment):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client, kpi_definition):
        data = {
            "kpi": str(kpi_definition.pk),
            "level": "department",
            "weight": "0.80",
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 10) Strategy Map API
# ═══════════════════════════════════════════════════

class TestStrategyMapAPI:
    URL = f"{BASE}/strategy-maps/"

    def test_list(self, auth_client, strategy_map):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client):
        data = {
            "name": "نقشه جدید",
            "status": "draft",
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_retrieve(self, auth_client, strategy_map):
        resp = auth_client.get(f"{self.URL}{strategy_map.pk}/")
        assert resp.status_code == 200

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 11) Map Perspective API
# ═══════════════════════════════════════════════════

class TestMapPerspectiveAPI:
    URL = f"{BASE}/map-perspectives/"

    def test_list(self, auth_client, map_perspective):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client, strategy_map):
        data = {
            "strategy_map": str(strategy_map.pk),
            "name": "فرآیندها",
            "sort_order": 2,
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 12) Map Objective API
# ═══════════════════════════════════════════════════

class TestMapObjectiveAPI:
    URL = f"{BASE}/map-objectives/"

    def test_list(self, auth_client, map_objective):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client, strategy_map, map_perspective, objective):
        data = {
            "strategy_map": str(strategy_map.pk),
            "perspective": str(map_perspective.pk),
            "objective": str(objective.pk),
            "x_position": 150,
            "y_position": 250,
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 13) Causal Link API
# ═══════════════════════════════════════════════════

class TestCausalLinkAPI:
    URL = f"{BASE}/causal-links/"

    def test_list(self, auth_client, causal_link):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client, strategy_map, map_objective, map_objective_b):
        data = {
            "strategy_map": str(strategy_map.pk),
            "from_objective": str(map_objective.pk),
            "to_objective": str(map_objective_b.pk),
            "strength": "medium",
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 14) Scorecard API
# ═══════════════════════════════════════════════════

class TestScorecardAPI:
    URL = f"{BASE}/scorecards/"

    def test_list(self, auth_client, scorecard):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client):
        data = {
            "name": "کارت امتیازی جدید",
            "status": "draft",
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_retrieve(self, auth_client, scorecard):
        resp = auth_client.get(f"{self.URL}{scorecard.pk}/")
        assert resp.status_code == 200

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 15) SC Perspective API
# ═══════════════════════════════════════════════════

class TestScPerspectiveAPI:
    URL = f"{BASE}/sc-perspectives/"

    def test_list(self, auth_client, sc_perspective):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client, scorecard):
        data = {
            "scorecard": str(scorecard.pk),
            "name": "مشتری",
            "weight": "0.25",
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 16) SC Measure API
# ═══════════════════════════════════════════════════

class TestScMeasureAPI:
    URL = f"{BASE}/sc-measures/"

    def test_list(self, auth_client, sc_measure):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client, sc_perspective):
        data = {
            "perspective": str(sc_perspective.pk),
            "weight": "1.0",
            "target_value": "90.00",
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 17) Gate Process API
# ═══════════════════════════════════════════════════

class TestGateProcessAPI:
    URL = f"{BASE}/gate-processes/"

    def test_list(self, auth_client, gate_process):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client):
        data = {
            "name": "فرآیند جدید",
            "applicable_to": "project",
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_retrieve(self, auth_client, gate_process):
        resp = auth_client.get(f"{self.URL}{gate_process.pk}/")
        assert resp.status_code == 200

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 18) Gate API
# ═══════════════════════════════════════════════════

class TestGateAPI:
    URL = f"{BASE}/gates/"

    def test_list(self, auth_client, gate):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client, gate_process):
        data = {
            "process": str(gate_process.pk),
            "name": "دروازه ۲",
            "sequence": 2,
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 19) Gate Review API
# ═══════════════════════════════════════════════════

class TestGateReviewAPI:
    URL = f"{BASE}/gate-reviews/"

    def test_list(self, auth_client, gate_review):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client, gate):
        data = {
            "gate": str(gate.pk),
            "entity_id": str(uuid.uuid4()),
            "entity_type": "project",
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 20) Gate Reviewer API
# ═══════════════════════════════════════════════════

class TestGateReviewerAPI:
    URL = f"{BASE}/gate-reviewers/"

    def test_list(self, auth_client, gate_reviewer):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client, gate_review, user):
        data = {
            "review": str(gate_review.pk),
            "user": str(user.pk),
            "role": "reviewer",
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 21) Gate Deliverable API
# ═══════════════════════════════════════════════════

class TestGateDeliverableAPI:
    URL = f"{BASE}/gate-deliverables/"

    def test_list(self, auth_client, gate_deliverable):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client, gate_review):
        data = {
            "review": str(gate_review.pk),
            "name": "تحویل‌دادنی جدید",
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 22) Policy API
# ═══════════════════════════════════════════════════

class TestPolicyAPI:
    URL = f"{BASE}/policies/"

    def test_list(self, auth_client, policy):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client):
        data = {
            "title": "سیاست جدید",
            "code": "POL-NEW",
            "category": "governance",
            "status": "draft",
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_retrieve(self, auth_client, policy):
        resp = auth_client.get(f"{self.URL}{policy.pk}/")
        assert resp.status_code == 200

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 23) Policy Acknowledgment API
# ═══════════════════════════════════════════════════

class TestPolicyAcknowledgmentAPI:
    URL = f"{BASE}/policy-acknowledgments/"

    def test_list(self, auth_client, policy_acknowledgment):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client, policy, admin_user):
        data = {
            "policy": str(policy.pk),
            "user": str(admin_user.pk),
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)


# ═══════════════════════════════════════════════════
# 24) Objective-Portfolio Alignment API
# ═══════════════════════════════════════════════════

class TestAlignmentAPI:
    URL = f"{BASE}/alignments/"

    def test_list(self, auth_client, alignment):
        resp = auth_client.get(self.URL)
        assert resp.status_code == 200

    def test_create(self, auth_client, objective):
        data = {
            "objective": str(objective.pk),
            "portfolio_id": str(uuid.uuid4()),
            "alignment_level": "secondary",
            "strategic_fit_score": "7.00",
        }
        resp = auth_client.post(self.URL, data, format="json")
        assert resp.status_code in (200, 201)

    def test_retrieve(self, auth_client, alignment):
        resp = auth_client.get(f"{self.URL}{alignment.pk}/")
        assert resp.status_code == 200

    def test_unauthenticated(self, api_client):
        assert api_client.get(self.URL).status_code in (401, 403)
