--ProfessionGuides_UI.lua
local PT = AhUI
if not PT then return end

local G  = PT.ProfessionGuides
local UI = {}
local Shopping = PT.ProfessionGuides_Shopping
local Waypoints = PT.ProfessionGuides_Waypoints
local State = PT.ProfessionGuides_State
local FONT = "Interface\\AddOns\\AhUI\\fonts\\GothamXNarrow-Medium.ttf"
local INFO_ATLAS = "help-i"
local FRAME_PADDING_TOP    = 16
local FRAME_PADDING_BOTTOM = 16
local FRAME_MIN_HEIGHT     = 200
local Tooltip = PT.Tooltip
local Epochs = PT.ProfessionGuides_Epochs or {}
local lastOpenedSkillLine = nil

local function CraftRecipe(spellID, count)
    if not C_TradeSkillUI
       or not C_TradeSkillUI.OpenTradeSkill
       or not C_TradeSkillUI.CraftRecipe
    then
        print("AhUI: Craft API недоступен")
        return
    end

    if not spellID then
        print("AhUI: нет рецепта для крафта")
        return
    end

    local skillLineID = G:GetSelectedSkillLine()
    if skillLineID then
        C_TradeSkillUI.OpenTradeSkill(skillLineID)
    end

    C_TradeSkillUI.CraftRecipe(spellID, count or 1)
end

local function UpdateBuyButtonVisibility()
    if not UI.frame or not UI.frame.buyBtn then return end

    local skillLineID = G:GetSelectedSkillLine()
    local step = skillLineID and G:GetCurrentStepBySkillLine(skillLineID)

    UI.frame.buyBtn:SetShown(
        Shopping:CanBuy(skillLineID)
        and not (step and step.disablesShopping)
    )
end

local function OpenProfessionLikeConcentration(parentProfessionID)
    if not parentProfessionID then return end

    local p1, p2 = GetProfessions()

    for _, slot in ipairs({ p1, p2 }) do
        if slot then
            local name, icon, _, _, _, _, skillLine =
                GetProfessionInfo(slot)

            if skillLine == parentProfessionID then
                if ProfessionsFrame and ProfessionsFrame:IsShown()
                   and lastOpenedSkillLine == skillLine
                then
                    HideUIPanel(ProfessionsFrame)
                    lastOpenedSkillLine = nil
                    return
                end

                if ProfessionsFrame then
                    ShowUIPanel(ProfessionsFrame)
                end

                if C_TradeSkillUI and C_TradeSkillUI.OpenTradeSkill then
                    C_TradeSkillUI.OpenTradeSkill(skillLine)
                    lastOpenedSkillLine = skillLine
                end

                return
            end
        end
    end
end


local function CreateIconBorder(iconHolder)
    local holder = CreateFrame("Frame", nil, iconHolder, "BackdropTemplate")
    holder:SetFrameLevel(iconHolder:GetFrameLevel() + 10)

    holder:SetPoint("TOPLEFT", iconHolder, "TOPLEFT", -2, 2)
    holder:SetPoint("BOTTOMRIGHT", iconHolder, "BOTTOMRIGHT", 2, -2)

    holder:SetBackdrop({
        edgeFile = "Interface\\Buttons\\WHITE8x8",
        edgeSize = 2,
    })

    holder:SetBackdropBorderColor(0, 0, 0, 1)
    iconHolder.border = holder
end

local function CreateButtonBorder(button)
    local border = CreateFrame("Frame", nil, button, "BackdropTemplate")
    border:SetPoint("TOPLEFT", -1, 1)
    border:SetPoint("BOTTOMRIGHT", 1, -1)
    border:SetFrameLevel(button:GetFrameLevel() - 1)

    border:SetBackdrop({
        edgeFile = "Interface\\Buttons\\WHITE8x8",
        edgeSize = 1,
    })

    border:SetBackdropBorderColor(1, 1, 1, 0.15)
    button.border = border
end

-- =====================================================
-- Create UI
-- =====================================================

