from __future__ import annotations

import argparse
from collections import Counter

from sqlalchemy import func, select

# Standalone utilities do not pass through FastAPI startup automatically.
# Importing startup loads the complete SQLAlchemy model registry (including
# ConsultantProfile and all relationship targets) before ORM queries compile.
import app.core.startup  # noqa: F401

from app.core.db.common import CommonSessionLocal
from app.modules.services.execution import generate_tasks_for_subscription_if_ready
from app.modules.services.models import (
    ClientServiceSubscription,
    ClientServiceTaskInstance,
    FirmServiceTaskTemplate,
)


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(
        description=(
            "Generate missing task instances for existing active engagements. "
            "Dry-run is the default; pass --apply to commit."
        )
    )
    parser.add_argument("--apply", action="store_true", help="Commit generated tasks.")
    parser.add_argument("--tenant-id", type=int, default=None, help="Optional tenant filter.")
    parser.add_argument(
        "--subscription-id",
        type=int,
        action="append",
        default=[],
        help="Repair only this engagement/subscription ID. May be repeated.",
    )
    return parser.parse_args()


def main() -> int:
    args = parse_args()
    db = CommonSessionLocal()
    try:
        existing_task_count = (
            select(
                ClientServiceTaskInstance.subscription_id.label("subscription_id"),
                func.count(ClientServiceTaskInstance.id).label("task_count"),
            )
            .group_by(ClientServiceTaskInstance.subscription_id)
            .subquery()
        )

        stmt = (
            select(ClientServiceSubscription)
            .outerjoin(
                existing_task_count,
                existing_task_count.c.subscription_id == ClientServiceSubscription.id,
            )
            .where(
                ClientServiceSubscription.status == "active",
                ClientServiceSubscription.is_active.is_(True),
                func.coalesce(existing_task_count.c.task_count, 0) == 0,
            )
            .order_by(ClientServiceSubscription.tenant_id, ClientServiceSubscription.id)
        )

        if args.tenant_id is not None:
            stmt = stmt.where(ClientServiceSubscription.tenant_id == args.tenant_id)
        if args.subscription_id:
            stmt = stmt.where(ClientServiceSubscription.id.in_(args.subscription_id))

        engagements = db.execute(stmt).scalars().all()
        print(f"Candidate active engagements with zero task instances: {len(engagements)}")

        summary = Counter()
        total_created = 0

        for engagement in engagements:
            template_count = db.execute(
                select(func.count(FirmServiceTaskTemplate.id)).where(
                    FirmServiceTaskTemplate.tenant_id == engagement.tenant_id,
                    FirmServiceTaskTemplate.service_catalogue_id == engagement.service_catalogue_id,
                    FirmServiceTaskTemplate.is_active.is_(True),
                )
            ).scalar_one()

            actor_user_id = (
                engagement.updated_by_user_id
                or engagement.created_by_user_id
                or engagement.assigned_partner_user_id
                or engagement.assigned_manager_user_id
                or engagement.assigned_staff_user_id
            )

            if not template_count:
                summary["no_active_templates"] += 1
                print(
                    f"SKIP engagement={engagement.id}: "
                    "no active Firm Service Task Templates."
                )
                continue

            if not actor_user_id:
                summary["no_actor_user"] += 1
                print(
                    f"SKIP engagement={engagement.id}: "
                    "no valid existing actor/team user available for audit fields."
                )
                continue

            created = generate_tasks_for_subscription_if_ready(
                db,
                subscription=engagement,
                user_id=int(actor_user_id),
            )
            if created:
                total_created += created
                summary["repaired"] += 1
                print(
                    f"READY engagement={engagement.id}: "
                    f"{created} task instance(s) generated from {template_count} active template(s)."
                )
            else:
                summary["quality_gate_or_no_change"] += 1
                print(
                    f"NO CHANGE engagement={engagement.id}: "
                    "AQMM acceptance gate is pending or no task was required."
                )

        if args.apply:
            db.commit()
            print(f"COMMITTED. Total task instances generated: {total_created}")
        else:
            db.rollback()
            print(f"DRY RUN ONLY. Would generate {total_created} task instance(s). No database changes committed.")

        print("Summary:")
        for key in sorted(summary):
            print(f"  {key}: {summary[key]}")
        return 0
    except Exception:
        db.rollback()
        raise
    finally:
        db.close()


if __name__ == "__main__":
    raise SystemExit(main())
