"""
Strategy Module — Pytest Fixtures.

فیکسچرهای مشترک برای تست‌های ماژول مدیریت راهبرد و حاکمیت.
"""
import sys
from pathlib import Path
import uuid
from datetime import date, timedelta
from decimal import Decimal

PROJECT_ROOT = str(Path(__file__).resolve().parent.parent.parent.parent)
if PROJECT_ROOT not in sys.path:
    sys.path.insert(0, PROJECT_ROOT)

import pytest

from apps.core.tenant.models import Tenant, Domain
from apps.core.tenant.middleware import _thread_locals
from apps.core.auth.models import User

# Force import of Strategy views before tests
import modules.strategy.backend.api.v1.views  # noqa: F401

from modules.strategy.backend.infrastructure.persistence.models import (
    VisionModel,
    StrategicThemeModel,
    ObjectiveModel,
    KeyResultModel,
    KeyResultCheckInModel,
    KPIDefinitionModel,
    KPITargetModel,
    KPIActualModel,
    KPIAssignmentModel,
    StrategyMapModel,
    StrategyMapPerspectiveModel,
    StrategyMapObjectiveModel,
    CausalLinkModel,
    ScorecardModel,
    ScorecardPerspectiveModel,
    ScorecardMeasureModel,
    GateProcessModel,
    GateModel,
    GateReviewModel,
    GateReviewerModel,
    GateDeliverableModel,
    PolicyModel,
    PolicyAcknowledgmentModel,
    ObjectivePortfolioAlignmentModel,
)


# ─── Tenant & Auth ──────────────────────────────────────────

@pytest.fixture(autouse=True)
def _patch_tenant_middleware(tenant, monkeypatch):
    from django.db import connection
    from apps.core.tenant import middleware as tenant_mw

    monkeypatch.setattr(tenant_mw, "get_current_tenant", lambda: tenant)
    if hasattr(connection, "set_tenant"):
        connection.set_tenant(tenant)
    yield
    if hasattr(_thread_locals, "tenant"):
        del _thread_locals.tenant
    if hasattr(_thread_locals, "request"):
        del _thread_locals.request


@pytest.fixture(scope="function")
def tenant(db):
    t = Tenant.objects.create(
        name="Strategy Test Tenant",
        slug="strategy-test",
        schema_name="public",
    )
    Domain.objects.create(domain="localhost", tenant=t, is_primary=True)
    return t


@pytest.fixture
def user(tenant):
    return User.objects.create_user(
        email="str-user@example.com",
        password="testpass123",
        first_name="Strategy",
        last_name="User",
        tenant=tenant,
    )


@pytest.fixture
def admin_user(tenant):
    return User.objects.create_superuser(
        email="str-admin@example.com",
        password="adminpass123",
        first_name="Strategy",
        last_name="Admin",
        tenant=tenant,
    )


@pytest.fixture
def api_client():
    from rest_framework.test import APIClient
    return APIClient()


@pytest.fixture
def auth_client(api_client, admin_user):
    api_client.force_authenticate(user=admin_user)
    return api_client


# ─── OKR Fixtures ───────────────────────────────────────────

@pytest.fixture
def vision(tenant, admin_user):
    return VisionModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        title="چشم‌انداز ۱۴۱۰",
        description="رهبری بازار فناوری",
        status="active",
        time_horizon_start=date(2026, 1, 1),
        time_horizon_end=date(2031, 12, 29),
        owner=admin_user,
    )


@pytest.fixture
def theme(tenant, vision, admin_user):
    return StrategicThemeModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        vision=vision,
        name="نوآوری و فناوری",
        priority="high",
        status="active",
        owner=admin_user,
    )


@pytest.fixture
def objective(tenant, theme, admin_user):
    return ObjectiveModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        theme=theme,
        title="افزایش سهم بازار",
        level="enterprise",
        time_frame="annual",
        status="active",
        weight=Decimal("1.00"),
        owner=admin_user,
    )


@pytest.fixture
def key_result(tenant, objective, admin_user):
    return KeyResultModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        objective=objective,
        title="افزایش فروش ۳۰٪",
        metric_type="percentage",
        start_value=Decimal("0"),
        target_value=Decimal("30"),
        current_value=Decimal("12"),
        weight=Decimal("1.00"),
        status="active",
        owner=admin_user,
    )


@pytest.fixture
def check_in(tenant, key_result, admin_user):
    return KeyResultCheckInModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        key_result=key_result,
        value=Decimal("15.50"),
        confidence="medium",
        notes="پیشرفت مناسب",
        checked_by=admin_user,
    )


# ─── KPI Fixtures ───────────────────────────────────────────

@pytest.fixture
def kpi_definition(tenant, admin_user):
    return KPIDefinitionModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        name="نرخ تکمیل پروژه",
        code="KPI-PCT",
        direction="higher_is_better",
        frequency="monthly",
        data_source="calculated",
        status="active",
        owner=admin_user,
    )


