from __future__ import annotations

import json
from collections import Counter
from dataclasses import dataclass
from pathlib import Path
from typing import Any

from google.protobuf import field_mask_pb2

from ..config import ClientConfig, client_dir
from ..google_ads import get_google_ads_client, run_query
from ..history import append_change_markdown, append_history, now_local
from ..knowledge.store import rules_for_task
from ..table import print_table


TASK_ID = "check_conversion_tracking"
TASK_NAME = "Sprawdzenie pomiaru konwersji"


DEFAULT_SCOPE = [
    {
        "area": "Akcje konwersji",
        "check": "Pobierz akcje konwersji z Google Ads, ich status, typ, kategorie i ustawienie podstawowa/dodatkowa.",
    },
    {
        "area": "Dane 30 dni",
        "check": "Sprawdz, czy akcje konwersji zbieraja konwersje, wartosc konwersji i wszystkie konwersje z ostatnich 30 dni.",
    },
    {
        "area": "Wartosc konwersji",
        "check": "Oznacz konwersje zakupowe i e-commerce bez wartosci albo bez waluty jako problem do poprawy pomiaru.",
    },
    {
        "area": "Jakosc optymalizacji",
        "check": "Oznacz brak aktywnych konwersji podstawowych, brak danych 30 dni oraz podejrzana duplikacje podobnych akcji.",
    },
    {
        "area": "Rekomendacje",
        "check": "Przygotuj rekomendacje decyzyjne do konfiguracji pomiaru; skrypt nie wdraza zmian automatycznie.",
    },
]


ECOMMERCE_CATEGORIES = {"PURCHASE", "STORE_SALE", "ADD_TO_CART", "BEGIN_CHECKOUT"}
NO_DYNAMIC_VALUE_TYPES = {"AD_CALL", "WEBSITE_CALL"}
LEAD_CATEGORIES = {
    "SUBMIT_LEAD_FORM",
    "CONTACT",
    "REQUEST_QUOTE",
    "BOOK_APPOINTMENT",
    "PHONE_CALL_LEAD",
    "IMPORTED_LEAD",
}


@dataclass
class ConversionTrackingPlan:
    currency_code: str
    conversion_actions: list[dict]
    action_summary: list[dict]
    findings: list[dict]
    changes: list[dict]
    scope: list[dict]
    knowledge_rules: list[dict]
    warnings: list[str]

    def to_dict(self) -> dict:
        return {
            "task": TASK_ID,
            "task_name": TASK_NAME,
            "currency_code": self.currency_code,
            "conversion_actions": self.conversion_actions,
            "action_summary": self.action_summary,
            "findings": self.findings,
            "changes": self.changes,
            "scope": self.scope,
            "knowledge_rules": self.knowledge_rules,
            "warnings": self.warnings,
        }

    @classmethod
    def from_dict(cls, data: dict) -> "ConversionTrackingPlan":
        return cls(
            currency_code=data.get("currency_code", ""),
            conversion_actions=data.get("conversion_actions", []),
            action_summary=data.get("action_summary", []),
            findings=data.get("findings", []),
            changes=data.get("changes", []),
            scope=data.get("scope", []),
            knowledge_rules=data.get("knowledge_rules", []),
            warnings=data.get("warnings", []),
        )


def enum_name(value: Any) -> str:
    name = getattr(value, "name", None)
    if name:
        return name
    return str(value or "")


def safe_float(value: Any) -> float:
    try:
        return float(value or 0)
    except (TypeError, ValueError):
        return 0.0


def safe_int(value: Any) -> int:
    try:
        return int(value or 0)
    except (TypeError, ValueError):
        return 0


def format_decimal(value: Any) -> str:
    return f"{safe_float(value):.2f}"


def format_money(value: Any, currency_code: str) -> str:
    suffix = f" {currency_code}" if currency_code else ""
    return f"{safe_float(value):.2f}{suffix}"


def md_cell(value: Any) -> str:
    return str(value or "").replace("|", "\\|").replace("\n", " ").strip()


def bool_label(value: bool) -> str:
    return "TAK" if value else "NIE"


def get_attr(obj: Any, path: str, default: Any = "") -> Any:
    current = obj
    for part in path.split("."):
        try:
            current = getattr(current, part)
        except Exception:
            return default
        if current is None:
            return default
    return current


