# src/geometry_viewer.py

import matplotlib
matplotlib.use("TkAgg")  # Para usar Tkinter como backend
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D  # necesario para 3D
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np

def plot_geometry_in_frame(parent_frame, geom, p1, p2):
    """
    Dibuja la geometría (Prisma/Cilindro/Esfera) en un Axes3D dentro
    de 'parent_frame' (un Frame de Tkinter). No abre ventana nueva.
    (Ejemplo de integración en tu TabDrag)
    """

    fig = plt.Figure(figsize=(4, 3), dpi=100)
    ax = fig.add_subplot(111, projection='3d')
    ax.set_title(f"{geom}", fontsize=10)

    if geom == "Prisma cuadrado":
        lado = p1
        largo = p2
        Xs = [0, lado, lado, 0, 0, lado, lado, 0]
        Ys = [0, 0, lado, lado, 0, 0, lado, lado]
        Zs = [0, 0, 0, 0, largo, largo, largo, largo]
        edges = [(0,1),(1,2),(2,3),(3,0),
                 (4,5),(5,6),(6,7),(7,4),
                 (0,4),(1,5),(2,6),(3,7)]
        for (i,j) in edges:
            ax.plot([Xs[i], Xs[j]], [Ys[i], Ys[j]], [Zs[i], Zs[j]], color='g')
        ax.set_xlim(0, max(lado,1))
        ax.set_ylim(0, max(lado,1))
        ax.set_zlim(0, max(largo,1))

    elif geom == "Cilindro":
        r = p1
        h = p2
        theta = np.linspace(0, 2*np.pi, 30)
        z = np.linspace(0, h, 30)
        theta_grid, z_grid = np.meshgrid(theta, z)
        X = r * np.cos(theta_grid)
        Y = r * np.sin(theta_grid)
        Z = z_grid
        ax.plot_surface(X, Y, Z, color='cyan', alpha=0.5)
        ax.set_xlim(-r, r)
        ax.set_ylim(-r, r)
        ax.set_zlim(0, h)

    elif geom == "Esfera":
        r = p1
        phi = np.linspace(0, np.pi, 30)
        theta = np.linspace(0, 2*np.pi, 30)
        phi_grid, theta_grid = np.meshgrid(phi, theta)
        X = r*np.sin(phi_grid)*np.cos(theta_grid)
        Y = r*np.sin(phi_grid)*np.sin(theta_grid)
        Z = r*np.cos(phi_grid)
        ax.plot_surface(X, Y, Z, color='yellow', alpha=0.6)
        ax.set_xlim(-r, r)
        ax.set_ylim(-r, r)
        ax.set_zlim(-r, r)

    else:
        # Geometría no reconocida
        ax.text2D(0.2, 0.5, "Geometría desconocida", transform=ax.transAxes)

    # Borramos lo anterior en parent_frame y embebemos el nuevo canvas
    for child in parent_frame.winfo_children():
        child.destroy()

    canvas = FigureCanvasTkAgg(fig, master=parent_frame)
    canvas_widget = canvas.get_tk_widget()
    canvas_widget.pack(fill="both", expand=True)
    canvas.draw()


def plot_coil_in_frame(parent_frame,
                       N=10,
                       e_pvc=1.0,
                       r_int=5.0,
                       r_ext=8.0,
                       h_c=10.0,
                       d_cu=0.5):
    """
    Dibuja un esquema 2D aproximado de la bobina en un Frame de Tkinter,
    basado en los parámetros:
        N       : número total de vueltas
        e_pvc   : espesor del PVC
        r_int   : radio interior de la bobina
        r_ext   : radio exterior total de la bobina
        h_c     : altura total de la bobina
        d_cu    : diámetro del conductor

    Se calcula:
        r_capas = r_ext - (r_int + e_pvc)
    Luego se distribuyen N vueltas en 'num_capas' radiales, etc.
    """

    # 1) Cálculo de la anchura de bobinado
    r_capas = r_ext - (r_int + e_pvc)
    if r_capas < 0:
        # Si ocurre un valor absurdo, forzamos a 0
        r_capas = 0.0

    # 2) Creamos la figura y eje 2D
    fig = plt.Figure(figsize=(4, 3), dpi=100)
    ax = fig.add_subplot(111)
    ax.set_aspect("equal", adjustable="box")
    ax.set_title("Bobina (vista 2D)", fontsize=10)

    # 3) Dibujar PVC como dos rectángulos "verticales"
    # Eje Y: 0 -> h_c
    # Izquierda: x ~ -(r_int + e_pvc) hasta -r_int
    # Derecha  : x ~  (r_int)         hasta  (r_int + e_pvc)
    ax.fill_between(
        x=[-(r_int + e_pvc), -r_int],
        y1=0,
        y2=h_c,
        color="black",
        alpha=0.3
    )
    ax.fill_between(
        x=[r_int, r_int + e_pvc],
        y1=0,
        y2=h_c,
        color="black",
        alpha=0.3
    )

    # 4) Cálculo de capas radiales y vueltas por capa
    num_capas = int(np.floor(r_capas / d_cu))
    if num_capas < 1:
        num_capas = 1

    vueltas_por_capa = int(np.ceil(N / num_capas))

    # 5) Distancia vertical entre vueltas en cada capa
    delta_h = h_c / (vueltas_por_capa + 1)

    # Función auxiliar para dibujar un conductor (círculo)
    def dibuja_conductor(xc, yc, radio):
        circle = plt.Circle((xc, yc), radio, color="orange", fill=True)
        ax.add_patch(circle)

    # 6) Bucle para colocar cada capa (izq/dcha)
    for i in range(num_capas):
        # X de la capa i, en lado izquierdo
        x_left = -(r_int + e_pvc + (2*i + 1) * (d_cu / 2))
        # ... y lado derecho
        x_right = +(r_int + e_pvc + (2*i + 1) * (d_cu / 2))

        # Añadimos vueltas en altura
        for j in range(vueltas_por_capa):
            y = (j + 1) * delta_h
            if y > h_c:
                break  # no dibujamos si excede la altura
            dibuja_conductor(x_left, y, d_cu/2)
            dibuja_conductor(x_right, y, d_cu/2)

    # 7) Ajustar los límites del dibujo en X e Y
    ax.set_xlim(-r_ext - d_cu, r_ext + d_cu)
    ax.set_ylim(0, h_c + d_cu)

    ax.set_xlabel("Radio (X)")
    ax.set_ylabel("Altura (Y)")
    ax.grid(True)

    # 8) Borramos lo anterior en parent_frame y embebemos esta figura
    for child in parent_frame.winfo_children():
        child.destroy()

    canvas = FigureCanvasTkAgg(fig, master=parent_frame)
    canvas_widget = canvas.get_tk_widget()
    canvas_widget.pack(fill="both", expand=True)
    canvas.draw()
