from __future__ import annotations

import json
import os
import re
from dataclasses import dataclass
from datetime import date
from pathlib import Path

import requests

from ..config import ClientConfig, client_dir
from ..history import append_change_markdown, append_history, now_local
from ..table import print_table


TASK_ID = "optimize_product_feed"
TASK_NAME = "Optymalizacja feed produktow"
TASK_TITLES_ID = "optimize_product_titles"
TASK_TITLES_NAME = "Optymalizacja tytulow produktow"
TASK_CATEGORIES_ID = "optimize_product_categories"
TASK_CATEGORIES_NAME = "Optymalizacja kategorii Google"
TASK_UNIT_PRICING_ID = "fill_product_unit_pricing"
TASK_UNIT_PRICING_NAME = "Uzupelnienie unit pricing"


@dataclass
class ProductFeedPlan:
    products: list[dict]
    title_changes: list[dict]
    category_changes: list[dict]
    unit_pricing_changes: list[dict]
    skipped: list[dict]
    warnings: list[str]
    task_id: str = TASK_ID
    task_name: str = TASK_NAME

    def to_dict(self) -> dict:
        return {
            "task": self.task_id,
            "task_name": self.task_name,
            "products": self.products,
            "title_changes": self.title_changes,
            "category_changes": self.category_changes,
            "unit_pricing_changes": self.unit_pricing_changes,
            "skipped": self.skipped,
            "warnings": self.warnings,
        }

    @classmethod
    def from_dict(cls, data: dict) -> "ProductFeedPlan":
        return cls(
            products=data.get("products", []),
            title_changes=data.get("title_changes", []),
            category_changes=data.get("category_changes", []),
            unit_pricing_changes=data.get("unit_pricing_changes", data.get("unit_pricing_previews", [])),
            skipped=data.get("skipped", []),
            warnings=data.get("warnings", []),
            task_id=data.get("task", TASK_ID),
            task_name=data.get("task_name", TASK_NAME),
        )


def adspro_credentials(client_config: ClientConfig) -> tuple[str, str, str]:
    api_url = os.environ.get("ADSPRO_API_URL")
    api_key = os.environ.get("ADSPRO_API_KEY")
    if not api_url or not api_key:
        raise RuntimeError("Brak ADSPRO_API_URL lub ADSPRO_API_KEY w .env.")
    if not client_config.adspro_client_id:
        raise RuntimeError(f"Brak adspro_client_id dla {client_config.domain} w config/clients.toml.")
    return api_url, api_key, client_config.adspro_client_id


def adspro_request(api_url: str, payload: dict, timeout: int = 30) -> dict:
    response = requests.post(api_url, data=payload, timeout=timeout)
    response.raise_for_status()
    response.encoding = "utf-8"
    data = response.json()
    if data.get("result") == "error":
        raise RuntimeError(data.get("message") or "adsPRO zwrocil blad.")
    return data


def fetch_products_by_action(client_config: ClientConfig, action: str, limit: int) -> list[dict]:
    api_url, api_key, adspro_client_id = adspro_credentials(client_config)
    data = adspro_request(
        api_url,
        {
            "action": action,
            "api_key": api_key,
            "client_id": adspro_client_id,
            "limit": str(limit),
        },
        timeout=60,
    )
    return data.get("products", [])


def fetch_missing_title_products(client_config: ClientConfig, limit: int) -> list[dict]:
    return fetch_products_by_action(client_config, "products_get_missing_title", limit)


def fetch_missing_category_products(client_config: ClientConfig, limit: int) -> list[dict]:
    return fetch_products_by_action(client_config, "products_get_missing_google_category", limit)


def fetch_missing_unit_pricing_products(client_config: ClientConfig, limit: int) -> list[dict]:
    api_url, api_key, adspro_client_id = adspro_credentials(client_config)
    data = adspro_request(
        api_url,
        {
            "action": "products_get_missing_unit_pricing",
            "api_key": api_key,
            "client_id": adspro_client_id,
            "top": str(limit),
        },
        timeout=60,
    )
    return data.get("products", [])


def merge_products(*groups: list[dict]) -> list[dict]:
    merged: dict[str, dict] = {}
    for products in groups:
        for product in products:
            offer_id = str(product.get("offer_id") or product.get("id") or "").strip()
            if not offer_id:
                continue
            merged.setdefault(offer_id, {}).update(product)
    return list(merged.values())