def fetch_customer_currency(client_config: ClientConfig, google_client) -> str:
    rows = run_query(
        google_client,
        client_config.safe_customer_id,
        """
        SELECT
          customer.currency_code
        FROM customer
        LIMIT 1
        """,
    )
    for row in rows:
        return str(row.customer.currency_code or "")
    return ""


def fetch_conversion_actions(client_config: ClientConfig, google_client) -> list[dict]:
    rows = run_query(
        google_client,
        client_config.safe_customer_id,
        """
        SELECT
          conversion_action.id,
          conversion_action.resource_name,
          conversion_action.name,
          conversion_action.status,
          conversion_action.type,
          conversion_action.category,
          conversion_action.primary_for_goal,
          conversion_action.include_in_conversions_metric,
          conversion_action.counting_type,
          conversion_action.value_settings.default_value,
          conversion_action.value_settings.default_currency_code,
          conversion_action.value_settings.always_use_default_value,
          conversion_action.click_through_lookback_window_days,
          conversion_action.view_through_lookback_window_days,
          conversion_action.attribution_model_settings.attribution_model
        FROM conversion_action
        WHERE conversion_action.status != 'REMOVED'
        """,
    )
    actions = []
    for row in rows:
        action = row.conversion_action
        actions.append(
            {
                "conversion_action_id": str(action.id),
                "resource_name": str(action.resource_name or ""),
                "name": str(action.name or ""),
                "status": enum_name(action.status),
                "type": enum_name(action.type_),
                "category": enum_name(action.category),
                "primary_for_goal": bool(get_attr(action, "primary_for_goal", False)),
                "include_in_conversions_metric": bool(get_attr(action, "include_in_conversions_metric", False)),
                "counting_type": enum_name(get_attr(action, "counting_type", "")),
                "default_value": safe_float(get_attr(action, "value_settings.default_value", 0)),
                "default_currency_code": str(get_attr(action, "value_settings.default_currency_code", "") or ""),
                "always_use_default_value": bool(get_attr(action, "value_settings.always_use_default_value", False)),
                "click_window_days": safe_int(get_attr(action, "click_through_lookback_window_days", 0)),
                "view_window_days": safe_int(get_attr(action, "view_through_lookback_window_days", 0)),
                "attribution_model": enum_name(
                    get_attr(action, "attribution_model_settings.attribution_model", "")
                ),
            }
        )
    actions.sort(key=lambda item: (item["status"] != "ENABLED", item["category"], item["name"]))
    return actions


def fetch_conversion_performance(client_config: ClientConfig, google_client) -> dict[str, dict]:
    rows = run_query(
        google_client,
        client_config.safe_customer_id,
        """
        SELECT
          segments.conversion_action,
          segments.conversion_action_name,
          segments.conversion_action_category,
          metrics.conversions,
          metrics.conversions_value,
          metrics.all_conversions,
          metrics.all_conversions_value
        FROM customer
        WHERE segments.date DURING LAST_30_DAYS
        """,
    )
    performance: dict[str, dict] = {}
    for row in rows:
        resource_name = str(row.segments.conversion_action or "")
        if not resource_name:
            continue
        bucket = performance.setdefault(
            resource_name,
            {
                "resource_name": resource_name,
                "name": str(row.segments.conversion_action_name or ""),
                "category": enum_name(row.segments.conversion_action_category),
                "conversions_30d": 0.0,
                "conversion_value_30d": 0.0,
                "all_conversions_30d": 0.0,
                "all_conversion_value_30d": 0.0,
            },
        )
        bucket["conversions_30d"] += safe_float(row.metrics.conversions)
        bucket["conversion_value_30d"] += safe_float(row.metrics.conversions_value)
        bucket["all_conversions_30d"] += safe_float(row.metrics.all_conversions)
        bucket["all_conversion_value_30d"] += safe_float(row.metrics.all_conversions_value)
    return performance


def attach_performance(actions: list[dict], performance: dict[str, dict]) -> list[dict]:
    for action in actions:
        row = performance.get(action["resource_name"], {})
        action["conversions_30d"] = round(safe_float(row.get("conversions_30d")), 2)
        action["conversion_value_30d"] = round(safe_float(row.get("conversion_value_30d")), 2)
        action["all_conversions_30d"] = round(safe_float(row.get("all_conversions_30d")), 2)
        action["all_conversion_value_30d"] = round(safe_float(row.get("all_conversion_value_30d")), 2)
        action["is_collecting_data"] = action["all_conversions_30d"] > 0
        action["problem_flags"] = action_problem_flags(action)
        action["recommendation"] = action_recommendation(action)
    return actions