function UI:Create()
    if self.frame then return self.frame end

    local f = CreateFrame("Frame", "AhUIProfessionGuide", UIParent, "BackdropTemplate")
    f:SetSize(500, 210)
	f:ClearAllPoints()
	f:SetPoint("TOPLEFT", UIParent, "TOPLEFT", 400, -200)
	f:SetWidth(500)
    f:SetBackdrop({
        bgFile   = "Interface\\Buttons\\WHITE8x8",
        edgeFile = "Interface\\Buttons\\WHITE8x8",
        edgeSize = 1,
    })
    f:SetBackdropColor(0, 0, 0, 0.92)
    f:SetBackdropBorderColor(1, 1, 1, 1)

    table.insert(UISpecialFrames, f:GetName())

    f:SetMovable(true)
    f:EnableMouse(true)
    f:RegisterForDrag("LeftButton")
    f:SetScript("OnDragStart", f.StartMoving)
    f:SetScript("OnDragStop", function(self)
		self:StopMovingOrSizing()

		-- принудительно фиксируем TOP якорь
		local left, top = self:GetLeft(), self:GetTop()

		self:ClearAllPoints()
		self:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", left, top)
		self:SetWidth(self:GetWidth())
	end)

    -- Title
    f.title = f:CreateFontString(nil, "OVERLAY")
    f.title:SetFont(FONT, 14, "OUTLINE")
    f.title:SetPoint("TOPLEFT", 14, -12)
    f.title:SetText("Profession Guide")
	-- Profession icon holder (AhUI style)
	f.profIconHolder = CreateFrame("Frame", nil, f, "BackdropTemplate")
	f.profIconHolder:SetSize(26, 26)
	f.profIconHolder:SetPoint("LEFT", f.title, "RIGHT", 8, 0)
	f.profIconHolder:SetFrameLevel(f:GetFrameLevel() + 5)

	f.profIcon = f.profIconHolder:CreateTexture(nil, "ARTWORK", nil, 5)
	f.profIcon:SetAllPoints()

	CreateIconBorder(f.profIconHolder)

	f.profIconHolder:Hide()

	f.profIconHolder:SetScript("OnEnter", function()
		GameTooltip:SetOwner(f.profIconHolder, "ANCHOR_RIGHT")
		GameTooltip:AddLine("Открыть профессию", 1, 1, 1)
		GameTooltip:Show()
	end)
	-- текст-подсказка справа от иконки профессии
	f.profHint = f:CreateFontString(nil, "OVERLAY")
	f.profHint:SetFont(FONT, 11)
	f.profHint:SetPoint("LEFT", f.profIconHolder, "RIGHT", 6, 0)
	f.profHint:SetText("|cffaaaaaa<< открыть профессию|r")
	f.profHint:Hide()

	f.profIconHolder:SetScript("OnLeave", function()
		GameTooltip:Hide()
	end)

	f.profIconHolder:SetScript("OnMouseDown", function(_, button)
		if button == "LeftButton" then
			f.profIcon:SetPoint("CENTER", 1, -1)

			local skillLineID = G:GetSelectedSkillLine()
			if skillLineID then
				local info =
					C_TradeSkillUI.GetProfessionInfoBySkillLineID(skillLineID)

				if info and info.parentProfessionID then
					OpenProfessionLikeConcentration(info.parentProfessionID)
				end

			end
		end
	end)

	f.profIconHolder:SetScript("OnMouseUp", function(_, button)
		if button == "LeftButton" then
			f.profIcon:SetPoint("CENTER", 0, 0)
		end
	end)

    -- Close
    f.close = CreateFrame("Button", nil, f)
    f.close:SetSize(16, 16)
    f.close:SetPoint("TOPRIGHT", -10, -10)

    local c = f.close:CreateFontString(nil, "OVERLAY")
    c:SetFont(FONT, 25)
    c:SetPoint("CENTER")
    c:SetText("×")
    c:SetTextColor(0.7, 0.7, 0.7)

    f.close:SetScript("OnEnter", function() c:SetTextColor(1, 0.4, 0.4) end)
    f.close:SetScript("OnLeave", function() c:SetTextColor(0.7, 0.7, 0.7) end)
    f.close:SetScript("OnClick", function() f:Hide() end)
	-- Info button (под крестиком)
	f.infoBtn = CreateFrame("Button", nil, f)
	f.infoBtn:SetSize(14, 14)
	f.infoBtn:SetPoint("TOPRIGHT", f.close, "BOTTOMRIGHT", 0, -4)
	f.infoBtn:SetFrameLevel(f.close:GetFrameLevel() + 5)
	f.infoBtn.icon = f.infoBtn:CreateTexture(nil, "OVERLAY")
	f.infoBtn.icon:SetSize(25, 25)
	f.infoBtn.icon:SetPoint("CENTER")
	f.infoBtn.icon:SetDrawLayer("OVERLAY", 7)
	f.infoBtn.icon:SetTexture("Interface\\COMMON\\help-i")
	f.infoBtn.icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
	f.infoBtn.icon:SetAlpha(0.85)
	f.infoBtn:SetScript("OnEnter", function(self)
	    if self.icon then
			self.icon:SetAlpha(1)
		end
		if not Tooltip then return end
		Tooltip:Clear()
		Tooltip:AddLine("Profession Guide", 14, 1, 1, 1)
		Tooltip:AddLine(" ")
		Tooltip:AddLine("• Выберите эпоху профессии")
		Tooltip:AddLine("• Откройте аукцион — появится кнопка покупки")
		Tooltip:AddLine("• Откройте профессию — появятся кнопки создания предметов")
		Tooltip:AddLine("• Используйте кнопки «Предыдущий / Следующий»")
		Tooltip:AddLine("     для просмотра шагов руководства", 12, 0.85, 0.85, 0.85)
		Tooltip:AddLine("• «Создать» — крафт 1 предмета")
		Tooltip:AddLine("• «Создать всё» — крафт максимума")
		Tooltip:AddLine("• ЛКМ по имени учителя - метка на карте ")
		Tooltip:AddLine("     не забывайте изучать новые рецепты", 12, 0.85, 0.85, 0.85)
		Tooltip:ShowAt(self, "BOTTOMRIGHT", "TOPRIGHT", 0, 6)
	end)
	f.infoBtn:SetScript("OnLeave", function(self)
	    if self.icon then
			self.icon:SetAlpha(0.85)
		end
		if Tooltip then
			Tooltip:Clear()
		end
	end)

	-- Profession select button
	f.profBtn = CreateFrame("Button", nil, f)
	f.profBtn:SetFrameLevel(f:GetFrameLevel() + 20)
	f.profBtn:SetSize(160, 22)
	f.profBtn:SetPoint("TOPRIGHT", -40, -12)

	local bgp = f.profBtn:CreateTexture(nil, "BACKGROUND")
	bgp:SetAllPoints()
	bgp:SetColorTexture(1, 1, 1, 0.08)

	f.profBtn.text = f.profBtn:CreateFontString(nil, "OVERLAY")
	f.profBtn.text:SetFont(FONT, 12)
	f.profBtn.text:SetPoint("CENTER")
	f.profBtn.text:SetText("Выбрать профессию")

    -- Epoch button
    f.epochBtn = CreateFrame("Button", nil, f)
	f.epochBtn:SetFrameLevel(f:GetFrameLevel() + 20)
    f.epochBtn:SetSize(160, 22)
    f.epochBtn:SetPoint("TOPRIGHT", -40, -40)

    local bg = f.epochBtn:CreateTexture(nil, "BACKGROUND")
    bg:SetAllPoints()
    bg:SetColorTexture(1, 1, 1, 0.08)

    f.epochBtn.text = f.epochBtn:CreateFontString(nil, "OVERLAY")
    f.epochBtn.text:SetFont(FONT, 12)
    f.epochBtn.text:SetPoint("CENTER")
    f.epochBtn.text:SetText("Выбрать эпоху")
	f.buyBtn = CreateFrame("Button", nil, f)
	f.buyBtn:SetFrameLevel(f:GetFrameLevel() + 20)
	f.buyBtn:SetSize(160, 22)
	f.buyBtn:SetPoint("TOPRIGHT", -40, -68)
	f.buyBtn:Hide()

	local bg = f.buyBtn:CreateTexture(nil, "BACKGROUND")
	bg:SetAllPoints()
	bg:SetColorTexture(1, 1, 1, 0.08)

	f.buyBtn.text = f.buyBtn:CreateFontString(nil, "OVERLAY")
	f.buyBtn.text:SetFont(FONT, 12)
	f.buyBtn.text:SetPoint("CENTER")
	f.buyBtn.text:SetText("Создать список покупок")
	f.buyBtn:SetScript("OnClick", function()
		local skillLineID = G:GetSelectedSkillLine()
		if not skillLineID then return end

		local mats = G:BuildShoppingList(skillLineID)
		if not mats or not next(mats) then
			print("AhUI: нечего покупать")
			return
		end

		local S = PT.ProfessionGuides_Shopping
		if not S or not S:IsAvailable() then
			print("AhUI: Auctionator недоступен")
			return
		end

		local ok, reason = S:CreateShoppingListAndOpen(mats)
		if not ok then
			print("AhUI: ошибка аукциона:", reason)
		end

	end)
	f.buyBtn:SetScript("OnEnter", function(self)
		if not Tooltip then return end

		Tooltip:Clear()
		Tooltip:AddLine("Создать список покупок", 14, 1, 1, 1)
		Tooltip:AddLine(" ")
		Tooltip:AddLine("Создаёт Shopping List в Auctionator.", 12, 0.9, 0.9, 0.9)
		Tooltip:AddLine("Откройте вкладку «Покупка» для работы со списком.", 12, 0.9, 0.9, 0.9)
		Tooltip:ShowAt(self, "TOP", "BOTTOM", 0, -6)
	end)

	f.buyBtn:SetScript("OnLeave", function()
		if Tooltip then
			Tooltip:Clear()
		end
	end)

	-- Step navigation buttons
	
	f.nextStepBtn = CreateFrame("Button", nil, f)
	f.nextStepBtn:SetFrameLevel(f:GetFrameLevel() + 20)
	f.nextStepBtn:SetSize(100, 20)
	f.nextStepBtn:SetPoint("TOPRIGHT", -40, -96)
	f.nextStepBtn:Hide()

	local bgNext = f.nextStepBtn:CreateTexture(nil, "BACKGROUND")
	bgNext:SetAllPoints()
	bgNext:SetColorTexture(1, 1, 1, 0.06)

	f.nextStepBtn.text = f.nextStepBtn:CreateFontString(nil, "OVERLAY")
	f.nextStepBtn.text:SetFont(FONT, 11)
	f.nextStepBtn.text:SetPoint("CENTER")
	f.nextStepBtn.text:SetText("Следующий >")

	f.prevStepBtn = CreateFrame("Button", nil, f)
	f.prevStepBtn:SetFrameLevel(f:GetFrameLevel() + 20)
	f.prevStepBtn:SetSize(100, 20)
	f.prevStepBtn:SetPoint("TOPLEFT", f.nextStepBtn, "BOTTOMLEFT", -60, -6)
	f.prevStepBtn:Hide()

	local bgPrev = f.prevStepBtn:CreateTexture(nil, "BACKGROUND")
	bgPrev:SetAllPoints()
	bgPrev:SetColorTexture(1, 1, 1, 0.06)

	f.prevStepBtn.text = f.prevStepBtn:CreateFontString(nil, "OVERLAY")
	f.prevStepBtn.text:SetFont(FONT, 11)
	f.prevStepBtn.text:SetPoint("CENTER")
	f.prevStepBtn.text:SetText("< Предыдущий")

	f.prevStepBtn:SetScript("OnClick", function()
		G:StepPrev()
		State:Save()
		UI:Refresh()
	end)

	f.nextStepBtn:SetScript("OnClick", function()
		G:StepNext()
		State:Save()
		UI:Refresh()
	end)

	-- Step indicator
	f.stepIndicator = f:CreateFontString(nil, "OVERLAY")
	f.stepIndicator:SetFont(FONT, 11)
	f.stepIndicator:SetPoint("LEFT", f.prevStepBtn, "RIGHT", 8, 0)
	f.stepIndicator:SetText("")
	f.stepIndicator:Hide()
	-- Back to current step button
	f.resetStepBtn = CreateFrame("Button", nil, f)
	f.resetStepBtn:SetFrameLevel(f:GetFrameLevel() + 20)
	f.resetStepBtn:SetSize(160, 20)
	f.resetStepBtn:SetPoint("TOPRIGHT", -40, -148)
	f.resetStepBtn:Hide()

	local bgReset = f.resetStepBtn:CreateTexture(nil, "BACKGROUND")
	bgReset:SetAllPoints()
	bgReset:SetColorTexture(1, 1, 1, 0.06)

	f.resetStepBtn.text = f.resetStepBtn:CreateFontString(nil, "OVERLAY")
	f.resetStepBtn.text:SetFont(FONT, 11)
	f.resetStepBtn.text:SetPoint("CENTER")
	f.resetStepBtn.text:SetText("К текущему шагу")
	f.resetStepBtn:SetScript("OnClick", function()
		G:ResetManualStep()
		State:Save()
		UI:Refresh()
	end)
	-- =========================
	-- CONTENT CONTAINER
	-- =========================
	f.content = CreateFrame("Frame", nil, f)
	f.content:SetPoint("TOPLEFT", f.title, "BOTTOMLEFT", 0, -16)
	f.content:SetPoint("TOPRIGHT", f, "TOPRIGHT", -16, -48)
	f.content:SetFrameLevel(f:GetFrameLevel() + 1)
	f.content:SetHeight(1)
	f.content:SetHeight(1)
	f.textLines = {}
	-- Trainers header + buttons (create once)
	f.trainersHeader = f.content:CreateFontString(nil, "OVERLAY")
	f.trainersHeader:SetFont(FONT, 12)
	f.trainersHeader:SetText("Учителя:")
	f.trainersHeader:Hide()

	f.trainerButtons = f.trainerButtons or {}

	f.footer = CreateFrame("Frame", nil, f)
	f.footer:SetPoint("TOPLEFT", f.content, "BOTTOMLEFT", 0, 6)
	f.footer:SetPoint("TOPRIGHT", f.content, "BOTTOMRIGHT", 0, 6)
	f.footer:SetHeight(48)