def changelog_path(domain: str) -> Path:
    return client_dir(domain) / "produkty_changelog.jsonl"


def read_product_changelog(domain: str) -> list[dict]:
    path = changelog_path(domain)
    if not path.exists():
        return []
    entries = []
    for line in path.read_text(encoding="utf-8").splitlines():
        line = line.strip()
        if not line:
            continue
        try:
            entries.append(json.loads(line))
        except json.JSONDecodeError:
            continue
    return entries


def latest_title_change_dates(domain: str) -> dict[str, date]:
    latest: dict[str, date] = {}
    for entry in read_product_changelog(domain):
        if entry.get("field") != "title":
            continue
        product_id = str(entry.get("product_id") or entry.get("offer_id") or "")
        if not product_id:
            continue
        try:
            changed_at = date.fromisoformat(str(entry.get("date")))
        except ValueError:
            continue
        if product_id not in latest or changed_at > latest[product_id]:
            latest[product_id] = changed_at
    return latest


def append_product_changelog(domain: str, rows: list[dict]) -> Path:
    path = changelog_path(domain)
    path.parent.mkdir(parents=True, exist_ok=True)
    today = now_local().date().isoformat()
    with path.open("a", encoding="utf-8") as f:
        for row in rows:
            f.write(
                json.dumps(
                    {
                        "product_id": row["offer_id"],
                        "date": today,
                        "field": row["field"],
                        "old": row.get("current_value", ""),
                        "new": row.get("target_value", ""),
                    },
                    ensure_ascii=False,
                )
                + "\n"
            )
    return path


def clean_title(value: str) -> str:
    value = re.sub(r"\s+", " ", value or "").strip()
    value = value.replace(" - - ", " - ")
    if value.isupper() and len(value) > 12:
        value = value.title()
    return value[:150].strip()


def suggest_title(product: dict) -> str:
    source = product.get("default_name") or product.get("title") or product.get("custom_title") or ""
    title = clean_title(source)
    brand = clean_title(product.get("brand") or "")
    if brand and title and not title.lower().startswith(brand.lower()):
        title = clean_title(f"{brand} {title}")
    return title


def unit_pricing_preview(title: str) -> dict | None:
    match = re.search(r"(\d+(?:[,.]\d+)?)\s*(ml|l|g|kg|szt|sztuk|caps|kaps)\b", title or "", re.IGNORECASE)
    if not match:
        return None
    amount = match.group(1).replace(",", ".")
    unit = match.group(2).lower()
    unit = {"sztuk": "szt", "caps": "szt", "kaps": "szt"}.get(unit, unit)
    if unit in {"ml", "l"}:
        base = "100 ml" if unit == "ml" else "1 l"
    elif unit in {"g", "kg"}:
        base = "100 g" if unit == "g" else "1 kg"
    else:
        base = "1 szt"
    return {
        "unit_pricing_measure": f"{amount} {unit}",
        "unit_pricing_base_measure": base,
    }