def can_use_dynamic_conversion_value(action: dict) -> bool:
    return (
        action.get("status") == "ENABLED"
        and action.get("category") in ECOMMERCE_CATEGORIES
        and action.get("type") not in NO_DYNAMIC_VALUE_TYPES
    )


def needs_dynamic_conversion_value(action: dict) -> bool:
    if not can_use_dynamic_conversion_value(action):
        return False
    if action.get("always_use_default_value"):
        return True
    return False


def build_value_setting_changes(actions: list[dict]) -> list[dict]:
    changes = []
    for action in actions:
        if not needs_dynamic_conversion_value(action):
            continue
        reason_parts = []
        if action.get("always_use_default_value"):
            reason_parts.append("akcja uzywa stalej wartosci")
        changes.append(
            {
                "conversion_action_id": action["conversion_action_id"],
                "resource_name": action["resource_name"],
                "name": action["name"],
                "category": action["category"],
                "type": action["type"],
                "setting": "wartosc konwersji",
                "field": "value_settings.always_use_default_value",
                "current_value": "always_use_default_value=true",
                "target_value": "always_use_default_value=false",
                "current_label": "Stala wartosc albo brak wartosci",
                "target_label": "Zastosuj inna wartosc do kazdej konwersji",
                "description": "Ustaw akcje konwersji na uzywanie roznych wartosci dla kazdej konwersji.",
                "reason": ", ".join(reason_parts) or "akcja e-commerce uzywa stalej wartosci",
                "note": "Ta zmiana poprawia ustawienie w Google Ads. Po stronie tagu/GA4/GTM nadal musi byc wysylane value i currency.",
            }
        )
    return changes


def action_problem_flags(action: dict) -> list[str]:
    flags = []
    category = action.get("category", "")
    is_collecting_data = action.get("is_collecting_data") or action.get("all_conversions_30d", 0) > 0
    if action.get("status") != "ENABLED":
        flags.append("akcja nieaktywna")
    if action.get("status") == "ENABLED" and not is_collecting_data:
        flags.append("brak danych 30 dni")
    if action.get("primary_for_goal") and action.get("conversions_30d", 0) <= 0:
        flags.append("podstawowa bez konwersji")
    if category in ECOMMERCE_CATEGORIES and action.get("all_conversions_30d", 0) > 0:
        if action.get("all_conversion_value_30d", 0) <= 0:
            if action.get("always_use_default_value"):
                flags.append("brak wartosci przez ustawienie Google Ads")
            else:
                flags.append("brak wartosci mimo ustawienia dynamicznego")
        if not action.get("default_currency_code"):
            flags.append("brak waluty domyslnej")
    if action.get("always_use_default_value") and category in ECOMMERCE_CATEGORIES:
        flags.append("e-commerce uzywa stalej wartosci")
    return flags or ["ok"]


def action_recommendation(action: dict) -> str:
    flags = set(action.get("problem_flags", []))
    category = action.get("category", "")
    if "akcja nieaktywna" in flags:
        return "Zostaw nieaktywna, jesli jest historyczna; w przeciwnym razie uporzadkuj konfiguracje konwersji."
    if "podstawowa bez konwersji" in flags:
        return "Sprawdz tag i zasadnosc uzywania tej akcji jako podstawowej do optymalizacji."
    if "brak wartosci przez ustawienie Google Ads" in flags and category in ECOMMERCE_CATEGORIES:
        return "W Google Ads wlacz rozne wartosci dla kazdej konwersji, a potem sprawdz czy tag przekazuje value i currency."
    if "brak wartosci mimo ustawienia dynamicznego" in flags and category in ECOMMERCE_CATEGORIES:
        return "Ustawienie w Google Ads wyglada poprawnie; napraw wysylanie value i currency po stronie strony, GTM albo GA4."
    if "e-commerce uzywa stalej wartosci" in flags:
        return "Przelacz pomiar zakupow na rzeczywista wartosc transakcji zamiast stalej wartosci."
    if "brak danych 30 dni" in flags:
        return "Sprawdz, czy akcja nadal powinna byc aktywna i czy tag uruchamia sie na wlasciwym zdarzeniu."
    if action.get("primary_for_goal") and category in LEAD_CATEGORIES:
        return "Dane nadaja sie do optymalizacji leadowej, jesli zdarzenie odpowiada realnemu leadowi."
    if action.get("primary_for_goal") and category in ECOMMERCE_CATEGORIES:
        return "Dane zakupowe wygladaja na podstawowy sygnal optymalizacji; kontroluj wartosc i duplikacje."
    return "Bez pilnej zmiany; zostaw jako kontekst albo konwersje dodatkowa."