@pytest.fixture
def kpi_target(tenant, kpi_definition):
    return KPITargetModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        kpi=kpi_definition,
        period_start=date(2026, 1, 1),
        period_end=date(2026, 3, 31),
        target_value=Decimal("85.00"),
        stretch_value=Decimal("95.00"),
    )


@pytest.fixture
def kpi_actual(tenant, kpi_definition, admin_user):
    return KPIActualModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        kpi=kpi_definition,
        period_start=date(2026, 1, 1),
        period_end=date(2026, 1, 31),
        actual_value=Decimal("78.50"),
        recorded_by=admin_user,
    )


@pytest.fixture
def kpi_assignment(tenant, kpi_definition):
    return KPIAssignmentModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        kpi=kpi_definition,
        level="organization",
        weight=Decimal("1.0"),
        status="active",
    )


# ─── Strategy Map Fixtures ──────────────────────────────────

@pytest.fixture
def strategy_map(tenant):
    return StrategyMapModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        name="نقشه راهبردی ۱۴۰۵",
        status="published",
        version=1,
    )


@pytest.fixture
def map_perspective(tenant, strategy_map):
    return StrategyMapPerspectiveModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        strategy_map=strategy_map,
        name="مالی",
        sort_order=1,
        color="#10b981",
    )


@pytest.fixture
def map_objective(tenant, strategy_map, map_perspective, objective):
    return StrategyMapObjectiveModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        strategy_map=strategy_map,
        perspective=map_perspective,
        objective=objective,
        x_position=100.0,
        y_position=200.0,
    )


@pytest.fixture
def map_objective_b(tenant, strategy_map, map_perspective, theme, admin_user):
    obj_b = ObjectiveModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        theme=theme,
        title="بهبود فرآیندها",
        level="enterprise",
        status="active",
        owner=admin_user,
    )
    return StrategyMapObjectiveModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        strategy_map=strategy_map,
        perspective=map_perspective,
        objective=obj_b,
        x_position=300.0,
        y_position=200.0,
    )


@pytest.fixture
def causal_link(tenant, strategy_map, map_objective, map_objective_b):
    return CausalLinkModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        strategy_map=strategy_map,
        from_objective=map_objective,
        to_objective=map_objective_b,
        strength="strong",
    )


# ─── Scorecard Fixtures ─────────────────────────────────────

@pytest.fixture
def scorecard(tenant, admin_user):
    return ScorecardModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        name="کارت امتیازی ۱۴۰۵",
        status="active",
        owner=admin_user,
        period_start=date(2026, 1, 1),
        period_end=date(2026, 12, 29),
    )


@pytest.fixture
def sc_perspective(tenant, scorecard):
    return ScorecardPerspectiveModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        scorecard=scorecard,
        name="مالی",
        weight=Decimal("0.30"),
        sort_order=1,
    )


@pytest.fixture
def sc_measure(tenant, sc_perspective, kpi_assignment):
    return ScorecardMeasureModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        perspective=sc_perspective,
        kpi_assignment=kpi_assignment,
        weight=Decimal("1.0"),
        target_value=Decimal("85.00"),
        actual_value=Decimal("78.50"),
        score=Decimal("92.35"),
        status="on_track",
    )


# ─── Gate Fixtures ───────────────────────────────────────────

@pytest.fixture
def gate_process(tenant):
    return GateProcessModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        name="فرآیند Stage-Gate پروژه",
        applicable_to="project",
        is_active=True,
    )


@pytest.fixture
def gate(tenant, gate_process):
    return GateModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        process=gate_process,
        name="دروازه ۱ — تأیید مفهوم",
        sequence=1,
    )


@pytest.fixture
def gate_review(tenant, gate):
    return GateReviewModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        gate=gate,
        entity_id=uuid.uuid4(),
        entity_type="project",
        status="pending",
    )


@pytest.fixture
def gate_reviewer(tenant, gate_review, admin_user):
    return GateReviewerModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        review=gate_review,
        user=admin_user,
        role="lead",
    )


@pytest.fixture
def gate_deliverable(tenant, gate_review):
    return GateDeliverableModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        review=gate_review,
        name="منشور پروژه",
        status="pending",
    )


# ─── Policy Fixtures ────────────────────────────────────────

@pytest.fixture
def policy(tenant, admin_user):
    return PolicyModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        title="سیاست مدیریت ریسک",
        code="POL-001",
        category="risk",
        content="محتوای سیاست",
        status="active",
        owner=admin_user,
    )


@pytest.fixture
def policy_acknowledgment(tenant, policy, user):
    return PolicyAcknowledgmentModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        policy=policy,
        user=user,
    )


# ─── Alignment Fixture ──────────────────────────────────────

@pytest.fixture
def alignment(tenant, objective):
    return ObjectivePortfolioAlignmentModel.objects.create(
        id=uuid.uuid4(), tenant=tenant,
        objective=objective,
        portfolio_id=uuid.uuid4(),
        alignment_level="primary",
        strategic_fit_score=Decimal("8.50"),
        weight=Decimal("1.0"),
        is_active=True,
    )