def build_product_feed_plan(
    client_config: ClientConfig,
    global_rules: dict,
    scope: str = "all",
    task_id: str = TASK_ID,
    task_name: str = TASK_NAME,
) -> ProductFeedPlan:
    rules = client_config.effective_rules(global_rules, "product_feed_optimization")
    limit = int(rules.get("limit", 10))
    min_days_between_title_changes = int(rules.get("min_days_between_title_changes", 30))

    title_products = fetch_missing_title_products(client_config, limit) if scope in {"all", "titles"} else []
    category_products = fetch_missing_category_products(client_config, limit) if scope in {"all", "categories"} else []
    unit_products = fetch_missing_unit_pricing_products(client_config, limit) if scope in {"all", "unit_pricing"} else []
    products = merge_products(title_products, category_products, unit_products)
    latest_changes = latest_title_change_dates(client_config.domain)
    today = now_local().date()

    title_changes = []
    category_changes = []
    unit_changes = []
    skipped = []
    warnings = []

    for product in title_products:
        offer_id = str(product.get("offer_id") or product.get("id") or "").strip()
        default_title = product.get("default_name") or product.get("title") or ""
        if not offer_id:
            skipped.append({"offer_id": "", "reason": "produkt bez offer_id"})
            continue

        changed_at = latest_changes.get(offer_id)
        if changed_at and (today - changed_at).days < min_days_between_title_changes:
            skipped.append(
                {
                    "offer_id": offer_id,
                    "reason": f"tytul zmieniony {(today - changed_at).days} dni temu, minimum {min_days_between_title_changes}",
                }
            )
            continue

        needs_title = bool(product.get("needs_title")) or not product.get("title_changed")
        proposed_title = suggest_title(product)
        current_title = product.get("custom_title") or default_title
        if needs_title and proposed_title and proposed_title != current_title:
            title_changes.append(
                {
                    "offer_id": offer_id,
                    "field": "title",
                    "current_value": current_title,
                    "target_value": proposed_title,
                    "reason": "brak zoptymalizowanego tytulu lub tytul wymaga normalizacji",
                }
            )
        elif needs_title:
            title_changes.append(
                {
                    "offer_id": offer_id,
                    "field": "title",
                    "current_value": current_title,
                    "target_value": "",
                    "reason": "brak zoptymalizowanego tytulu; tytul wybiera agent AI po analizie produktu",
                    "requires_agent_decision": True,
                }
            )

    for product in category_products:
        offer_id = str(product.get("offer_id") or product.get("id") or "").strip()
        if not offer_id:
            skipped.append({"offer_id": "", "reason": "produkt bez offer_id"})
            continue
        current_category = product.get("google_product_category") or product.get("google_category") or ""
        category_changes.append(
            {
                "offer_id": offer_id,
                "field": "google_product_category",
                "current_value": current_category,
                "target_value": "",
                "reason": "brak kategorii Google; kategorie wybiera agent AI po analizie produktu",
                "requires_agent_decision": True,
            }
        )

    seen_unit_offer_ids = set()
    for product in unit_products:
        offer_id = str(product.get("offer_id") or product.get("id") or "").strip()
        default_title = product.get("default_name") or product.get("title") or product.get("custom_title") or ""
        if not offer_id or offer_id in seen_unit_offer_ids:
            continue
        seen_unit_offer_ids.add(offer_id)
        preview = unit_pricing_preview(default_title)
        if not preview:
            skipped.append({"offer_id": offer_id, "reason": "brak jednoznacznego unit pricing w nazwie produktu"})
            continue
        unit_changes.append(
            {
                "offer_id": offer_id,
                "field": "unit_pricing",
                "title": default_title,
                "current_unit_pricing_measure": product.get("unit_pricing_measure") or "",
                "current_unit_pricing_base_measure": product.get("unit_pricing_base_measure") or "",
                "unit_pricing_measure": preview["unit_pricing_measure"],
                "unit_pricing_base_measure": preview["unit_pricing_base_measure"],
                "reason": "brak unit pricing; wartosc wyliczona z nazwy produktu",
            }
        )

    if scope == "titles" and not title_products:
        warnings.append("adsPRO nie zwrocil produktow bez zoptymalizowanego tytulu.")
    if scope == "categories" and not category_products:
        warnings.append("adsPRO nie zwrocil produktow bez kategorii Google.")
    if scope == "all" and not products:
        warnings.append("adsPRO nie zwrocil produktow do optymalizacji.")
    if scope == "unit_pricing" and not unit_products:
        warnings.append("adsPRO nie zwrocil produktow bez unit pricing.")
    if category_changes:
        warnings.append("Kategorie Google wybiera agent AI; skrypt nie zgaduje ich automatycznie.")
    if title_changes and any(row.get("requires_agent_decision") for row in title_changes):
        warnings.append("Czesc tytulow wymaga decyzji agenta AI; skrypt nie przepisuje tytulu bazowego jako optymalizacji.")
    if unit_changes:
        warnings.append("Unit pricing zostanie zapisany w adsPRO dopiero po akceptacji planu.")

    return ProductFeedPlan(
        products=products,
        title_changes=title_changes,
        category_changes=category_changes,
        unit_pricing_changes=unit_changes,
        skipped=skipped,
        warnings=warnings,
        task_id=task_id,
        task_name=task_name,
    )