def build_action_summary(actions: list[dict]) -> list[dict]:
    counter = Counter()
    counter["akcje konwersji"] = len(actions)
    counter["aktywne"] = sum(1 for action in actions if action["status"] == "ENABLED")
    counter["podstawowe"] = sum(1 for action in actions if action["primary_for_goal"])
    counter["zbieraja dane 30 dni"] = sum(
        1 for action in actions if action.get("is_collecting_data") or action.get("all_conversions_30d", 0) > 0
    )
    counter["z problemami"] = sum(1 for action in actions if action.get("problem_flags", ["ok"]) != ["ok"])
    counter["podstawowe z danymi"] = sum(
        1 for action in actions if action["primary_for_goal"] and action["conversions_30d"] > 0
    )
    return [{"metric": key, "count": value} for key, value in counter.items()]


def duplicate_name_findings(actions: list[dict]) -> list[dict]:
    normalized: dict[tuple[str, str], list[dict]] = {}
    for action in actions:
        key = (" ".join(action["name"].lower().split()), action.get("category", ""))
        normalized.setdefault(key, []).append(action)
    findings = []
    for (_name, category), rows in normalized.items():
        active_rows = [row for row in rows if row["status"] == "ENABLED"]
        if len(active_rows) < 2:
            continue
        findings.append(
            {
                "severity": "srednie",
                "area": "Duplikacja konwersji",
                "item": ", ".join(row["name"] for row in active_rows[:4]),
                "problem": f"{len(active_rows)} aktywne akcje o tej samej nazwie i kategorii {category}",
                "recommendation": "Sprawdz, czy konto nie liczy tego samego zdarzenia kilka razy.",
            }
        )
    return findings


def build_findings(actions: list[dict]) -> list[dict]:
    findings = []
    if not actions:
        findings.append(
            {
                "severity": "wysokie",
                "area": "Konwersje",
                "item": "konto",
                "problem": "brak akcji konwersji",
                "recommendation": "Skonfiguruj podstawowe konwersje przed optymalizacja kampanii.",
            }
        )
        return findings
    primary_actions = [action for action in actions if action["primary_for_goal"] and action["status"] == "ENABLED"]
    if not primary_actions:
        findings.append(
            {
                "severity": "wysokie",
                "area": "Optymalizacja",
                "item": "cele konta",
                "problem": "brak aktywnych konwersji podstawowych",
                "recommendation": "Ustaw jako podstawowe tylko te konwersje, ktore maja sterowac strategiami stawek.",
            }
        )
    if primary_actions and not any(action["conversions_30d"] > 0 for action in primary_actions):
        findings.append(
            {
                "severity": "wysokie",
                "area": "Dane 30 dni",
                "item": "konwersje podstawowe",
                "problem": "konwersje podstawowe nie zbieraja danych z ostatnich 30 dni",
                "recommendation": "Sprawdz tagi, importy i cele przed wlaczaniem automatyzacji opartej o konwersje.",
            }
        )
    for action in actions:
        for flag in action.get("problem_flags", []):
            if flag == "ok":
                continue
            severity = (
                "wysokie"
                if flag in {
                    "podstawowa bez konwersji",
                    "brak wartosci przez ustawienie Google Ads",
                    "brak wartosci mimo ustawienia dynamicznego",
                }
                else "srednie"
            )
            findings.append(
                {
                    "severity": severity,
                    "area": action.get("category", ""),
                    "item": action.get("name", ""),
                    "problem": flag,
                    "recommendation": action.get("recommendation", ""),
                }
            )
    findings.extend(duplicate_name_findings(actions))
    order = {"wysokie": 0, "srednie": 1, "niskie": 2}
    findings.sort(key=lambda item: (order.get(item["severity"], 9), item["area"], item["item"]))
    return findings


