from flask import Flask, render_template, request, session
import full
import csv
import numpy as np
import json

app = Flask(__name__)  # two underscores before and after name
app.secret_key = "mlb_capstone_simulation"

def get_pitcher_data():
    pitchers = []
    with open('pitcher_list.csv', mode='r', encoding='utf-8') as f:
        reader = csv.DictReader(f)
        for row in reader:
            pitchers.append({
                'id_number' : row['pitcher'],
                'name' : row['player_name'],
                'throws' : row['p_throws']})
    return pitchers

def get_pitch_options(selected_pitcher, selected_batter_stance):
    pitches = []
    search_pitcher = str(selected_pitcher)
    with open('pitchnames_and_estsd.csv', mode='r', encoding='utf-8') as f:
        reader = csv.DictReader(f)
        for row in reader:
            if row['pitcher'] == search_pitcher and row['stand'] == selected_batter_stance:
                pitches.append({
                    'pitch_name': row['pitch_name'],
                    'sd_x': float(row['est_sdx']),
                    'sd_z': float(row['est_sdz'])})
    return pitches


outcome_colors = {
    "Called Strike": "#d7191c",
    "Ball": "#2c7bb6",
    "Miss": "#256a9e",
    "Foul": "#f6e995",
    "In Play": "#dbeffa"
}


@app.route('/', methods = ['GET', 'POST'])
def index():
    #list of options that user can select
    pitcher_options = get_pitcher_data()
    stance_options = ["L", "R"]
    
    #set ab
    balls = session.get('balls', 0)
    strikes = session.get('strikes', 0)
    logs = session.get('logs', [])
    outcome = None

    #what will default on the screen
    selected_pitcher = None
    selected_batter_stance = None
    selected_pitch = None

    available_pitches = []
    matchup_set = False

    if request.method == 'GET':
        if 'selected_pitcher_id' not in request.form:
            session.clear() 
            balls = 0
            strikes = 0
            logs = []
    

    if request.method == 'POST':
        #stores id number as a string...
        raw_pitcher_id = request.form.get('selected_pitcher_id')
        #convert to int for pitcher id...
        if raw_pitcher_id:
            selected_pitcher = int(raw_pitcher_id)

        selected_batter_stance = request.form.get('selected_stance')
        

        if selected_pitcher and selected_batter_stance:
            available_pitches = get_pitch_options(selected_pitcher, selected_batter_stance)
            matchup_set = True
        

        selected_pitch = request.form.get('pitch_selection')

        for p in available_pitches:
            if p['pitch_name'] == selected_pitch:
                sd_x = p['sd_x']
                sd_z = p['sd_z']
                break

        #take selections and pass them to full.py run_simulation
        if selected_pitch:
            # get values from dragging pitch
            raw_x = request.form.get('plate_x')
            raw_z = request.form.get('plate_z')

            # use default if missing
            mu_x = float(raw_x) if raw_x and raw_x.strip() else 0.0
            mu_z = float(raw_z) if raw_z and raw_z.strip() else 2.5
            

            sim_output = full.run_simulation(selected_pitcher, selected_batter_stance, selected_pitch, balls, strikes,
                                             sd_x, sd_z, mu_x, mu_z) #edits here
        
            probs = sim_output['outcome'].value_counts(normalize=True)

            #creating lists for additional details under each pitch
            #outcome probabilities
            #probs_list = [f"{outcome}: {val*100:.1f}%" for outcome, val in probs.items()]
            probs_labels = probs.index.tolist()
            probs_values = [float(v * 100) for v in probs.tolist()]
            current_colors = [outcome_colors.get(label, "#cccccc") for label in probs_labels]

            #umpire call
            ump = sim_output['true_call'].value_counts(normalize=True)
            ump_pct = ump.get('Called Strike', 0) * 100
            #swing prob
            avg_swing_prob = sim_output['p_swing'].mean() * 100


            #get one result for at bat
            pitch_result = np.random.choice(probs.index, size=1, p=probs.values.astype('float64'))[0]

            #update at bat count
            if pitch_result == "Ball":
                balls += 1
            elif pitch_result in ["Called Strike", "Miss"]:
                strikes += 1
            elif pitch_result == "Foul" and strikes < 2:
                strikes += 1

            #check if AB is over
            outcome = None
            if balls >= 4:
                outcome = "Walk"
            elif strikes >= 3:
                outcome = "Strikeout"
            elif pitch_result == "In Play":
                outcome = "Hit into Play"


            pitch_data = {
                "result": pitch_result,
                "count": f"{balls - strikes}",
                "outcome_labels": json.dumps(probs_labels),
                "outcome_values": json.dumps(probs_values),
                "outcome_colors": json.dumps(current_colors),
                #"probs": probs_list,
                "ump_call": f"{ump_pct:.1f}% Strike",
                "avg_swing": f"{avg_swing_prob:.1f}%"
            }

            if outcome:
                pitch_data["display_text"] = f"Result: {pitch_result} | Final: {outcome}"
                logs.append(pitch_data)
                session.clear() #reset for next hitter
            else:
                pitch_data["display_text"] = f" {selected_pitch} | {pitch_result} | Count: {balls}-{strikes}"
                logs.append(pitch_data)
                session['balls'] = balls
                session['strikes'] = strikes
                session['logs'] = logs

    return render_template('index.html', 
                           pitchers=pitcher_options,
                           pitcher=selected_pitcher, 
                           stances=stance_options,
                           selected_stance=selected_batter_stance,
                           pitches=available_pitches,
                           pitch=selected_pitch,
                           balls=balls,
                           strikes=strikes,
                           matchup_set=matchup_set,
                           pitch_logs=logs,
                           outcome=outcome)

if __name__ == '__main__':
    app.run(debug=True)