def save_product_feed_plan(domain: str, plan: ProductFeedPlan) -> tuple[Path, Path]:
    ts = now_local()
    base = client_dir(domain) / "plans"
    base.mkdir(parents=True, exist_ok=True)
    stem = f"{ts.strftime('%Y-%m-%d_%H-%M-%S')}_{plan.task_id}"
    json_path = base / f"{stem}.json"
    md_path = base / f"{stem}.md"
    payload = {
        "created_at": ts.isoformat(timespec="seconds"),
        "client": domain,
        **plan.to_dict(),
    }
    json_path.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8")

    lines = [
        f"# Plan: {plan.task_name}",
        "",
        f"Klient: {domain}",
        f"Utworzono: {ts.isoformat(timespec='seconds')}",
        "",
        "## Podsumowanie",
        "",
        f"- Produkty z adsPRO: {len(plan.products)}",
        f"- Tytuly do zmiany: {len(plan.title_changes)}",
        f"- Kategorie do uzupelnienia: {len(plan.category_changes)}",
        f"- Unit pricing do zmiany: {len(plan.unit_pricing_changes)}",
        f"- Pominiete: {len(plan.skipped)}",
        "",
    ]
    if plan.warnings:
        lines.extend(["## Uwagi", ""])
        lines.extend(f"- {item}" for item in plan.warnings)
        lines.append("")
    if plan.title_changes:
        lines.extend(["## Tytuly do decyzji lub zmiany", "", "| Produkt | Obecnie | Docelowo | Powod |", "| --- | --- | --- | --- |"])
        for row in plan.title_changes:
            lines.append(f"| {row['offer_id']} | {row['current_value']} | {row['target_value']} | {row['reason']} |")
        lines.append("")
    if plan.category_changes:
        lines.extend(["## Kategorie Google do decyzji agenta AI", "", "| Produkt | Obecnie | Decyzja agenta AI | Powod |", "| --- | --- | --- | --- |"])
        for row in plan.category_changes:
            lines.append(f"| {row['offer_id']} | {row['current_value']} | {row['target_value']} | {row['reason']} |")
        lines.append("")
    if plan.unit_pricing_changes:
        lines.extend(["## Unit pricing do zmiany", "", "| Produkt | Measure | Base measure | Powod |", "| --- | --- | --- | --- |"])
        for row in plan.unit_pricing_changes:
            lines.append(
                f"| {row['offer_id']} | {row['unit_pricing_measure']} | {row['unit_pricing_base_measure']} | {row['reason']} |"
            )
        lines.append("")
    if plan.skipped:
        lines.extend(["## Pominiete", "", "| Produkt | Powod |", "| --- | --- |"])
        for row in plan.skipped:
            lines.append(f"| {row.get('offer_id', '')} | {row.get('reason', '')} |")
        lines.append("")
    md_path.write_text("\n".join(lines), encoding="utf-8")
    return json_path, md_path


def print_product_feed_plan(plan: ProductFeedPlan) -> None:
    print(f"\nPlan: {plan.task_name}")
    print_table(
        ["Zakres", "Liczba"],
        [
            ["Produkty z adsPRO", str(len(plan.products))],
            ["Tytuly do zmiany", str(len(plan.title_changes))],
            ["Kategorie do uzupelnienia", str(len(plan.category_changes))],
            ["Unit pricing do zmiany", str(len(plan.unit_pricing_changes))],
            ["Pominiete", str(len(plan.skipped))],
        ],
    )
    if plan.title_changes:
        print("\nNajwazniejsze dzialania")
        rows = [
            [str(i), row["offer_id"], "Zmien tytul", row["target_value"]]
            for i, row in enumerate(plan.title_changes[:10], 1)
        ]
        print_table(["Nr", "Produkt", "Dzialanie", "Docelowo"], rows)
        if len(plan.title_changes) > 10:
            print(f"... oraz {len(plan.title_changes) - 10} kolejnych zmian tytulow")
    for warning in plan.warnings:
        print(f"Uwaga: {warning}")


def print_next_navigation(domain: str) -> None:
    print("\nCo dalej:")
    print(f"1. Lista zadan klienta {domain}")
    print("2. Lista klientow")
    print("3. Zakoncz")
    print("\nKomendy:")
    print(f"1 -> python gads.py analiza-klienta --client {domain}")
    print("2 -> python gads.py analiza-klienta")


def set_product_title(api_url: str, api_key: str, client_id: str, row: dict) -> None:
    adspro_request(
        api_url,
        {
            "action": "product_title_set",
            "api_key": api_key,
            "client_id": client_id,
            "offer_id": row["offer_id"],
            "title": row["target_value"],
        },
    )