def build_conversion_tracking_plan(client_config: ClientConfig) -> ConversionTrackingPlan:
    warnings = []
    currency_code = ""
    actions: list[dict] = []
    try:
        google_client = get_google_ads_client(use_proto_plus=True)
        currency_code = fetch_customer_currency(client_config, google_client)
        actions = fetch_conversion_actions(client_config, google_client)
        performance = fetch_conversion_performance(client_config, google_client)
        actions = attach_performance(actions, performance)
    except Exception as exc:
        warnings.append(f"Nie udalo sie pobrac danych pomiaru konwersji z Google Ads API: {exc}")

    if not client_config.google_ads_customer_id:
        warnings.append("Klient nie ma google_ads_customer_id w config/clients.toml.")
    if not actions:
        warnings.append("Nie znaleziono akcji konwersji albo nie udalo sie ich pobrac.")

    knowledge_rules = [
        {
            "id": rule.id,
            "topic": rule.topic,
            "rule_type": rule.rule_type,
            "condition": rule.condition,
            "recommendation": rule.recommendation,
            "risk": rule.risk,
            "source": rule.source,
        }
        for rule in rules_for_task(TASK_ID)
    ]
    if not knowledge_rules:
        warnings.append(
            "Do tego zadania nie przypisano jeszcze regul z bazy wiedzy. "
            "Reguly dotyczace pomiaru konwersji warto dopisac po pierwszych audytach."
        )

    changes = build_value_setting_changes(actions)
    return ConversionTrackingPlan(
        currency_code=currency_code,
        conversion_actions=actions,
        action_summary=build_action_summary(actions),
        findings=build_findings(actions),
        changes=changes,
        scope=DEFAULT_SCOPE,
        knowledge_rules=knowledge_rules,
        warnings=warnings,
    )


def save_conversion_tracking_plan(domain: str, plan: ConversionTrackingPlan) -> 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')}_{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 = [
        "# Plan: Sprawdzenie pomiaru konwersji",
        "",
        f"Klient: {domain}",
        f"Utworzono: {ts.isoformat(timespec='seconds')}",
        "",
        "## Podsumowanie",
        "",
        f"- Akcje konwersji: {len(plan.conversion_actions)}",
        f"- Problemy / rekomendacje: {len(plan.findings)}",
        f"- Reguly wiedzy przypisane do zadania: {len(plan.knowledge_rules)}",
        f"- Zmiany do wdrozenia: {len(plan.changes)}",
        "",
    ]
    if plan.warnings:
        lines.extend(["## Uwagi", ""])
        lines.extend(f"- {item}" for item in plan.warnings)
        lines.append("")
    lines.extend(["## Zakres audytu", "", "| Obszar | Co sprawdzic |", "| --- | --- |"])
    for row in plan.scope:
        lines.append(f"| {md_cell(row.get('area', ''))} | {md_cell(row.get('check', ''))} |")
    lines.append("")
    if plan.action_summary:
        lines.extend(["## Podsumowanie akcji", "", "| Metryka | Liczba |", "| --- | --- |"])
        for row in plan.action_summary:
            lines.append(f"| {md_cell(row['metric'])} | {row['count']} |")
        lines.append("")
    if plan.findings:
        lines.extend(
            [
                "## Problemy i rekomendacje",
                "",
                "| Waznosc | Obszar | Element | Problem | Rekomendacja |",
                "| --- | --- | --- | --- | --- |",
            ]
        )
        for row in plan.findings:
            lines.append(
                f"| {row['severity']} | {md_cell(row['area'])} | {md_cell(row['item'])} | "
                f"{md_cell(row['problem'])} | {md_cell(row['recommendation'])} |"
            )
        lines.append("")
    if plan.changes:
        lines.extend(
            [
                "## Zmiany do akceptacji",
                "",
                "| Akcja konwersji | Kategoria | Obecnie | Docelowo | Powod | Uwaga |",
                "| --- | --- | --- | --- | --- | --- |",
            ]
        )
        for change in plan.changes:
            lines.append(
                f"| {md_cell(change['name'])} | {change['category']} | "
                f"{md_cell(change['current_label'])} | {md_cell(change['target_label'])} | "
                f"{md_cell(change['reason'])} | {md_cell(change['note'])} |"
            )
        lines.append("")
    if plan.conversion_actions:
        lines.extend(
            [
                "## Akcje konwersji",
                "",
                "| Nazwa | Status | Typ | Kategoria | Podstawowa | W konwersjach | Konw. 30d | Wartosc 30d | Wszystkie konw. 30d | Wartosc wszystkich 30d | Okno klik. | Okno view | Problemy |",
                "| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |",
            ]
        )
        for action in plan.conversion_actions:
            lines.append(
                f"| {md_cell(action['name'])} | {action['status']} | {action['type']} | {action['category']} | "
                f"{bool_label(action['primary_for_goal'])} | {bool_label(action['include_in_conversions_metric'])} | "
                f"{format_decimal(action['conversions_30d'])} | {format_money(action['conversion_value_30d'], plan.currency_code)} | "
                f"{format_decimal(action['all_conversions_30d'])} | {format_money(action['all_conversion_value_30d'], plan.currency_code)} | "
                f"{action['click_window_days']} | {action['view_window_days']} | {md_cell(', '.join(action['problem_flags']))} |"
            )
        lines.append("")
    if plan.knowledge_rules:
        lines.extend(
            [
                "## Reguly z bazy wiedzy",
                "",
                "| ID | Temat | Rekomendacja | Ryzyko |",
                "| --- | --- | --- | --- |",
            ]
        )
        for rule in plan.knowledge_rules:
            lines.append(
                f"| {md_cell(rule.get('id', ''))} | {md_cell(rule.get('topic', ''))} | "
                f"{md_cell(rule.get('recommendation', ''))} | {md_cell(rule.get('risk', ''))} |"
            )
        lines.append("")
    md_path.write_text("\n".join(lines), encoding="utf-8")
    return json_path, md_path


