"""
Database writing functions for Tilt processed data.

Writes elaborated tilt sensor data back to database.
"""

import numpy as np
import logging
from typing import Optional
from ..common.database import DatabaseConnection

logger = logging.getLogger(__name__)


def write_tilt_link_hr_data(
    conn: DatabaseConnection,
    control_unit_id: str,
    chain: str,
    x_global: np.ndarray,
    y_global: np.ndarray,
    z_global: np.ndarray,
    x_local: np.ndarray,
    y_local: np.ndarray,
    z_local: np.ndarray,
    temperature: np.ndarray,
    timestamps: np.ndarray,
    errors: Optional[np.ndarray] = None
) -> None:
    """
    Write Tilt Link HR elaborated data to database.

    Converts MATLAB DBwriteTLHR.m function.

    Args:
        conn: Database connection
        control_unit_id: Control unit identifier
        chain: Chain identifier
        x_global: X displacement in global coordinates
        y_global: Y displacement in global coordinates
        z_global: Z displacement in global coordinates
        x_local: X displacement in local coordinates
        y_local: Y displacement in local coordinates
        z_local: Z displacement in local coordinates
        temperature: Temperature data
        timestamps: Timestamp array
        errors: Error flags (optional)
    """
    logger.info("Writing Tilt Link HR data to database")

    query = """
        INSERT INTO elaborated_tlhr_data
        (IDcentralina, DTcatena, timestamp, nodeID,
         X_global, Y_global, Z_global,
         X_local, Y_local, Z_local,
         temperature, error_flag)
        VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
        ON DUPLICATE KEY UPDATE
        X_global = VALUES(X_global),
        Y_global = VALUES(Y_global),
        Z_global = VALUES(Z_global),
        X_local = VALUES(X_local),
        Y_local = VALUES(Y_local),
        Z_local = VALUES(Z_local),
        temperature = VALUES(temperature),
        error_flag = VALUES(error_flag)
    """

    n_timestamps, n_sensors = x_global.shape
    data_rows = []

    for t in range(n_timestamps):
        for s in range(n_sensors):
            error_flag = 0
            if errors is not None and s < errors.shape[1]:
                error_flag = int(errors[s, t])

            data_rows.append((
                control_unit_id,
                chain,
                timestamps[t],
                s + 1,
                float(x_global[t, s]),
                float(y_global[t, s]),
                float(z_global[t, s]),
                float(x_local[t, s]),
                float(y_local[t, s]),
                float(z_local[t, s]),
                float(temperature[t, s]),
                error_flag
            ))

    if data_rows:
        conn.execute_many(query, data_rows)
        logger.info(f"Wrote {len(data_rows)} Tilt Link HR records")


def write_tilt_link_data(
    conn: DatabaseConnection,
    control_unit_id: str,
    chain: str,
    x_disp: np.ndarray,
    y_disp: np.ndarray,
    z_disp: np.ndarray,
    temperature: np.ndarray,
    timestamps: np.ndarray,
    errors: Optional[np.ndarray] = None
) -> None:
    """
    Write Tilt Link elaborated data to database.

    Converts MATLAB DBwriteTL.m function.
    """
    logger.info("Writing Tilt Link data to database")

    query = """
        INSERT INTO elaborated_tl_data
        (IDcentralina, DTcatena, timestamp, nodeID,
         X_displacement, Y_displacement, Z_displacement,
         temperature, error_flag)
        VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
        ON DUPLICATE KEY UPDATE
        X_displacement = VALUES(X_displacement),
        Y_displacement = VALUES(Y_displacement),
        Z_displacement = VALUES(Z_displacement),
        temperature = VALUES(temperature),
        error_flag = VALUES(error_flag)
    """

    n_timestamps, n_sensors = x_disp.shape
    data_rows = []

    for t in range(n_timestamps):
        for s in range(n_sensors):
            error_flag = 0
            if errors is not None:
                error_flag = int(errors[s, t]) if s < errors.shape[1] else 0

            data_rows.append((
                control_unit_id,
                chain,
                timestamps[t],
                s + 1,
                float(x_disp[t, s]),
                float(y_disp[t, s]),
                float(z_disp[t, s]),
                float(temperature[t, s]),
                error_flag
            ))

    if data_rows:
        conn.execute_many(query, data_rows)
        logger.info(f"Wrote {len(data_rows)} Tilt Link records")


def write_biaxial_link_data(
    conn: DatabaseConnection,
    control_unit_id: str,
    chain: str,
    x_disp: np.ndarray,
    y_disp: np.ndarray,
    z_disp: np.ndarray,
    temperature: np.ndarray,
    timestamps: np.ndarray,
    errors: Optional[np.ndarray] = None
) -> None:
    """
    Write Biaxial Link elaborated data to database.

    Converts MATLAB DBwriteBL.m function.
    """
    logger.info("Writing Biaxial Link data to database")

    query = """
        INSERT INTO elaborated_bl_data
        (IDcentralina, DTcatena, timestamp, nodeID,
         X_displacement, Y_displacement, Z_displacement,
         temperature, error_flag)
        VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
        ON DUPLICATE KEY UPDATE
        X_displacement = VALUES(X_displacement),
        Y_displacement = VALUES(Y_displacement),
        Z_displacement = VALUES(Z_displacement),
        temperature = VALUES(temperature),
        error_flag = VALUES(error_flag)
    """

    n_timestamps, n_sensors = x_disp.shape
    data_rows = []

    for t in range(n_timestamps):
        for s in range(n_sensors):
            error_flag = 0
            if errors is not None:
                error_flag = int(errors[s, t]) if s < errors.shape[1] else 0

            data_rows.append((
                control_unit_id,
                chain,
                timestamps[t],
                s + 1,
                float(x_disp[t, s]),
                float(y_disp[t, s]),
                float(z_disp[t, s]),
                float(temperature[t, s]),
                error_flag
            ))

    if data_rows:
        conn.execute_many(query, data_rows)
        logger.info(f"Wrote {len(data_rows)} Biaxial Link records")


