"""Phase 6.2 sales engine APIs — playbooks, forecasts, goals, products, win/loss."""
from __future__ import annotations

from uuid import UUID

from fastapi import APIRouter, Depends, status
from sqlalchemy.ext.asyncio import AsyncSession

from app.api.deps import get_db, get_pagination, require_tenant
from app.core.security import get_current_user
from app.schemas.sales_engine import (
    ForecastComputeRequest,
    ForecastRead,
    GoalCreate,
    GoalRead,
    OpportunityCompetitorCreate,
    OpportunityCompetitorRead,
    OpportunityContactCreate,
    OpportunityContactRead,
    OpportunityProductCreate,
    OpportunityProductRead,
    OpportunityWinLossRead,
    PlaybookAssignRequest,
    PlaybookAssignmentRead,
    PlaybookCompleteStepRequest,
    PlaybookCreate,
    PlaybookRead,
    PlaybookStepCreate,
    PlaybookStepRead,
    SalesProcessCreate,
    SalesProcessRead,
    TargetCreate,
    TargetRead,
    WinLossCategoryCreate,
    WinLossCategoryRead,
    WinLossReasonCreate,
    WinLossReasonRead,
)
from app.repositories.sales_engine import OpportunityWinLossRepository
from app.services.sales_engine_services import (
    ForecastService,
    GoalService,
    OpportunityExtrasService,
    PlaybookService,
    SalesProcessService,
    TargetService,
    WinLossService,
)
from shared.pagination import PaginationParams
from shared.security import CurrentUser

router = APIRouter()