def print_conversion_tracking_plan(plan: ConversionTrackingPlan) -> None:
    print("\nPlan sprawdzenia pomiaru konwersji")
    print_table(
        ["Metryka", "Liczba"],
        [
            ["Akcje konwersji", str(len(plan.conversion_actions))],
            ["Problemy / rekomendacje", str(len(plan.findings))],
            ["Reguly wiedzy", str(len(plan.knowledge_rules))],
            ["Zmiany do wdrozenia", str(len(plan.changes))],
        ],
    )
    if plan.warnings:
        print("\nUwagi")
        print_table(["Nr", "Uwaga"], [[str(index), item] for index, item in enumerate(plan.warnings, 1)])
    print("\nZakres audytu")
    print_table(
        ["Nr", "Obszar", "Co sprawdzic"],
        [[str(index), row["area"], row["check"]] for index, row in enumerate(plan.scope, 1)],
    )
    if plan.action_summary:
        print("\nPodsumowanie akcji")
        print_table(["Metryka", "Liczba"], [[row["metric"], str(row["count"])] for row in plan.action_summary])
    if plan.changes:
        print("\nZmiany do akceptacji")
        print_table(
            ["Nr", "Akcja", "Kategoria", "Obecnie", "Docelowo", "Powod"],
            [
                [
                    str(index),
                    change["name"],
                    change["category"],
                    change["current_label"],
                    change["target_label"],
                    change["reason"],
                ]
                for index, change in enumerate(plan.changes, 1)
            ],
        )
    if plan.findings:
        print("\nProblemy i rekomendacje")
        print_table(
            ["Nr", "Waznosc", "Obszar", "Element", "Problem", "Rekomendacja"],
            [
                [
                    str(index),
                    row["severity"],
                    row["area"],
                    row["item"],
                    row["problem"],
                    row["recommendation"],
                ]
                for index, row in enumerate(plan.findings, 1)
            ],
        )
    if plan.conversion_actions:
        print("\nAkcje konwersji")
        print_table(
            ["Nr", "Nazwa", "Status", "Kategoria", "Podst.", "Konw. 30d", "Wartosc", "Wszystkie", "Problemy"],
            [
                [
                    str(index),
                    action["name"],
                    action["status"],
                    action["category"],
                    bool_label(action["primary_for_goal"]),
                    format_decimal(action["conversions_30d"]),
                    format_money(action["conversion_value_30d"], plan.currency_code),
                    format_decimal(action["all_conversions_30d"]),
                    ", ".join(action["problem_flags"]),
                ]
                for index, action in enumerate(plan.conversion_actions[:30], 1)
            ],
        )
        if len(plan.conversion_actions) > 30:
            print(f"... oraz {len(plan.conversion_actions) - 30} kolejnych akcji w pliku planu")
    if plan.knowledge_rules:
        print("\nReguly z bazy wiedzy")
        print_table(
            ["Nr", "ID", "Temat", "Rekomendacja"],
            [
                [str(index), rule["id"], rule["topic"], rule["recommendation"]]
                for index, rule in enumerate(plan.knowledge_rules[:10], 1)
            ],
        )
        if len(plan.knowledge_rules) > 10:
            print(f"... oraz {len(plan.knowledge_rules) - 10} kolejnych regul")


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 apply_conversion_tracking_plan(
    client_config: ClientConfig,
    plan: ConversionTrackingPlan,
    show_navigation: bool = True,
) -> None:
    changed = 0
    errors = []
    if plan.changes:
        google_client = get_google_ads_client(use_proto_plus=True)
        customer_id = client_config.safe_customer_id
        service = google_client.get_service("ConversionActionService")
        operations = []
        for change in plan.changes:
            if change.get("type") in NO_DYNAMIC_VALUE_TYPES:
                errors.append(f"Pominieto {change.get('name', '')}: typ {change.get('type')} wymaga stalej wartosci.")
                continue
            op = google_client.get_type("ConversionActionOperation")
            conversion_action = op.update
            conversion_action.resource_name = change["resource_name"]
            conversion_action.value_settings.always_use_default_value = False
            op.update_mask = field_mask_pb2.FieldMask(paths=["value_settings.always_use_default_value"])
            operations.append(op)
        if operations:
            try:
                response = service.mutate_conversion_actions(customer_id=customer_id, operations=operations)
                changed = len(response.results)
            except Exception as exc:
                errors.append(str(exc))

    if plan.changes:
        print("\nWynik wdrozenia zmian pomiaru konwersji")
        print(f"Zmieniono akcji konwersji: {changed}")
        print(f"Bledy: {len(errors)}")
        for error in errors:
            print(f"Blad: {error}")
    else:
        print("\nTo zadanie jest audytem pomiaru konwersji i nie ma zmian do wdrozenia.")

    rows = [
        {
            "klient": client_config.domain,
            "kampania": "",
            "czynnosc": change["description"],
            "grupa reklam": "",
            "produkt": f"{change['name']}: {change['current_label']} -> {change['target_label']}. {change.get('note', '')}",
        }
        for change in plan.changes
    ]
    changes_path = append_change_markdown(client_config.domain, TASK_NAME, rows)
    history_path = append_history(
        client_config.domain,
        {
            "task": TASK_NAME,
            "status": "wdrozono zmiany pomiaru konwersji" if plan.changes and not errors else "audyt oznaczony jako wykonany",
            "campaign": "",
            "summary": {
                "conversion_actions": len(plan.conversion_actions),
                "findings": len(plan.findings),
                "knowledge_rules": len(plan.knowledge_rules),
                "changes": len(plan.changes),
                "changed": changed,
                "errors": len(errors),
            },
        },
    )
    print(f"Historia JSONL: {history_path}")
    print(f"Historia Markdown: {changes_path}")
    if show_navigation:
        print_next_navigation(client_config.domain)


