"""
PPM 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 PPM views before tests
import modules.ppm.backend.api.v1.views  # noqa: F401

from modules.ppm.backend.infrastructure.persistence.models import (
    PortfolioModel,
    ProgramModel,
    ProgramProjectModel,
    BusinessCaseModel,
    CashFlowProjectionModel,
    ScoringModelModel,
    ScoringCriterionModel,
    ProjectScoreModel,
    BenefitPlanModel,
    BenefitModel,
    BenefitMeasurementModel,
    CapacityPlanModel,
    ResourceDemandModel,
    ResourceSupplyModel,
    CrossProjectDependencyModel,
    PPMDocumentModel,
)


# ─── Tenant & Auth ──────────────────────────────────────────

@pytest.fixture(autouse=True)
def _patch_tenant_middleware(tenant, monkeypatch):
    """Ensure get_current_tenant() returns the fixture tenant."""
    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):
    """Create a test tenant with domain."""
    t = Tenant.objects.create(
        name="PPM Test Tenant",
        slug="ppm-test",
        schema_name="public",
    )
    Domain.objects.create(domain="localhost", tenant=t, is_primary=True)
    return t


@pytest.fixture
def user(tenant):
    """Create a regular user."""
    return User.objects.create_user(
        email="ppm-user@example.com",
        password="testpass123",
        first_name="PPM",
        last_name="User",
        tenant=tenant,
    )


@pytest.fixture
def admin_user(tenant):
    """Create a superuser."""
    return User.objects.create_superuser(
        email="ppm-admin@example.com",
        password="adminpass123",
        first_name="PPM",
        last_name="Admin",
        tenant=tenant,
    )


# ─── API Clients ────────────────────────────────────────────

@pytest.fixture
def api_client():
    """Unauthenticated API client."""
    from rest_framework.test import APIClient
    return APIClient()


@pytest.fixture
def auth_client(api_client, admin_user):
    """Authenticated API client (superuser)."""
    api_client.force_authenticate(user=admin_user)
    return api_client


# ─── PPM Domain Objects ────────────────────────────────────

@pytest.fixture
def portfolio(tenant, admin_user):
    """Create a test portfolio."""
    return PortfolioModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        code="PF-001",
        name="پرتفولیو آزمایشی",
        description="پرتفولیو تست",
        status="active",
        total_budget=Decimal("5000000000"),
        allocated_budget=Decimal("3000000000"),
        start_date=date.today(),
        end_date=date.today() + timedelta(days=365),
        owner=admin_user,
    )


@pytest.fixture
def program(tenant, portfolio, admin_user):
    """Create a test program."""
    return ProgramModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        code="PG-001",
        name="برنامه آزمایشی",
        description="برنامه تست",
        portfolio=portfolio,
        manager=admin_user,
        status="active",
        budget=Decimal("2000000000"),
        start_date=date.today(),
        end_date=date.today() + timedelta(days=180),
    )


@pytest.fixture
def program_project(tenant, program):
    """Create a program-project link."""
    return ProgramProjectModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        program=program,
        project_id=uuid.uuid4(),
        role="core",
        priority=1,
    )


@pytest.fixture
def business_case(tenant, program, admin_user):
    """Create a test business case."""
    return BusinessCaseModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        title="کیس تجاری آزمایشی",
        description="توضیحات",
        program=program,
        status="draft",
        sponsor=admin_user,
        total_investment=Decimal("1000000000"),
        expected_revenue=Decimal("3000000000"),
        payback_period_months=18,
    )


@pytest.fixture
def cash_flow(tenant, business_case):
    """Create a cash flow projection."""
    return CashFlowProjectionModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        business_case=business_case,
        year=2026,
        investment=Decimal("500000000"),
        revenue=Decimal("1500000000"),
        operational_cost=Decimal("200000000"),
    )


@pytest.fixture
def scoring_model(tenant, portfolio):
    """Create a scoring model."""
    return ScoringModelModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        name="مدل امتیازدهی آزمایشی",
        portfolio=portfolio,
        is_active=True,
    )


@pytest.fixture
def scoring_criterion(tenant, scoring_model):
    """Create a scoring criterion."""
    return ScoringCriterionModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        scoring_model=scoring_model,
        name="تطابق راهبردی",
        weight=Decimal("0.40"),
        scale_min=1,
        scale_max=10,
        category="strategic",
        order=1,
    )


@pytest.fixture
def project_score(tenant, scoring_model, scoring_criterion, admin_user):
    """Create a project score."""
    return ProjectScoreModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        scoring_model=scoring_model,
        project_id=uuid.uuid4(),
        criterion=scoring_criterion,
        score=Decimal("8.50"),
        justification="تطابق بالا",
        scored_by=admin_user,
    )


@pytest.fixture
def benefit_plan(tenant, portfolio, program):
    """Create a benefit plan."""
    return BenefitPlanModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        name="برنامه منافع آزمایشی",
        program=program,
        portfolio=portfolio,
        is_active=True,
    )


@pytest.fixture
def benefit(tenant, benefit_plan, admin_user):
    """Create a benefit."""
    return BenefitModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        benefit_plan=benefit_plan,
        title="افزایش درآمد",
        benefit_type="financial",
        target_value=Decimal("5000000000"),
        actual_value=Decimal("1000000000"),
        status="planned",
        owner=admin_user,
    )


@pytest.fixture
def benefit_measurement(tenant, benefit, admin_user):
    """Create a benefit measurement."""
    return BenefitMeasurementModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        benefit=benefit,
        measurement_date=date.today(),
        value=Decimal("1500000000"),
        notes="اندازه‌گیری سه‌ماهه اول",
        measured_by=admin_user,
    )


@pytest.fixture
def capacity_plan(tenant, portfolio):
    """Create a capacity plan."""
    return CapacityPlanModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        name="طرح ظرفیت ۱۴۰۵",
        portfolio=portfolio,
        period_start=date.today(),
        period_end=date.today() + timedelta(days=90),
        is_active=True,
    )


@pytest.fixture
def resource_demand(tenant, capacity_plan):
    """Create a resource demand."""
    return ResourceDemandModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        capacity_plan=capacity_plan,
        resource_type="نرم‌افزار",
        demand_hours=Decimal("480.00"),
        period="1405-Q1",
    )


@pytest.fixture
def resource_supply(tenant, capacity_plan):
    """Create a resource supply."""
    return ResourceSupplyModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        capacity_plan=capacity_plan,
        resource_type="نرم‌افزار",
        available_hours=Decimal("600.00"),
        period="1405-Q1",
    )


@pytest.fixture
def cross_project_dependency(tenant):
    """Create a cross-project dependency."""
    return CrossProjectDependencyModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        predecessor_project_id=uuid.uuid4(),
        successor_project_id=uuid.uuid4(),
        dependency_type="FS",
        lag_days=5,
        status="active",
        impact_description="وابستگی بین‌پروژه‌ای",
    )


@pytest.fixture
def ppm_document(tenant, portfolio, admin_user):
    """Create a PPM document."""
    return PPMDocumentModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        entity_type="portfolio",
        entity_id=portfolio.pk,
        document_id=uuid.uuid4(),
        title="سند منشور پرتفولیو",
        document_code="DOC-PF-001",
        linked_by=admin_user,
    )
