import frappe


def get_system_asset_categories():
    """
    Возвращает список системных категорий активов
    """
    return [
        "Binalar, tikililər və qurğular",
        "Maşınlar və avadanlıqlar",
        "Yüksək texnologiyalar məhsulu olan hesablama texnikası",
        "Nəqliyyat vasitələri",
        "Digər əsas vəsaitlər",
        "Düzən torpaqlar",
        "Dağ torpaqlar",
        "Orta və yüksək dağ torpaqlar",
        "Şəhərin mövcud hüdudundan kənarda olan kənd təsərrüfatı təyinatlı torpaqlar",
        "Sənaye, tikinti, nəqliyyat, rabitə, ticarət-məişət xidməti və digər xüsusi təyinatlı torpaq sahələri"
    ]


def create_asset_categories():
    """
    УСТАРЕЛО: Функция оставлена для обратной совместимости.
    Новые установки используют хук setup_wizard_complete.

    Создает категории активов для первой компании в системе.
    """
    # Проверка существования таблицы Company
    if not frappe.db.table_exists("Company"):
        frappe.log_error("Company table not found", "Asset Categories Patch")
        return

    # Получаем первую компанию
    company = frappe.get_all("Company", limit=1)
    if not company:
        frappe.log_error("No company found in the system", "Asset Categories Patch")
        return

    company_name = company[0].name

    # Используем новую функцию
    _create_categories_for_company(company_name)


def get_account_by_name(account_name, company):
    """Get account by account_name field"""
    account = frappe.db.get_value(
        "Account",
        {
            "account_name": account_name,
            "company": company
        },
        "name"
    )

    if not account:
        raise ValueError(f"Account not found: {account_name} for company {company}")

    return account


def create_asset_categories_on_company_update(doc, method):
    """
    Автоматически создает категории активов при создании компании.
    Вызывается через doc_events на Company.on_update.

    Это стандартный паттерн ERPNext (как создаются Warehouses, Departments, Cost Centers).

    Args:
        doc: Company document
        method: "on_update"
    """
    company_name = doc.name

    # Идемпотентность: проверяем, есть ли уже системные категории
    system_categories = get_system_asset_categories()

    # Проверяем первую категорию из списка
    if frappe.db.exists("Asset Category", {"asset_category_name": system_categories[0]}):
        # Категории уже созданы (они создаются для всех компаний сразу)
        frappe.log_error(
            f"Asset categories already exist, skipping creation\nCompany: {company_name}\nFirst category found: {system_categories[0]}",
            "AC Skip Existing"
        )
        return

    # Логируем начало создания
    frappe.log_error(
        f"Creating asset categories automatically\nTriggered by: Company.on_update\nCompany: {company_name}",
        "AC Auto Create"
    )

    try:
        # Создаем категории
        _create_categories_for_company(company_name)

        frappe.log_error(
            f"Asset categories created successfully\nCompany: {company_name}\nCategories: {len(system_categories)}",
            "AC Created"
        )
    except Exception as e:
        import traceback
        frappe.log_error(
            f"Failed to create asset categories\nCompany: {company_name}\nError: {str(e)}\n\nTraceback:\n{traceback.format_exc()}",
            "AC Create Failed"
        )
        # Не пробрасываем исключение - не блокируем создание компании


def create_asset_categories_for_company(company_name):
    """
    Создает категории активов для конкретной компании.
    Вызывается как фоновая задача после setup wizard.

    Args:
        company_name: Название компании
    """
    frappe.log_error(
        f"Function started\nCompany: {company_name}",
        "AC Create Start"
    )

    try:
        # Проверяем, что компания существует
        company_exists = frappe.db.exists("Company", company_name)

        if not company_exists:
            frappe.log_error(
                f"Company not found in database\nSearched for: {company_name}",
                "AC Company ERROR"
            )
            return

        frappe.log_error(
            f"Company exists in database\nCompany: {company_name}",
            "AC Company OK"
        )

        # Проверка идемпотентности: если категории уже есть, не создаем
        system_categories = get_system_asset_categories()
        existing_categories = frappe.db.count(
            "Asset Category",
            filters={"asset_category_name": ["in", system_categories]}
        )

        frappe.log_error(
            f"Idempotency check\nSystem categories: {len(system_categories)}\nExisting categories: {existing_categories}\nCategories list: {system_categories}",
            "AC Check Existing"
        )

        if existing_categories > 0:
            frappe.log_error(
                f"Categories already exist, skipping creation\nFound: {existing_categories} of {len(system_categories)}",
                "AC Already Exist"
            )
            return

        # Создаем категории
        frappe.log_error(
            f"Starting category creation\nCompany: {company_name}\nCategories to create: {len(system_categories)}",
            "AC Creating"
        )
        _create_categories_for_company(company_name)

        frappe.log_error(
            f"Asset categories creation completed successfully\nCompany: {company_name}",
            "AC Complete"
        )

    except Exception as e:
        # Не пробрасываем исключение - это фоновая задача
        import traceback
        frappe.log_error(
            f"Failed to create asset categories\nCompany: {company_name}\nError: {str(e)}\n\nFull traceback:\n{traceback.format_exc()}",
            "AC Create ERROR"
        )