def run_check_conversion_tracking(
    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:
    _ = global_rules
    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 = ConversionTrackingPlan.from_dict(plan_data)
        print_conversion_tracking_plan(plan)
        apply_conversion_tracking_plan(client_config, plan, show_navigation=show_navigation)
        return

    print(f"\nKlient: {client_config.domain}")
    print("Pobieram dane pomiaru konwersji z Google Ads API...")
    plan = build_conversion_tracking_plan(client_config)
    print_conversion_tracking_plan(plan)
    json_path, md_path = save_conversion_tracking_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",
            "campaign": "",
            "summary": {
                "conversion_actions": len(plan.conversion_actions),
                "findings": len(plan.findings),
                "knowledge_rules": len(plan.knowledge_rules),
                "changes": len(plan.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.changes:
        print("\nBrak zmian do wdrozenia. To zadanie przygotowuje audyt i rekomendacje pomiaru konwersji.")
        if show_navigation:
            print_next_navigation(client_config.domain)
        return

    answer = input("\nWpisz TAK, aby wdrozyc powyzsze zmiany wartosci konwersji: ").strip()
    if answer != "TAK":
        print("Przerwano. Zmiany nie zostaly wdrozone.")
        append_history(
            client_config.domain,
            {
                "task": TASK_NAME,
                "status": "odrzucono wdrozenie",
                "campaign": "",
                "summary": {
                    "conversion_actions": len(plan.conversion_actions),
                    "findings": len(plan.findings),
                    "changes": len(plan.changes),
                },
            },
        )
        if show_navigation:
            print_next_navigation(client_config.domain)
        return

    apply_conversion_tracking_plan(client_config, plan, show_navigation=show_navigation)