-- Craft buttons

	f.craftAllBtn = CreateFrame("Button", nil, f)
	f.craftAllBtn:SetSize(90, 20)
	f.craftAllBtn:Hide()
	f.craftAllBtn:SetPoint("TOPRIGHT", f.footer, "TOPRIGHT", -24, 0)

	local bg2 = f.craftAllBtn:CreateTexture(nil, "BACKGROUND")
	bg2:SetAllPoints()
	bg2:SetColorTexture(1, 1, 1, 0.06)

	f.craftAllBtn.text = f.craftAllBtn:CreateFontString(nil, "OVERLAY")
	f.craftAllBtn.text:SetFont(FONT, 12)
	f.craftAllBtn.text:SetPoint("CENTER")
	f.craftAllBtn.text:SetText("Создать всё")
	f.craftBtn = CreateFrame("Button", nil, f)
	f.craftBtn:SetSize(90, 20)
	f.craftBtn:Hide()
	-- якорь: правый нижний угол окна
	f.craftBtn:SetPoint("BOTTOMRIGHT", f.craftAllBtn, "TOPRIGHT", 0, 6)

	local bg1 = f.craftBtn:CreateTexture(nil, "BACKGROUND")
	bg1:SetAllPoints()
	bg1:SetColorTexture(1, 1, 1, 0.08)

	f.craftBtn.text = f.craftBtn:CreateFontString(nil, "OVERLAY")
	f.craftBtn.text:SetFont(FONT, 12)
	f.craftBtn.text:SetPoint("CENTER")
	f.craftBtn.text:SetText("Создать")
	f.craftBtn:SetScript("OnClick", function()
		local skillLineID = G:GetSelectedSkillLine()
		if not skillLineID then return end

		local step = G:GetCurrentStepBySkillLine(skillLineID)
		if not step or not step.recipes or not step.recipes[1] then
			print("AhUI: нет рецепта для крафта")
			return
		end

		local recipe = step.recipes[1]
		CraftRecipe(recipe.spellID, 1)
	end)

	f.craftAllBtn:SetScript("OnClick", function()
		local skillLineID = G:GetSelectedSkillLine()
		if not skillLineID then return end

		local step, realSkill = G:GetCurrentStepBySkillLine(skillLineID)
		if not step or not step.recipes or not step.recipes[1] then
			print("AhUI: нет рецепта для крафта")
			return
		end

		local recipe = step.recipes[1]

		local eff, real = G:GetEffectiveSkillLevel(skillLineID)

		local needBySkill =
			(recipe.crafts and recipe.crafts > 0)
			and recipe.crafts
			or G:GetRemainingCraftsForStep(step, eff, real)

		if needBySkill <= 0 then
			print("AhUI: шаг уже завершён")
			return
		end

		-- сколько позволяют материалы
		local byMaterials = G:GetMaxCraftsByMaterials(recipe)
		if byMaterials <= 0 then
			print("AhUI: недостаточно материалов")
			return
		end

		local craftCount = math.min(needBySkill, byMaterials)
		if craftCount <= 0 then return end

		CraftRecipe(recipe.spellID, craftCount)
	end)
	
    f:Hide()
    self.frame = f
	State:Restore()

	if State.materialsExpanded == nil then
		State.materialsExpanded = false
	end

    UI:Refresh()

    return f
