// This Pine Script™ source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © TMB Invest - NightFibPRO

//@version=6
indicator("TMB Invest - NightFibPRO", shorttitle="NightFibPRO", overlay=true, max_lines_count=500, max_labels_count=500)

// ══════════════════════════════════════════════════════════════════════════════
// EINSTELLUNGEN
// ══════════════════════════════════════════════════════════════════════════════

grp_time = "⏰ Zeiteinstellungen"
nightStartHour = input.int(22, "Nacht-Session Start (Stunde)", minval=0, maxval=23, group=grp_time)
nightStartMin = input.int(0, "Nacht-Session Start (Minute)", minval=0, maxval=59, group=grp_time)
nightEndHour = input.int(6, "Nacht-Session Ende (Stunde)", minval=0, maxval=23, group=grp_time)
nightEndMin = input.int(59, "Nacht-Session Ende (Minute)", minval=0, maxval=59, group=grp_time)
timezone = input.string("Europe/Berlin", "Zeitzone", group=grp_time)

grp_fib = "📐 Fibonacci-Einstellungen"
showFib0 = input.bool(true, "0 (High)", inline="fib1", group=grp_fib)
showFib236 = input.bool(true, "0.236", inline="fib1", group=grp_fib)
showFib382 = input.bool(true, "0.382", inline="fib1", group=grp_fib)
showFib5 = input.bool(true, "0.5", inline="fib2", group=grp_fib)
showFib618 = input.bool(true, "0.618", inline="fib2", group=grp_fib)
showFib786 = input.bool(true, "0.786", inline="fib2", group=grp_fib)
showFib1 = input.bool(true, "1 (Low)", inline="fib2", group=grp_fib)

grp_style = "🎨 Darstellung"
lineWidth = input.int(1, "Linienbreite", minval=1, maxval=4, group=grp_style)
extendLines = input.bool(false, "Linien nach rechts erweitern", group=grp_style)
showLabels = input.bool(true, "Labels anzeigen", group=grp_style)
labelSize = input.string("small", "Label-Größe", options=["tiny", "small", "normal", "large"], group=grp_style)

