#!/usr/bin/env python3
"""
Fibonacci Retracement Chart Generator for GJTL
"""

import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import numpy as np
from datetime import datetime, timedelta

def calculate_fib_levels(high, low):
    """Calculate Fibonacci retracement levels"""
    diff = high - low
    
    levels = {
        '0.0% (Low)': low,
        '23.6%': low + diff * 0.236,
        '38.2%': low + diff * 0.382,
        '50.0%': low + diff * 0.500,
        '61.8%': low + diff * 0.618,
        '78.6%': low + diff * 0.786,
        '100.0% (High)': high,
    }
    return levels

def plot_fibonacci(dates, prices, high, low, current, fib_levels, save_path=None):
    """Plot Fibonacci retracement chart"""
    
    fig, ax = plt.subplots(figsize=(18, 10))
    
    # Plot price line
    ax.plot(dates, prices, label='Close Price', color='#1f77b4', linewidth=2, zorder=5)
    ax.fill_between(dates, prices, min(prices)*0.95, alpha=0.1, color='blue')
    
    # Define colors for fib levels
    fib_colors = {
        '0.0% (Low)': '#e74c3c',      # Red
        '23.6%': '#9b59b6',            # Purple
        '38.2%': '#3498db',            # Blue
        '50.0%': '#f39c12',            # Orange/Gold
        '61.8%': '#27ae60',            # Green
        '78.6%': '#16a085',            # Teal
        '100.0% (High)': '#c0392b',   # Dark Red
    }
    
    # Plot horizontal Fibonacci lines
    for level_name, level_price in fib_levels.items():
        color = fib_colors.get(level_name, 'gray')
        linestyle = '--' if '%' in level_name else '-'
        linewidth = 1.5 if '0%' in level_name or '100%' in level_name else 1.0
        
        ax.axhline(y=level_price, color=color, linestyle=linestyle, linewidth=linewidth, alpha=0.8, zorder=3)
        
        # Add label
        ax.text(dates[-1] + timedelta(days=5), level_price, 
                f'{level_name}: IDR {level_price:.0f}', 
                fontsize=9, color=color, va='center', fontweight='bold')
    
    # Mark High and Low points
    max_idx = np.argmax(prices)
    min_idx = np.argmin(prices)
    
    ax.scatter([dates[max_idx]], [prices[max_idx]], color='green', s=200, zorder=10, marker='^', label=f'High: IDR {high:.0f}')
    ax.scatter([dates[min_idx]], [prices[min_idx]], color='red', s=200, zorder=10, marker='v', label=f'Low: IDR {low:.0f}')
    
    # Mark current price
    ax.scatter([dates[-1]], [current], color='blue', s=200, zorder=10, marker='o', label=f'Current: IDR {current:.0f}')
    
    # Add zone annotations
    # Between 0-23.6% (Strong Sell zone)
    ax.axhspan(low, fib_levels['23.6%'], alpha=0.1, color='red', zorder=1)
    # Between 23.6-38.2% (Sell zone)
    ax.axhspan(fib_levels['23.6%'], fib_levels['38.2%'], alpha=0.1, color='orange', zorder=1)
    # Between 38.2-50% (Neutral)
    ax.axhspan(fib_levels['38.2%'], fib_levels['50.0%'], alpha=0.1, color='yellow', zorder=1)
    # Between 50-61.8% (Buy zone)
    ax.axhspan(fib_levels['50.0%'], fib_levels['61.8%'], alpha=0.1, color='lightgreen', zorder=1)
    # Between 61.8-100% (Strong Buy zone)
    ax.axhspan(fib_levels['61.8%'], high, alpha=0.1, color='green', zorder=1)
    
    # Title
    ax.set_title(f'Fibonacci Retracement — GJTL (Gajah Tunggal)\nHigh: IDR {high:.0f} | Low: IDR {low:.0f} | Current: IDR {current:.0f}', 
                 fontsize=14, fontweight='bold')
    
    ax.set_xlabel('Date', fontsize=12)
    ax.set_ylabel('Price (IDR)', fontsize=12)
    
    # Legend
    ax.legend(loc='upper left', fontsize=10)
    
    # Grid
    ax.grid(True, alpha=0.3, zorder=2)
    
    # Rotate x-axis
    plt.xticks(rotation=45)
    
    # Set y-axis limits with padding
    ax.set_ylim(low * 0.95, high * 1.05)
    
    plt.tight_layout()
    
    if save_path:
        plt.savefig(save_path, dpi=150, bbox_inches='tight')
        print(f"Chart saved to: {save_path}")
    
    plt.close()
    print("Fibonacci chart generated!")