@router.post(
    "/sales-processes",
    response_model=SalesProcessRead,
    status_code=status.HTTP_201_CREATED,
)
async def create_sales_process(
    body: SalesProcessCreate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await SalesProcessService(db).create(
        tenant_id,
        name=body.name,
        code=body.code,
        description=body.description,
        pipeline_id=body.pipeline_id,
    )


@router.get("/sales-processes", response_model=list[SalesProcessRead])
async def list_sales_processes(
    tenant_id: UUID = Depends(require_tenant),
    pagination: PaginationParams = Depends(get_pagination),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await SalesProcessService(db).list(
        tenant_id, offset=pagination.offset, limit=pagination.page_size
    )


@router.post(
    "/playbooks", response_model=PlaybookRead, status_code=status.HTTP_201_CREATED
)
async def create_playbook(
    body: PlaybookCreate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await PlaybookService(db).create(tenant_id, body)


@router.get("/playbooks", response_model=list[PlaybookRead])
async def list_playbooks(
    tenant_id: UUID = Depends(require_tenant),
    pagination: PaginationParams = Depends(get_pagination),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await PlaybookService(db).list(
        tenant_id, offset=pagination.offset, limit=pagination.page_size
    )


@router.post(
    "/playbooks/steps",
    response_model=PlaybookStepRead,
    status_code=status.HTTP_201_CREATED,
)
async def create_playbook_step(
    body: PlaybookStepCreate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await PlaybookService(db).add_step(tenant_id, body)


@router.get("/playbooks/{playbook_id}/steps", response_model=list[PlaybookStepRead])
async def list_playbook_steps(
    playbook_id: UUID,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await PlaybookService(db).list_steps(tenant_id, playbook_id)


@router.post(
    "/playbooks/assignments",
    response_model=PlaybookAssignmentRead,
    status_code=status.HTTP_201_CREATED,
)
async def assign_playbook(
    body: PlaybookAssignRequest,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    user: CurrentUser = Depends(get_current_user),
):
    return await PlaybookService(db).assign(tenant_id, body, actor=user)


@router.post(
    "/playbooks/assignments/{assignment_id}/complete-step",
    response_model=PlaybookAssignmentRead,
)
async def complete_playbook_step(
    assignment_id: UUID,
    body: PlaybookCompleteStepRequest,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    user: CurrentUser = Depends(get_current_user),
):
    return await PlaybookService(db).complete_step(
        tenant_id, assignment_id, body, actor=user
    )


@router.post(
    "/forecasts/compute",
    response_model=ForecastRead,
    status_code=status.HTTP_201_CREATED,
)
async def compute_forecast(
    body: ForecastComputeRequest,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await ForecastService(db).compute(tenant_id, body)


@router.get("/forecasts", response_model=list[ForecastRead])
async def list_forecasts(
    tenant_id: UUID = Depends(require_tenant),
    pagination: PaginationParams = Depends(get_pagination),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await ForecastService(db).list(
        tenant_id, offset=pagination.offset, limit=pagination.page_size
    )


@router.post("/goals", response_model=GoalRead, status_code=status.HTTP_201_CREATED)
async def create_goal(
    body: GoalCreate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await GoalService(db).create(tenant_id, body)


@router.get("/goals", response_model=list[GoalRead])
async def list_goals(
    tenant_id: UUID = Depends(require_tenant),
    pagination: PaginationParams = Depends(get_pagination),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await GoalService(db).list(
        tenant_id, offset=pagination.offset, limit=pagination.page_size
    )


@router.post(
    "/targets", response_model=TargetRead, status_code=status.HTTP_201_CREATED
)
async def create_target(
    body: TargetCreate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await TargetService(db).create(tenant_id, body)


@router.get("/targets", response_model=list[TargetRead])
async def list_targets(
    tenant_id: UUID = Depends(require_tenant),
    pagination: PaginationParams = Depends(get_pagination),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await TargetService(db).list(
        tenant_id, offset=pagination.offset, limit=pagination.page_size
    )


@router.post(
    "/opportunity-products",
    response_model=OpportunityProductRead,
    status_code=status.HTTP_201_CREATED,
)
async def add_opportunity_product(
    body: OpportunityProductCreate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await OpportunityExtrasService(db).add_product(tenant_id, body)


@router.post(
    "/opportunity-contacts",
    response_model=OpportunityContactRead,
    status_code=status.HTTP_201_CREATED,
)
async def add_opportunity_contact(
    body: OpportunityContactCreate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await OpportunityExtrasService(db).add_contact(tenant_id, body)


@router.post(
    "/opportunity-competitors",
    response_model=OpportunityCompetitorRead,
    status_code=status.HTTP_201_CREATED,
)
async def add_opportunity_competitor(
    body: OpportunityCompetitorCreate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await OpportunityExtrasService(db).add_competitor(tenant_id, body)


@router.post(
    "/win-loss/categories",
    response_model=WinLossCategoryRead,
    status_code=status.HTTP_201_CREATED,
)
async def create_win_loss_category(
    body: WinLossCategoryCreate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await WinLossService(db).create_category(tenant_id, body)


@router.get("/win-loss/categories", response_model=list[WinLossCategoryRead])
async def list_win_loss_categories(
    tenant_id: UUID = Depends(require_tenant),
    pagination: PaginationParams = Depends(get_pagination),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await WinLossService(db).list_categories(
        tenant_id, offset=pagination.offset, limit=pagination.page_size
    )


@router.post(
    "/win-loss/reasons",
    response_model=WinLossReasonRead,
    status_code=status.HTTP_201_CREATED,
)
async def create_win_loss_reason(
    body: WinLossReasonCreate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await WinLossService(db).create_reason(tenant_id, body)


@router.get("/win-loss/reasons", response_model=list[WinLossReasonRead])
async def list_win_loss_reasons(
    tenant_id: UUID = Depends(require_tenant),
    pagination: PaginationParams = Depends(get_pagination),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await WinLossService(db).list_reasons(
        tenant_id, offset=pagination.offset, limit=pagination.page_size
    )


@router.get(
    "/win-loss/opportunities/{opportunity_id}",
    response_model=OpportunityWinLossRead,
)
async def get_opportunity_win_loss(
    opportunity_id: UUID,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    from shared.exceptions import NotFoundError

    row = await OpportunityWinLossRepository(db).get_by_opportunity(
        tenant_id, opportunity_id
    )
    if row is None:
        raise NotFoundError("تحلیل برد/باخت یافت نشد", error_code="win_loss_not_found")
    return row