end

-- =====================================================
-- Epoch menu
-- =====================================================
local function ShowProfessionMenu(btn)
    if not Epochs.professionsOrder then return end

    if btn.menu then btn.menu:Hide() end

    local m = CreateFrame("Frame", nil, btn, "BackdropTemplate")
    m:SetPoint("TOPRIGHT", btn, "BOTTOMRIGHT", 0, -2)

    local itemHeight = 18
    m:SetSize(160, #Epochs.professionsOrder * itemHeight + 12)

    m:SetBackdrop({
        bgFile   = "Interface\\Buttons\\WHITE8x8",
        edgeFile = "Interface\\Buttons\\WHITE8x8",
        edgeSize = 1,
    })
    m:SetBackdropColor(0, 0, 0, 0.95)
    m:SetBackdropBorderColor(1, 1, 1, 0.15)

    local y = -6
    for _, prof in ipairs(Epochs.professionsOrder) do
        local b = CreateFrame("Button", nil, m)
        b:SetPoint("TOPLEFT", 8, y)
        b:SetSize(144, itemHeight)

        local fs = b:CreateFontString(nil, "OVERLAY")
        fs:SetFont(FONT, 12)
        fs:SetPoint("LEFT")
        fs:SetText(prof)

        b:SetScript("OnClick", function()
            G:SetProfession(prof)
            State:Save()

            btn.text:SetText(prof)
            m:Hide()

            -- сбрасываем эпоху
            if UI.frame and UI.frame.epochBtn then
                UI.frame.epochBtn.text:SetText("Выбрать эпоху")
            end

            UI:Refresh()
        end)

        y = y - itemHeight
    end

    btn.menu = m
end

local function ShowEpochMenu(btn)
    local prof = G:GetSelectedProfession()
    if not prof then
        print("AhUI: выберите профессию")
        return
    end

    local profEpochs = Epochs[prof]
    if not profEpochs then
        print("AhUI: no epochs for profession", prof)
        return
    end

    local order = profEpochs.order
    local data  = profEpochs.data

    if btn.menu then btn.menu:Hide() end

    local m = CreateFrame("Frame", nil, btn, "BackdropTemplate")
    m:SetPoint("TOPRIGHT", btn, "BOTTOMRIGHT", 0, -2)

    local itemHeight = 18
    m:SetSize(160, #order * itemHeight + 12)

    m:SetBackdrop({
        bgFile   = "Interface\\Buttons\\WHITE8x8",
        edgeFile = "Interface\\Buttons\\WHITE8x8",
        edgeSize = 1,
    })
    m:SetBackdropColor(0, 0, 0, 0.95)
    m:SetBackdropBorderColor(1, 1, 1, 0.15)

    local y = -6
    for _, epochSkillLineID in ipairs(order) do
        local info = data[epochSkillLineID]
        if info then
            local b = CreateFrame("Button", nil, m)
            b:SetPoint("TOPLEFT", 8, y)
            b:SetSize(144, itemHeight)

            local fs = b:CreateFontString(nil, "OVERLAY")
            fs:SetFont(FONT, 12)
            fs:SetPoint("LEFT")
            fs:SetText(info.name)

            b:SetScript("OnClick", function()
                G:SetSkillLine(epochSkillLineID)
                State:Save()

                btn.text:SetText(info.name)
                m:Hide()

                UpdateBuyButtonVisibility()
                UI:Refresh()
            end)

            y = y - itemHeight
        end
    end

    btn.menu = m
end

local function GetTextLine(f, index)
    local line = f.textLines[index]

    if not line then
        line = CreateFrame("Button", nil, f.content)
        line:SetHeight(16)
        line:SetWidth(380)
        line:EnableMouse(true)

        line.text = line:CreateFontString(nil, "OVERLAY")
        line.text:SetFont(FONT, 12)
        line.text:SetPoint("LEFT", 0, 0)
        line.text:SetJustifyH("LEFT")

        line:SetScript("OnEnter", function(self)
            if self.itemID then
                GameTooltip:SetOwner(self, "ANCHOR_CURSOR")
                GameTooltip:SetItemByID(self.itemID)
                GameTooltip:Show()
            end
        end)

        line:SetScript("OnLeave", function()
            GameTooltip:Hide()
        end)

        line:SetScript("OnClick", function(self)
            if self.itemLink then
                ChatEdit_InsertLink(self.itemLink)
            end
        end)

        f.textLines[index] = line
    end

    return line
end

local function BuildNoteRefs(step)
    if not step or not step.noteRefs then return nil end

    local out = {}

    for _, ref in ipairs(step.noteRefs) do
        if ref.type == "spell" and ref.spellID then
            local name

            if C_Spell and C_Spell.GetSpellInfo then
                local info = C_Spell.GetSpellInfo(ref.spellID)
                name = info and info.name
            elseif GetSpellInfo then
                name = GetSpellInfo(ref.spellID)
            end

            table.insert(out, "• " .. (name or ("spell:" .. ref.spellID)))

        elseif ref.type == "item" and ref.itemID then
            local name = GetItemInfo(ref.itemID)
            table.insert(out, "• " .. (name or ("item:" .. ref.itemID)))
        end
    end

    if #out == 0 then return nil end
    return out
end

local function GetFirstLearnedRecipe(step)
	if not step or not step.recipes then return nil end

	for _, r in ipairs(step.recipes) do
		if r.spellID and G:IsRecipeLearned(r.spellID) then
			return r
		end
	end

	return nil
end

-- =====================================================
-- Refresh
-- =====================================================

function UI:Refresh()
    local f = self.frame
    local skillLineID = G:GetSelectedSkillLine()

-- =========================
-- CLEAR OLD LINES + ADDLINE
-- =========================
for _, l in ipairs(f.textLines) do
    l:Hide()
    if l.icon then l.icon:Hide() end
end

local ctx = { y = 0, i = 1 }

local function AddLine(text, color)
    local line = GetTextLine(f, ctx.i)
	    -- === RESET LINE STATE ===
    if line.icon then
        line.icon:Hide()
    end

    line:SetHeight(16)
    line:SetWidth(380)

    line.text:ClearAllPoints()
    line.text:SetPoint("LEFT", 0, 0)
    line.text:SetWidth(380)
    line.text:SetWordWrap(false)

    line:ClearAllPoints()
    line:SetPoint("TOPLEFT", f.content, "TOPLEFT", 0, -ctx.y)
    line.text:SetText((color or "") .. text .. "|r")
    line.itemID = nil
    line.itemLink = nil
    line:Show()

    ctx.y = ctx.y + 16
    ctx.i = ctx.i + 1
end
ctx.y = ctx.y + 6

-- =========================
-- PROFESSION ICON
-- =========================
f.profIconHolder:Hide()
if f.profHint then f.profHint:Hide() end

if skillLineID and G.GetProfessionIcon then
    local icon = G:GetProfessionIcon(skillLineID)
    if icon then
        f.profIcon:SetTexture(icon)
        f.profIconHolder:Show()
        if f.profHint then f.profHint:Show() end
    end
end

    -- =========================
    -- NO SELECTION
    -- =========================
	if not skillLineID then
		--f.text:SetHeight(0)
		AddLine("Выберите эпоху профессии", "|cffffffaa")
		AddLine("")
		AddLine("Потом откройте окно профессии", "|cffaaaaaa")
		if f.craftBtn then f.craftBtn:Hide() end
		if f.craftAllBtn then f.craftAllBtn:Hide() end

		-- ❌ ничего не вызываем
		return
	end

    local step, skill, guide =
        G:GetCurrentStepBySkillLine(skillLineID)
	local recipeVendor =
		step and G:GetRecipeVendorForStep(skillLineID, step)

	if not guide then
		guide = G:GetGuideBySkillLine(skillLineID)
	end
	local recipe = GetFirstLearnedRecipe(step)
	local recipeLearned = recipe ~= nil

	-- =========================
	-- GUIDE COMPLETED (ВАЖНО: ДО not step)
	-- =========================
	if G:IsGuideCompleted(skillLineID) then
		AddLine("Гайд завершён!", "|cff00ff00")
		AddLine("Вы достигли максимального навыка для этой эпохи.", "|cffaaaaaa")
		AddLine("")
		AddLine("Можно перейти к следующей эпохе профессии.", "|cff66ccff")

		if f.craftBtn then f.craftBtn:Hide() end
		if f.craftAllBtn then f.craftAllBtn:Hide() end

		UpdateBuyButtonVisibility()
		return
	end

	-- =========================
	-- NO STEP (РЕАЛЬНАЯ ОШИБКА)
	-- =========================
	if not step then
		AddLine("Нет данных для выбранной эпохи", "|cffffffaa")
		AddLine("")
		AddLine("Изучите профессию у учителя:", "|cffaaaaaa")

		if f.craftBtn then f.craftBtn:Hide() end
		if f.craftAllBtn then f.craftAllBtn:Hide() end

		if guide then
			self:RenderTrainers(f, guide, ctx)
		end

		return
	end

-- Step navigation visibility + state
	if f.prevStepBtn and f.nextStepBtn and f.stepIndicator then
		local steps = G:GetStepsBySkillLine(skillLineID)
		local idx   = G:GetCurrentStepIndex(skillLineID)

		if steps and idx and steps[idx] then

			local total = #steps

			f.prevStepBtn:Show()
			f.nextStepBtn:Show()
			f.stepIndicator:Show()

			-- индикатор
			f.stepIndicator:SetText(
				string.format("Шаг %d / %d", idx, total)
			)

			-- дизейбл Prev
			if idx <= 1 then
				f.prevStepBtn:Disable()
				f.prevStepBtn.text:SetTextColor(0.5, 0.5, 0.5)
			else
				f.prevStepBtn:Enable()
				f.prevStepBtn.text:SetTextColor(1, 1, 1)
			end

			-- дизейбл Next
			if idx >= total then
				f.nextStepBtn:Disable()
				f.nextStepBtn.text:SetTextColor(0.5, 0.5, 0.5)
			else
				f.nextStepBtn:Enable()
				f.nextStepBtn.text:SetTextColor(1, 1, 1)
			end
		else
			f.prevStepBtn:Hide()
			f.nextStepBtn:Hide()
			f.stepIndicator:Hide()
		end
		-- reset button visibility
		if f.resetStepBtn then
			local autoIdx = G:GetAutoStepIndex(skillLineID)

			if G.state.manualStepIndex
			   and autoIdx
			   and autoIdx ~= G.state.manualStepIndex
			then
				f.resetStepBtn:Show()
			else
				f.resetStepBtn:Hide()
			end

		end

	end

self:RenderHeader(f, guide, skill, step, recipeLearned, AddLine, ctx)
self:RenderNote(f, step, AddLine, ctx)
self:RenderRecipes(f, step, AddLine, ctx)
self:RenderMaterials(f, step, skill, AddLine, ctx, GetTextLine)

if recipeVendor then
    self:RenderRecipeVendor(f, recipeVendor, ctx)
else
    self:RenderTrainers(f, guide, ctx)
end

local showCraftButtons = G:IsProfessionWindowOpen(skillLineID)

if f.craftBtn and f.craftAllBtn then
    if showCraftButtons and recipeLearned then

        -- 🧪 disablesCraft → скрываем "Создать"
        if step and step.disablesCraft then
            f.craftBtn:Hide()
        else
            f.craftBtn:Show()
        end

        -- 🧪 disablesCraftAll → скрываем "Создать всё"
        if step and step.disablesCraftAll then
            f.craftAllBtn:Hide()
        else
            f.craftAllBtn:Show()
        end

    else
        f.craftBtn:Hide()
        f.craftAllBtn:Hide()
    end
end

-- =========================
-- FINAL SIZE
-- =========================

local contentHeight = ctx.y
local footerHeight = 0
if f.footer and f.footer:IsShown() then
    footerHeight = f.footer:GetHeight() + 6 -- тот самый offset
end

f.content:SetHeight(contentHeight)

local totalHeight =
    FRAME_PADDING_TOP
    + contentHeight
    + footerHeight
    + FRAME_PADDING_BOTTOM
    + 32

-- фиксируем верх перед изменением размера
local left = f:GetLeft()
local top  = f:GetTop()

f:SetHeight(math.max(totalHeight, FRAME_MIN_HEIGHT))

-- возвращаем верх на место (WoW мог сдвинуть)
if left and top then
    f:ClearAllPoints()
    f:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", left, top)
end

UpdateBuyButtonVisibility()

end

function UI:RenderHeader(f, guide, skill, step, recipeLearned, AddLine, ctx)
    AddLine(guide.name, "|cffffff00")
	if step and step.experiment then
		AddLine("Тип шага: эксперимент", "|cff66ccff")
	end

	if step and step.max then
		local _, real, bonus = G:GetEffectiveSkillLevel(G:GetSelectedSkillLine())
		if step.useEffectiveSkill then
			AddLine("Крафтить до навыка: "..step.max, "|cffaaaaaa")

		elseif bonus and bonus > 0 and not step.useEffectiveSkill then
			AddLine(
				"Крафтить до навыка: "..(step.max + bonus).." |cff66ccff(+"..bonus.." раса)|r",
				"|cffaaaaaa"
			)
		else
			AddLine("Крафтить до навыка: "..step.max, "|cffaaaaaa")
		end
	end

	if recipeLearned == false then
		AddLine("|cffff5555Рецепт не изучен|r")
		AddLine("|cffaaaaaaКупите рецепт у продавца|r")
	end

    if skill == false then
        AddLine("Ручной просмотр шага", "|cffaaaaaa")
    elseif type(skill) == "number" then
        local eff, real, bonus = G:GetEffectiveSkillLevel(G:GetSelectedSkillLine())

		if bonus > 0 then
			AddLine("Skill: "..real.." |cff66ccff(+"..bonus.." раса)|r", "|cffaaaaaa")
		else
			AddLine("Skill: "..real, "|cffaaaaaa")
		end
    end
end

function UI:RenderNote(f, step, AddLine, ctx)
    if not step then return end

    local note = step.note
    if not note or note == "" then return end
	local refs = BuildNoteRefs(step)

    ctx.y = ctx.y + 8

	local line = GetTextLine(f, ctx.i)
	line:ClearAllPoints()
	line:SetPoint("TOPLEFT", f.content, "TOPLEFT", 0, -ctx.y)
	line:SetWidth(220)
	line:SetHeight(16)   -- ← ВОТ ЭТОГО НЕ ХВАТАЛО
	line.text:SetWidth(200) -- 220 - иконка - отступ
	line.text:SetWordWrap(true)

    -- иконка help-i
    if not line.icon then
        line.icon = line:CreateTexture(nil, "OVERLAY")
        line.icon:SetSize(20, 20)
        line.icon:SetPoint("LEFT", 0, 0)
        line.icon:SetTexture("Interface\\COMMON\\help-i")
		line.icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)

    end
    line.icon:Show()

    -- текст рядом с иконкой
    line.text:SetPoint("LEFT", line.icon, "RIGHT", 2, 0)
    line.text:SetText("|cff66ccffЗаметка|r")

    line.itemID = nil
    line.itemLink = nil
    line:Show()

    ctx.y = ctx.y + 16
    ctx.i = ctx.i + 1

    -- многострочный текст заметки
	for textLine in string.gmatch(note, "[^\n]+") do
		local l = GetTextLine(f, ctx.i)
		l:ClearAllPoints()
		l:SetPoint("TOPLEFT", f.content, "TOPLEFT", 0, -ctx.y)
		l:SetWidth(220)
		l.text:SetWidth(250)
		l.text:SetWordWrap(true)
		l.text:SetText("|cffaaaaaa"..textLine.."|r")

		l.itemID = nil
		l.itemLink = nil
		l:Show()

		local h = l.text:GetStringHeight()
		l:SetHeight(h)

		ctx.y = ctx.y + h
		ctx.i = ctx.i + 1
	end
    if refs then
        ctx.y = ctx.y + 4
        for _, text in ipairs(refs) do
            AddLine(text, "|cff66ccff")
        end
    end

    AddLine("")
end


function UI:RenderRecipes(f, step, AddLine, ctx)
    AddLine("Сейчас крафтить:", "|cffffffaa")

    for _, r in ipairs(step.recipes or {}) do
        local recipeName

        if r.spellID and C_Spell and C_Spell.GetSpellInfo then
            local info = C_Spell.GetSpellInfo(r.spellID)
            recipeName = info and info.name
        elseif r.name then
            recipeName = r.name
        end

        if recipeName then
            AddLine(" • "..recipeName, "|cff66ccff")
        end
    end

    AddLine("")
end

function UI:RenderMaterials(f, step, skill, AddLine, ctx, GetTextLine)
    AddLine("Materials required:", "|cffffffaa")

    local recipe = step.recipes and step.recipes[1]
    if not recipe then
        AddLine("")
        return
    end
	-- =========================
	-- ИЛИ между разными предметами
	-- =========================
	if recipe.reagentsAny then
		for i, r in ipairs(recipe.reagentsAny) do
			local need = r.count or 0
			local have = G:GetItemCountTotal(r.itemID)

			local line = GetTextLine(f, ctx.i)
			line:ClearAllPoints()
			line:SetPoint("TOPLEFT", f.content, "TOPLEFT", 0, -ctx.y)

			local link = select(2, GetItemInfo(r.itemID)) or ("item:"..r.itemID)
			local color = have >= need and "|cff00ff00" or "|cffff5555"
			local prefix = (i == 1) and " • " or "   ИЛИ "

			line.text:SetText(
				prefix .. link .. " " .. color .. "× " .. need .. "|r  |cffaaaaaa(есть: "..have..")|r"
			)

			line.itemID   = r.itemID
			line.itemLink = link
			line:Show()

			ctx.y = ctx.y + 16
			ctx.i = ctx.i + 1
		end

		AddLine("")
		return
	end

local eff, real = G:GetEffectiveSkillLevel(G:GetSelectedSkillLine())

local crafts = (recipe.crafts and recipe.crafts > 0)
    and recipe.crafts
	or G:GetRemainingCraftsForStep(skillLineID, step)

	for _, r in ipairs(recipe.reagents or {}) do
		local need = math.max(0, (r.count or 0) * crafts)

	if r.anyOf then
		local maxHave = 0
		local bestItemID

		for _, opt in ipairs(r.anyOf) do
			local have = G:GetItemCountTotal(opt.itemID)
			if have > maxHave then
				maxHave = have
				bestItemID = opt.itemID
			end
		end

		-- 🔧 FIX: если ничего нет — всё равно показываем предмет
		if not bestItemID and r.anyOf[1] then
			bestItemID = r.anyOf[1].itemID
		end

		local link = bestItemID
			and (select(2, GetItemInfo(bestItemID)) or ("item:"..bestItemID))
			or "любой грейд"

			local color = maxHave >= need and "|cff00ff00" or "|cffff5555"

		local line = GetTextLine(f, ctx.i)
		line:ClearAllPoints()
		line:SetPoint("TOPLEFT", f.content, "TOPLEFT", 0, -ctx.y)

		line.text:SetText(
			" • " .. link .. " " .. color .. "× " .. need .. "|r  |cff00ff00(самый дешёвый грейд)|r"
		)

		line.itemID   = bestItemID
		line.itemLink = link
		line:Show()

		ctx.y = ctx.y + 16
		ctx.i = ctx.i + 1

		else
			local have = G:GetItemCountTotal(r.itemID)
			local link = select(2, GetItemInfo(r.itemID)) or ("item:"..r.itemID)
			local color = have >= need and "|cff00ff00" or "|cffff5555"

		local line = GetTextLine(f, ctx.i)
		line:ClearAllPoints()
		line:SetPoint("TOPLEFT", f.content, "TOPLEFT", 0, -ctx.y)

		line.text:SetText(
			" • " .. link .. " " .. color .. "× " .. need .. "|r  |cffaaaaaa(есть: "..have..")|r"
		)

		line.itemID   = r.itemID
		line.itemLink = link
		line:Show()

		ctx.y = ctx.y + 16
		ctx.i = ctx.i + 1

		end
	end

    AddLine("")
end

function UI:RenderRecipeVendor(f, vendor, ctx)
    -- hide previous trainer buttons
    if f.trainerButtons then
        for _, b in ipairs(f.trainerButtons) do
            b:Hide()
        end
    end

    if f.trainersHeader then
        f.trainersHeader:Hide()
    end

    -- header
    ctx.y = ctx.y + 12
    f.trainersHeader:ClearAllPoints()
    f.trainersHeader:SetPoint("TOPLEFT", f.content, "TOPLEFT", 0, -ctx.y)
    f.trainersHeader:SetText("Продавец рецепта:")
    f.trainersHeader:Show()

    ctx.y = ctx.y + 18

    local b = f.trainerButtons[1]

    if not b then
        b = CreateFrame("Button", nil, f.content)
        b:SetSize(230, 20)
        b:EnableMouse(true)
        CreateButtonBorder(b)

        b.bg = b:CreateTexture(nil, "BACKGROUND")
        b.bg:SetAllPoints()
        b.bg:SetColorTexture(1, 1, 1, 0)

        b:SetScript("OnEnter", function(self)
            self.bg:SetColorTexture(1, 1, 1, 0.08)
            if self.border then
                self.border:SetBackdropBorderColor(1, 1, 1, 0.35)
            end
        end)

        b:SetScript("OnLeave", function(self)
            self.bg:SetColorTexture(1, 1, 1, 0)
            if self.border then
                self.border:SetBackdropBorderColor(1, 1, 1, 0.15)
            end
        end)

        b.text = b:CreateFontString(nil, "OVERLAY")
        b.text:SetFont(FONT, 12)
        b.text:SetPoint("LEFT", 6, 0)

        f.trainerButtons[1] = b
    end

    b:ClearAllPoints()
    b:SetPoint("TOPLEFT", f.content, "TOPLEFT", 0, -ctx.y)
    b.text:SetText(" " .. (vendor.name or ("NPC " .. (vendor.npcID or "?"))))
    b:SetScript("OnClick", function()
        Waypoints:SetTrainerWaypoint(vendor)
    end)

    b:Show()
    ctx.y = ctx.y + 22
end

function UI:RenderTrainers(f, guide, ctx)
    -- hide previous
    if f.trainerButtons then
        for _, b in ipairs(f.trainerButtons) do
            b:Hide()
        end
    end
    if f.trainersHeader then
        f.trainersHeader:Hide()
    end

    if not guide or not guide.trainers then return end

    local faction = (G.GetPlayerFaction and G:GetPlayerFaction())
    if not faction then return end

    local trainers = guide.trainers[faction]
    if not trainers or #trainers == 0 then return end

    -- header
    ctx.y = ctx.y + 12
    f.trainersHeader:ClearAllPoints()
    f.trainersHeader:SetPoint("TOPLEFT", f.content, "TOPLEFT", 0, -ctx.y)
    f.trainersHeader:Show()

    ctx.y = ctx.y + 18

    for idx, t in ipairs(trainers) do
        local b = f.trainerButtons[idx]

        if not b then
            b = CreateFrame("Button", nil, f.content)
            b:SetSize(230, 20)
            b:EnableMouse(true)
            CreateButtonBorder(b)

            b.bg = b:CreateTexture(nil, "BACKGROUND")
            b.bg:SetAllPoints()
            b.bg:SetColorTexture(1, 1, 1, 0)

            b:SetScript("OnEnter", function(self)
                self.bg:SetColorTexture(1, 1, 1, 0.08)
                if self.border then
                    self.border:SetBackdropBorderColor(1, 1, 1, 0.35)
                end
            end)

            b:SetScript("OnLeave", function(self)
                self.bg:SetColorTexture(1, 1, 1, 0)
                if self.border then
                    self.border:SetBackdropBorderColor(1, 1, 1, 0.15)
                end
            end)

            b.text = b:CreateFontString(nil, "OVERLAY")
            b.text:SetFont(FONT, 12)
            b.text:SetPoint("LEFT", 6, 0)

            f.trainerButtons[idx] = b
        end

        b:ClearAllPoints()
        b:SetPoint("TOPLEFT", f.content, "TOPLEFT", 0, -ctx.y)
        b.text:SetText(" " .. (t.name or ("NPC " .. (t.npcID or "?"))))
        b:SetScript("OnClick", function()
            Waypoints:SetTrainerWaypoint(t)
        end)

        b:Show()
        ctx.y = ctx.y + 22
    end
end

-- =====================================================
-- Toggle
-- =====================================================

SLASH_AHUIPG1 = "/pg"
SlashCmdList.AHUIPG = function()
    local f = UI.frame or UI:Create()
	if f:IsShown() then
		f:Hide()
	else
		f:Show()
		UpdateBuyButtonVisibility()
		UI:Refresh()
	end

end

UI.frame = UI:Create()
UI.frame.epochBtn:SetScript("OnClick", function(self)
    ShowEpochMenu(self)
end)
UI.frame.profBtn:SetScript("OnClick", function(self)
    ShowProfessionMenu(self)
end)
Shopping.OnAuctionStateChanged = function()
    UpdateBuyButtonVisibility()
end

-- =====================================================
-- Auto refresh on game state changes
-- =====================================================

local pgWatcher = CreateFrame("Frame")

	pgWatcher:RegisterEvent("SKILL_LINES_CHANGED")
	pgWatcher:RegisterEvent("TRADE_SKILL_DATA_SOURCE_CHANGED")
	pgWatcher:RegisterEvent("TRADE_SKILL_CLOSE")
	pgWatcher:RegisterEvent("BAG_UPDATE_DELAYED")
	pgWatcher:RegisterEvent("PLAYER_REGEN_ENABLED")
	pgWatcher:RegisterEvent("NEW_RECIPE_LEARNED")
	pgWatcher:RegisterEvent("TRADE_SKILL_LIST_UPDATE")

pgWatcher:SetScript("OnEvent", function(_, event)
    if not UI.frame or not UI.frame:IsShown() then return end

    local skillLineID = G:GetSelectedSkillLine()
    if not skillLineID then return end

    -- события, при которых профессия обновляет данные асинхронно
    if event == "NEW_RECIPE_LEARNED"
       or event == "TRADE_SKILL_LIST_UPDATE"
       or event == "TRADE_SKILL_DATA_SOURCE_CHANGED"
    then
        -- обновляемся на следующий кадр, когда API уже актуален
        C_Timer.After(0, function()
            if not UI.frame or not UI.frame:IsShown() then return end

            G:ValidateManualStep(skillLineID)
            State:Save()
            UI:Refresh()
        end)

        return
    end

    -- дефолтное поведение для прочих событий
    G:ValidateManualStep(skillLineID)
    State:Save()
    UI:Refresh()
end)