def write_pendulum_link_data(
    conn: DatabaseConnection,
    control_unit_id: str,
    chain: str,
    x_disp: np.ndarray,
    y_disp: np.ndarray,
    temperature: np.ndarray,
    timestamps: np.ndarray,
    errors: Optional[np.ndarray] = None
) -> None:
    """
    Write Pendulum Link elaborated data to database.

    Converts MATLAB DBwritePL.m function.
    """
    logger.info("Writing Pendulum Link data to database")

    query = """
        INSERT INTO elaborated_pl_data
        (IDcentralina, DTcatena, timestamp, nodeID,
         X_displacement, Y_displacement,
         temperature, error_flag)
        VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
        ON DUPLICATE KEY UPDATE
        X_displacement = VALUES(X_displacement),
        Y_displacement = VALUES(Y_displacement),
        temperature = VALUES(temperature),
        error_flag = VALUES(error_flag)
    """

    n_timestamps, n_sensors = x_disp.shape
    data_rows = []

    for t in range(n_timestamps):
        for s in range(n_sensors):
            error_flag = 0
            if errors is not None:
                error_flag = int(errors[s, t]) if s < errors.shape[1] else 0

            data_rows.append((
                control_unit_id,
                chain,
                timestamps[t],
                s + 1,
                float(x_disp[t, s]),
                float(y_disp[t, s]),
                float(temperature[t, s]),
                error_flag
            ))

    if data_rows:
        conn.execute_many(query, data_rows)
        logger.info(f"Wrote {len(data_rows)} Pendulum Link records")


def write_kessler_link_data(
    conn: DatabaseConnection,
    control_unit_id: str,
    chain: str,
    x_disp: np.ndarray,
    y_disp: np.ndarray,
    temperature: np.ndarray,
    timestamps: np.ndarray,
    errors: Optional[np.ndarray] = None
) -> None:
    """
    Write Kessler Link elaborated data to database.

    Converts MATLAB DBwriteKLHR.m function.
    """
    logger.info("Writing Kessler Link data to database")

    query = """
        INSERT INTO elaborated_klhr_data
        (IDcentralina, DTcatena, timestamp, nodeID,
         X_displacement, Y_displacement,
         temperature, error_flag)
        VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
        ON DUPLICATE KEY UPDATE
        X_displacement = VALUES(X_displacement),
        Y_displacement = VALUES(Y_displacement),
        temperature = VALUES(temperature),
        error_flag = VALUES(error_flag)
    """

    n_timestamps, n_sensors = x_disp.shape
    data_rows = []

    for t in range(n_timestamps):
        for s in range(n_sensors):
            error_flag = 0
            if errors is not None:
                error_flag = int(errors[s, t]) if s < errors.shape[1] else 0

            data_rows.append((
                control_unit_id,
                chain,
                timestamps[t],
                s + 1,
                float(x_disp[t, s]),
                float(y_disp[t, s]),
                float(temperature[t, s]),
                error_flag
            ))

    if data_rows:
        conn.execute_many(query, data_rows)
        logger.info(f"Wrote {len(data_rows)} Kessler Link records")


def write_temperature_data(
    conn: DatabaseConnection,
    control_unit_id: str,
    chain: str,
    temperature: np.ndarray,
    timestamps: np.ndarray,
    sensor_type: str = "ThL"
) -> None:
    """
    Write temperature sensor data to database.

    For thermistors (ThL) or PT100 sensors.

    Args:
        conn: Database connection
        control_unit_id: Control unit identifier
        chain: Chain identifier
        temperature: Temperature data
        timestamps: Timestamp array
        sensor_type: Sensor type ("ThL" or "PT100")
    """
    logger.info(f"Writing {sensor_type} temperature data to database")

    table_name = f"elaborated_{sensor_type.lower()}_data"

    query = f"""
        INSERT INTO {table_name}
        (IDcentralina, DTcatena, timestamp, nodeID, temperature)
        VALUES (%s, %s, %s, %s, %s)
        ON DUPLICATE KEY UPDATE
        temperature = VALUES(temperature)
    """

    n_timestamps, n_sensors = temperature.shape
    data_rows = []

    for t in range(n_timestamps):
        for s in range(n_sensors):
            data_rows.append((
                control_unit_id,
                chain,
                timestamps[t],
                s + 1,
                float(temperature[t, s])
            ))

    if data_rows:
        conn.execute_many(query, data_rows)
        logger.info(f"Wrote {len(data_rows)} {sensor_type} temperature records")