def _create_categories_for_company(company_name):
    """
    Внутренняя функция для создания категорий активов.
    Извлечена из create_asset_categories для переиспользования.
    """
    asset_categories = get_system_asset_categories()

    # Находим нужные счета
    frappe.log_error(
        f"Searching for required accounts\nCompany: {company_name}\nAccounts needed: 3",
        "AC Search Accounts"
    )

    try:
        accumulated_depreciation = get_account_by_name(
            "Tikililər üzrə yığılmış amortizasiya",
            company_name
        )
        depreciation_expense = get_account_by_name(
            "Amortizasiya xərci",
            company_name
        )
        fixed_asset = get_account_by_name(
            "Digər uzunmüddətli aktivlər",
            company_name
        )

        frappe.log_error(
            f"All required accounts found\nCompany: {company_name}\n\nAccounts:\n1. Accumulated Depreciation: {accumulated_depreciation}\n2. Depreciation Expense: {depreciation_expense}\n3. Fixed Asset: {fixed_asset}",
            "AC Accounts OK"
        )

    except Exception as e:
        import traceback
        frappe.log_error(
            f"Required accounts not found\nCompany: {company_name}\nError: {str(e)}\n\nRequired accounts:\n- Tikililər üzrə yığılmış amortizasiya\n- Amortizasiya xərci\n- Digər uzunmüddətli aktivlər\n\nFull traceback:\n{traceback.format_exc()}",
            "AC Accounts ERROR"
        )
        return

    # Создаем категории
    created_count = 0
    skipped_count = 0
    errors = []

    for idx, category_name in enumerate(asset_categories, 1):
        try:
            if not frappe.db.exists("Asset Category", category_name):
                asset_category = frappe.new_doc("Asset Category")
                asset_category.asset_category_name = category_name
                asset_category.enable_cwip_accounting = 0

                asset_category.append("accounts", {
                    "company_name": company_name,
                    "fixed_asset_account": fixed_asset,
                    "accumulated_depreciation_account": accumulated_depreciation,
                    "depreciation_expense_account": depreciation_expense,
                    "capital_work_in_progress_account": ""
                })

                asset_category.insert(ignore_permissions=True)
                created_count += 1
            else:
                skipped_count += 1
        except Exception as e:
            import traceback
            error_msg = f"Category: {category_name}\nError: {str(e)}"
            errors.append(error_msg)
            frappe.log_error(
                f"Failed to create category\n{error_msg}\n\nFull traceback:\n{traceback.format_exc()}",
                f"AC Cat ERROR {idx}"
            )

    frappe.db.commit()

    # Финальный отчет
    status = "SUCCESS" if created_count > 0 else ("SKIP" if skipped_count > 0 else "ERROR")
    frappe.log_error(
        f"Category creation finished\nCompany: {company_name}\nCreated: {created_count}\nSkipped: {skipped_count}\nErrors: {len(errors)}\n\nError details:\n{chr(10).join(errors) if errors else 'No errors'}",
        f"AC {status}"
    )


def prevent_delete_system_asset_categories(doc, method):
    """
    Запрещает удаление системных категорий активов
    """
    system_categories = get_system_asset_categories()

    if doc.asset_category_name in system_categories:
        frappe.throw(
            f"Cannot delete system asset category: {doc.asset_category_name}",
            frappe.PermissionError
        )


def prevent_create_new_asset_categories(doc, method):
    """
    Запрещает создание новых категорий активов.
    Разрешены только системные категории, созданные через hooks.
    """
    system_categories = get_system_asset_categories()

    # Проверяем, создается ли новая запись
    if doc.is_new():
        # Если это не системная категория, запрещаем создание
        if doc.asset_category_name not in system_categories:
            frappe.throw(
                "Cannot create new asset categories. Only predefined system categories are allowed.",
                frappe.PermissionError
            )