def set_product_category(api_url: str, api_key: str, client_id: str, row: dict) -> None:
    adspro_request(
        api_url,
        {
            "action": "product_google_category_set",
            "api_key": api_key,
            "client_id": client_id,
            "offer_id": row["offer_id"],
            "google_product_category": row["target_value"],
        },
    )


def set_product_unit_pricing(api_url: str, api_key: str, client_id: str, row: dict) -> None:
    adspro_request(
        api_url,
        {
            "action": "product_unit_pricing_set",
            "api_key": api_key,
            "client_id": client_id,
            "offer_id": row["offer_id"],
            "unit_pricing_measure": row["unit_pricing_measure"],
            "unit_pricing_base_measure": row["unit_pricing_base_measure"],
        },
    )


def apply_product_feed_plan(client_config: ClientConfig, plan: ProductFeedPlan, show_navigation: bool = True) -> None:
    api_url, api_key, adspro_client_id = adspro_credentials(client_config)
    applied = []
    skipped = []

    for row in plan.title_changes:
        if not row.get("target_value"):
            skipped.append({**row, "skip_reason": "brak target_value"})
            continue
        set_product_title(api_url, api_key, adspro_client_id, row)
        applied.append(row)

    for row in plan.category_changes:
        if not row.get("target_value"):
            skipped.append({**row, "skip_reason": "brak target_value"})
            continue
        set_product_category(api_url, api_key, adspro_client_id, row)
        applied.append(row)

    for row in plan.unit_pricing_changes:
        if not row.get("unit_pricing_measure") or not row.get("unit_pricing_base_measure"):
            skipped.append({**row, "skip_reason": "brak unit_pricing_measure lub unit_pricing_base_measure"})
            continue
        set_product_unit_pricing(api_url, api_key, adspro_client_id, row)
        applied.append(
            {
                "offer_id": row["offer_id"],
                "field": "unit_pricing",
                "current_value": (
                    f"{row.get('current_unit_pricing_measure', '')} / "
                    f"{row.get('current_unit_pricing_base_measure', '')}"
                ).strip(" /"),
                "target_value": f"{row['unit_pricing_measure']} / {row['unit_pricing_base_measure']}",
            }
        )

    print("\nWynik wdrozenia zmian")
    print(f"Wdrozono zmian: {len(applied)}")
    print(f"Pominieto: {len(skipped)}")

    change_rows = [
        {
            "klient": client_config.domain,
            "produkt": row["offer_id"],
            "pole": row["field"],
            "obecnie": row.get("current_value", ""),
            "docelowo": row.get("target_value", ""),
        }
        for row in applied
    ]
    changes_path = append_change_markdown(client_config.domain, plan.task_name, change_rows)
    history_path = append_history(
        client_config.domain,
        {
            "task": plan.task_name,
            "status": "wdrozono zmiany",
            "product": ", ".join(row["offer_id"] for row in applied[:10]),
            "summary": {"applied": len(applied), "skipped": len(skipped)},
        },
    )
    changelog = append_product_changelog(client_config.domain, applied) if applied else changelog_path(client_config.domain)
    print(f"Historia JSONL: {history_path}")
    print(f"Historia Markdown: {changes_path}")
    print(f"Changelog produktow: {changelog}")
    if show_navigation:
        print_next_navigation(client_config.domain)