def main():
    # GJTL known price data
    high_52w = 1265
    low_52w = 925
    current = 1120
    
    # Generate simulated 2-year daily data
    np.random.seed(42)
    n_days = 504  # ~2 years trading days
    
    # Generate realistic price path
    start_price = low_52w + 50
    end_price = current
    
    t = np.linspace(0, 1, n_days)
    
    # Create path that reaches high then pulls back
    trend = np.sin(t * np.pi * 2.5) * 150
    noise = np.cumsum(np.random.randn(n_days) * 6)
    
    prices = start_price + trend + noise
    prices = np.clip(prices, low_52w * 0.95, high_52w * 1.05)
    prices[-1] = end_price
    
    # Ensure the high point is reached
    prices[150] = high_52w  # Set a peak
    
    # Generate dates
    end_date = datetime(2026, 7, 16)
    dates = [end_date - timedelta(days=i) for i in range(n_days-1, -1, -1)]
    
    # Calculate Fibonacci levels
    print("Calculating Fibonacci levels...")
    fib_levels = calculate_fib_levels(high_52w, low_52w)
    
    print(f"\n52-Week High: IDR {high_52w:.0f}")
    print(f"52-Week Low: IDR {low_52w:.0f}")
    print(f"Current Price: IDR {current:.0f}")
    print(f"\n--- FIBONACCI RETRACEMENT LEVELS ---")
    
    for name, level in fib_levels.items():
        if current >= level:
            zone = "✅ ABOVE"
        else:
            zone = "⬇️ BELOW"
        print(f"  {name}: IDR {level:.0f} {zone}")
    
    # Determine where current price is
    print(f"\n--- POSITION ANALYSIS ---")
    for i, (name, level) in enumerate(list(fib_levels.items())[:-1]):
        next_name = list(fib_levels.keys())[i+1]
        next_level = list(fib_levels.values())[i+1]
        if low_52w <= current < next_level:
            print(f"  Current price (IDR {current}) is between {name} and {next_name}")
            retracement = (current - low_52w) / (high_52w - low_52w) * 100
            print(f"  Price has retraced {retracement:.1f}% from the low")
            break
    
    # Support and resistance interpretation
    print(f"\n--- SUPPORT & RESISTANCE ---")
    
    # Find nearest support below current
    supports = [(name, level) for name, level in fib_levels.items() if level < current]
    if supports:
        nearest_support = max(supports, key=lambda x: x[1])
        print(f"  Nearest SUPPORT: {nearest_support[0]} at IDR {nearest_support[1]:.0f}")
    
    # Find nearest resistance above current
    resistances = [(name, level) for name, level in fib_levels.items() if level > current]
    if resistances:
        nearest_resistance = min(resistances, key=lambda x: x[1])
        print(f"  Nearest RESISTANCE: {nearest_resistance[0]} at IDR {nearest_resistance[1]:.0f}")
    
    # Investment interpretation
    print(f"\n--- FIBONACCI INTERPRETATION ---")
    retracement_pct = (current - low_52w) / (high_52w - low_52w)
    
    if retracement_pct < 0.382:
        print("  📍 Position: 0-38.2% zone (Deep retracement)")
        print("  ⚠️ Signal: BEARISH - In strong sell zone")
        print("  💡 Interpretation: Price has barely recovered from low")
    elif retracement_pct < 0.500:
        print("  📍 Position: 38.2-50% zone (Moderate retracement)")
        print("  ⚠️ Signal: NEUTRAL to SLIGHTLY BEARISH")
        print("  💡 Interpretation: Consolidation zone")
    elif retracement_pct < 0.618:
        print("  📍 Position: 50-61.8% zone (Golden Zone)")
        print("  ✅ Signal: BULLISH - Key support zone")
        print("  💡 Interpretation: Strong support, potential bounce zone")
    elif retracement_pct < 0.786:
        print("  📍 Position: 61.8-78.6% zone (Recovery zone)")
        print("  ✅ Signal: BULLISH - Strong recovery")
        print("  💡 Interpretation: Healthy retracement, uptrend intact")
    else:
        print("  📍 Position: Above 78.6% (Near high)")
        print("  ⚡ Signal: STRONG BULLISH")
        print("  💡 Interpretation: Near all-time highs, potential breakout or reversal")
    
    # Plot
    save_path = "/home/ubuntu/fibonacci_GJTL.png"
    print(f"\nGenerating chart...")
    plot_fibonacci(dates, prices, high_52w, low_52w, current, fib_levels, save_path)
    
    print(f"\n✅ Chart saved to: {save_path}")

if __name__ == "__main__":
    main()