// ─── BLAU-FARBSCHEMA (TMB-Invest Branding) ───
col0 = input.color(color.new(#93C5FD, 0), "Farbe 0 (High)", group=grp_style)           // Hellblau
col236 = input.color(color.new(#60A5FA, 0), "Farbe 0.236", group=grp_style)            // Sky Blue
col382 = input.color(color.new(#3B82F6, 0), "Farbe 0.382", group=grp_style)            // Primary Blue
col5 = input.color(color.new(#2563EB, 0), "Farbe 0.5", group=grp_style)                // Brand Blue (Button)
col618 = input.color(color.new(#1D4ED8, 0), "Farbe 0.618", group=grp_style)            // Deep Blue (Key-Level)
col786 = input.color(color.new(#3B82F6, 0), "Farbe 0.786", group=grp_style)            // Primary Blue
col1 = input.color(color.new(#60A5FA, 0), "Farbe 1 (Low)", group=grp_style)            // Sky Blue

grp_zone = "🌙 Nacht-Zone"
showNightZone = input.bool(true, "Nacht-Zone farbig hinterlegen", group=grp_zone)
nightZoneColor = input.color(color.new(#2563EB, 88), "Nacht-Zone Farbe", group=grp_zone)

// ══════════════════════════════════════════════════════════════════════════════
// ZEITBERECHNUNG
// ══════════════════════════════════════════════════════════════════════════════

// Aktuelle Zeit in der gewählten Zeitzone
currentHour = hour(time, timezone)
currentMin = minute(time, timezone)
currentTime = currentHour * 100 + currentMin

// Nacht-Session Zeiten
nightStart = nightStartHour * 100 + nightStartMin  // z.B. 2200
nightEnd = nightEndHour * 100 + nightEndMin        // z.B. 659

// Prüfen ob wir in der Nacht-Session sind (über Mitternacht)
isNightSession = nightStart > nightEnd ? 
     (currentTime >= nightStart or currentTime <= nightEnd) : 
     (currentTime >= nightStart and currentTime <= nightEnd)

// Prüfen ob wir in der Tages-Session sind (07:00 - 21:59)
isDaySession = currentTime >= 700 and currentTime < 2200

// Erkennen wann die Nacht-Session endet (Übergang zu Tag)
wasNightSession = nightStart > nightEnd ? 
     (currentTime[1] >= nightStart or currentTime[1] <= nightEnd) : 
     (currentTime[1] >= nightStart and currentTime[1] <= nightEnd)

nightSessionEnded = wasNightSession and not isNightSession

// Erkennen wann eine neue Nacht-Session beginnt
nightSessionStarted = not wasNightSession and isNightSession

// ══════════════════════════════════════════════════════════════════════════════
// HIGH/LOW TRACKING
// ══════════════════════════════════════════════════════════════════════════════

var float nightHigh = na
var float nightLow = na
var int nightHighBar = na
var int nightLowBar = na
var bool nightDataReady = false

// Nacht-Session High/Low sammeln
if nightSessionStarted
    nightHigh := high
    nightLow := low
    nightHighBar := bar_index
    nightLowBar := bar_index
    nightDataReady := false

if isNightSession
    if high > nightHigh or na(nightHigh)
        nightHigh := high
        nightHighBar := bar_index
    if low < nightLow or na(nightLow)
        nightLow := low
        nightLowBar := bar_index

if nightSessionEnded
    nightDataReady := true

// ══════════════════════════════════════════════════════════════════════════════
// FIBONACCI BERECHNUNG
// ══════════════════════════════════════════════════════════════════════════════

var float fibHigh = na
var float fibLow = na
var float fibRange = na

// Fibonacci-Level speichern wenn Nacht-Session endet
if nightSessionEnded and not na(nightHigh) and not na(nightLow)
    fibHigh := nightHigh
    fibLow := nightLow
    fibRange := nightHigh - nightLow

// Fibonacci-Werte berechnen (0 = High, 1 = Low)
calcFibLevel(level) =>
    fibHigh - (fibRange * level)

fib0 = calcFibLevel(0)      // High
fib236 = calcFibLevel(0.236)
fib382 = calcFibLevel(0.382)
fib5 = calcFibLevel(0.5)
fib618 = calcFibLevel(0.618)
fib786 = calcFibLevel(0.786)
fib1 = calcFibLevel(1)      // Low

// ══════════════════════════════════════════════════════════════════════════════
// ZEICHNEN
// ══════════════════════════════════════════════════════════════════════════════

var line[] fibLines = array.new_line()
var label[] fibLabels = array.new_label()
var int dayStartBar = na
var box nightBox = na

// Label-Größe konvertieren
getLabelSize() =>
    switch labelSize
        "tiny" => size.tiny
        "small" => size.small
        "normal" => size.normal
        "large" => size.large
        => size.small

// Alte Linien und Labels löschen wenn neue Session beginnt
if nightSessionEnded
    // Alte Objekte löschen
    for ln in fibLines
        line.delete(ln)
    array.clear(fibLines)
    
    for lbl in fibLabels
        label.delete(lbl)
    array.clear(fibLabels)
    
    dayStartBar := bar_index

// Tages-Session Ende erkennen (21:59 -> 22:00)
daySessionEnded = currentTime >= 2200 and currentTime[1] < 2200

// Fibonacci-Linien während der Tages-Session zeichnen
if isDaySession and nightDataReady and not na(fibRange) and fibRange > 0
    // Linien bei jedem Bar aktualisieren
    for ln in fibLines
        line.delete(ln)
    array.clear(fibLines)
    
    for lbl in fibLabels
        label.delete(lbl)
    array.clear(fibLabels)
    
    lineExt = extendLines ? extend.right : extend.none
    
    // Level 0 (High)
    if showFib0 and not na(fib0)
        array.push(fibLines, line.new(dayStartBar, fib0, bar_index, fib0, color=col0, width=lineWidth, extend=lineExt))
        if showLabels
            array.push(fibLabels, label.new(bar_index + 2, fib0, "0 | " + str.tostring(fib0, format.mintick), style=label.style_label_left, color=color.new(col0, 80), textcolor=col0, size=getLabelSize()))
    
    // Level 0.236
    if showFib236 and not na(fib236)
        array.push(fibLines, line.new(dayStartBar, fib236, bar_index, fib236, color=col236, width=lineWidth, extend=lineExt))
        if showLabels
            array.push(fibLabels, label.new(bar_index + 2, fib236, "0.236 | " + str.tostring(fib236, format.mintick), style=label.style_label_left, color=color.new(col236, 80), textcolor=col236, size=getLabelSize()))
    
    // Level 0.382
    if showFib382 and not na(fib382)
        array.push(fibLines, line.new(dayStartBar, fib382, bar_index, fib382, color=col382, width=lineWidth, extend=lineExt))
        if showLabels
            array.push(fibLabels, label.new(bar_index + 2, fib382, "0.382 | " + str.tostring(fib382, format.mintick), style=label.style_label_left, color=color.new(col382, 80), textcolor=col382, size=getLabelSize()))
    
    // Level 0.5
    if showFib5 and not na(fib5)
        array.push(fibLines, line.new(dayStartBar, fib5, bar_index, fib5, color=col5, width=lineWidth, extend=lineExt))
        if showLabels
            array.push(fibLabels, label.new(bar_index + 2, fib5, "0.5 | " + str.tostring(fib5, format.mintick), style=label.style_label_left, color=color.new(col5, 80), textcolor=col5, size=getLabelSize()))
    
    // Level 0.618
    if showFib618 and not na(fib618)
        array.push(fibLines, line.new(dayStartBar, fib618, bar_index, fib618, color=col618, width=lineWidth, extend=lineExt))
        if showLabels
            array.push(fibLabels, label.new(bar_index + 2, fib618, "0.618 | " + str.tostring(fib618, format.mintick), style=label.style_label_left, color=color.new(col618, 80), textcolor=col618, size=getLabelSize()))
    
    // Level 0.786
    if showFib786 and not na(fib786)
        array.push(fibLines, line.new(dayStartBar, fib786, bar_index, fib786, color=col786, width=lineWidth, extend=lineExt))
        if showLabels
            array.push(fibLabels, label.new(bar_index + 2, fib786, "0.786 | " + str.tostring(fib786, format.mintick), style=label.style_label_left, color=color.new(col786, 80), textcolor=col786, size=getLabelSize()))
    
    // Level 1 (Low)
    if showFib1 and not na(fib1)
        array.push(fibLines, line.new(dayStartBar, fib1, bar_index, fib1, color=col1, width=lineWidth, extend=lineExt))
        if showLabels
            array.push(fibLabels, label.new(bar_index + 2, fib1, "1 | " + str.tostring(fib1, format.mintick), style=label.style_label_left, color=color.new(col1, 80), textcolor=col1, size=getLabelSize()))

// Nacht-Zone Box zeichnen
if showNightZone
    if nightSessionStarted
        nightBox := box.new(bar_index, high, bar_index, low, 
             border_color=color.new(nightZoneColor, 60), 
             bgcolor=nightZoneColor)
    
    if isNightSession and not na(nightBox)
        box.set_right(nightBox, bar_index)
        box.set_top(nightBox, nightHigh)
        box.set_bottom(nightBox, nightLow)

// ══════════════════════════════════════════════════════════════════════════════
// INFO-TABELLE
// ══════════════════════════════════════════════════════════════════════════════

var table infoTable = table.new(position.top_right, 2, 4, 
     bgcolor=color.new(#0B1E33, 15), border_width=1, border_color=color.new(#2563EB, 50))

if barstate.islast
    statusText = isNightSession ? "🌙 Nacht-Session" : isDaySession ? "☀️ Tages-Session" : "⏸️ Pause"
    
    table.cell(infoTable, 0, 0, "Status", text_color=#60A5FA, text_size=size.small)
    table.cell(infoTable, 1, 0, statusText, text_color=color.white, text_size=size.small)
    
    table.cell(infoTable, 0, 1, "Nacht High", text_color=#60A5FA, text_size=size.small)
    table.cell(infoTable, 1, 1, str.tostring(nightHigh, format.mintick), text_color=#93C5FD, text_size=size.small)
    
    table.cell(infoTable, 0, 2, "Nacht Low", text_color=#60A5FA, text_size=size.small)
    table.cell(infoTable, 1, 2, str.tostring(nightLow, format.mintick), text_color=#3B82F6, text_size=size.small)
    
    table.cell(infoTable, 0, 3, "Range", text_color=#60A5FA, text_size=size.small)
    table.cell(infoTable, 1, 3, str.tostring(fibRange, format.mintick), text_color=#2563EB, text_size=size.small)

// ══════════════════════════════════════════════════════════════════════════════
// ALERTS
// ══════════════════════════════════════════════════════════════════════════════

alertcondition(nightSessionEnded, "Nacht-Session beendet", "Nacht-Session beendet - Fibonacci-Level aktiv")
alertcondition(ta.crossover(close, fib618), "Preis über 0.618", "Preis hat 0.618 Level nach oben durchbrochen")
alertcondition(ta.crossunder(close, fib618), "Preis unter 0.618", "Preis hat 0.618 Level nach unten durchbrochen")
alertcondition(ta.crossover(close, fib5), "Preis über 0.5", "Preis hat 0.5 Level nach oben durchbrochen")
alertcondition(ta.crossunder(close, fib5), "Preis unter 0.5", "Preis hat 0.5 Level nach unten durchbrochen")