def run_product_feed_task(
    client_config: ClientConfig,
    global_rules: dict,
    scope: str,
    task_id: str,
    task_name: str,
    plan_only: bool = False,
    apply_plan_path: str | None = None,
    confirm_apply: str | None = None,
    show_navigation: bool = True,
) -> None:
    if apply_plan_path:
        if confirm_apply != "TAK":
            print("Do wdrozenia planu wymagane jest --confirm-apply TAK.")
            if show_navigation:
                print_next_navigation(client_config.domain)
            return
        plan_data = json.loads(Path(apply_plan_path).read_text(encoding="utf-8"))
        if plan_data.get("client") != client_config.domain:
            print(f"Plan jest dla klienta {plan_data.get('client')}, a wybrano {client_config.domain}.")
            if show_navigation:
                print_next_navigation(client_config.domain)
            return
        plan = ProductFeedPlan.from_dict(plan_data)
        print_product_feed_plan(plan)
        apply_product_feed_plan(client_config, plan, show_navigation=show_navigation)
        return

    print(f"\nKlient: {client_config.domain}")
    print(f"Pobieram produkty z adsPRO i przygotowuje plan: {task_name}...")
    plan = build_product_feed_plan(client_config, global_rules, scope=scope, task_id=task_id, task_name=task_name)
    print_product_feed_plan(plan)
    json_path, md_path = save_product_feed_plan(client_config.domain, plan)
    print(f"\nPlan JSON: {json_path}")
    print(f"Plan Markdown: {md_path}")

    append_history(
        client_config.domain,
        {
            "task": task_name,
            "status": "plan przygotowany",
            "product": ", ".join(str(product.get("offer_id") or product.get("id") or "") for product in plan.products[:10]),
            "summary": {
                "products": len(plan.products),
                "title_changes": len(plan.title_changes),
                "category_changes": len(plan.category_changes),
                "unit_pricing_changes": len(plan.unit_pricing_changes),
            },
        },
    )

    if plan_only:
        print("\nTryb plan-only: zmiany nie zostaly wdrozone.")
        if show_navigation:
            print_next_navigation(client_config.domain)
        return

    if (
        not plan.title_changes
        and not any(row.get("target_value") for row in plan.category_changes)
        and not plan.unit_pricing_changes
    ):
        print("\nBrak gotowych zmian do wdrozenia.")
        append_change_markdown(client_config.domain, task_name, [])
        if show_navigation:
            print_next_navigation(client_config.domain)
        return

    answer = input("\nWpisz TAK, aby wdrozyc powyzsze zmiany: ").strip()
    if answer != "TAK":
        print("Przerwano. Zmiany nie zostaly wdrozone.")
        append_history(
            client_config.domain,
            {
                "task": task_name,
                "status": "odrzucono wdrozenie",
                "product": ", ".join(row["offer_id"] for row in plan.title_changes[:10]),
            },
        )
        if show_navigation:
            print_next_navigation(client_config.domain)
        return

    apply_product_feed_plan(client_config, plan, show_navigation=show_navigation)


def run_optimize_product_feed(
    client_config: ClientConfig,
    global_rules: dict,
    plan_only: bool = False,
    apply_plan_path: str | None = None,
    confirm_apply: str | None = None,
    show_navigation: bool = True,
) -> None:
    run_product_feed_task(
        client_config,
        global_rules,
        "all",
        TASK_ID,
        TASK_NAME,
        plan_only=plan_only,
        apply_plan_path=apply_plan_path,
        confirm_apply=confirm_apply,
        show_navigation=show_navigation,
    )


def run_optimize_product_titles(
    client_config: ClientConfig,
    global_rules: dict,
    plan_only: bool = False,
    apply_plan_path: str | None = None,
    confirm_apply: str | None = None,
    show_navigation: bool = True,
) -> None:
    run_product_feed_task(
        client_config,
        global_rules,
        "titles",
        TASK_TITLES_ID,
        TASK_TITLES_NAME,
        plan_only=plan_only,
        apply_plan_path=apply_plan_path,
        confirm_apply=confirm_apply,
        show_navigation=show_navigation,
    )


def run_optimize_product_categories(
    client_config: ClientConfig,
    global_rules: dict,
    plan_only: bool = False,
    apply_plan_path: str | None = None,
    confirm_apply: str | None = None,
    show_navigation: bool = True,
) -> None:
    run_product_feed_task(
        client_config,
        global_rules,
        "categories",
        TASK_CATEGORIES_ID,
        TASK_CATEGORIES_NAME,
        plan_only=plan_only,
        apply_plan_path=apply_plan_path,
        confirm_apply=confirm_apply,
        show_navigation=show_navigation,
    )


def run_fill_product_unit_pricing(
    client_config: ClientConfig,
    global_rules: dict,
    plan_only: bool = False,
    apply_plan_path: str | None = None,
    confirm_apply: str | None = None,
    show_navigation: bool = True,
) -> None:
    run_product_feed_task(
        client_config,
        global_rules,
        "unit_pricing",
        TASK_UNIT_PRICING_ID,
        TASK_UNIT_PRICING_NAME,
        plan_only=plan_only,
        apply_plan_path=apply_plan_path,
        confirm_apply=confirm_apply,
        show_navigation=show_navigation,
    )
