import json

import frappe


def execute():
	"""Inject the new "Tax Articles" column into saved Sales Invoice Item grid layouts.

	Per-user grid column layouts live in `__UserSettings` (GridView). A layout saved
	before the multi tax-article feature lists the legacy `tax_article` column but not
	the new `custom_tax_articles_display`. Frappe renders that saved list verbatim and
	ignores the new in_list_view field, so the "Tax Articles" cell never appears for
	those users until they add it manually via the grid gear.

	Add `custom_tax_articles_display` to every saved layout that doesn't already have
	it, positioned near the tax fields. This is purely additive: the legacy
	`tax_article` column (if present) is left untouched. Idempotent.
	"""
	rows = frappe.db.sql(
		"select user, data from `__UserSettings` where doctype = 'Sales Invoice'",
		as_dict=True,
	)
	for r in rows:
		try:
			data = json.loads(r.data or "{}")
		except (ValueError, TypeError):
			continue

		grid_view = data.get("GridView") or {}
		cols = grid_view.get("Sales Invoice Item")
		if not cols:
			continue

		names = [c.get("fieldname") for c in cols]
		if "custom_tax_articles_display" in names:
			continue

		new_col = {"fieldname": "custom_tax_articles_display", "columns": 2}
		if "item_tax_template" in names:
			cols.insert(names.index("item_tax_template") + 1, new_col)
		elif "tax_article" in names:
			cols.insert(names.index("tax_article") + 1, new_col)
		else:
			cols.append(new_col)

		grid_view["Sales Invoice Item"] = cols
		data["GridView"] = grid_view
		frappe.db.sql(
			"update `__UserSettings` set data = %s where user = %s and doctype = 'Sales Invoice'",
			(json.dumps(data), r.user),
		)

	frappe.db.commit()
	frappe.cache().delete_value("_user_settings")
