"""
Database writing functions for RSN processed data.

Writes elaborated 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_rsn_database(
    conn: DatabaseConnection,
    chain_schema: list,
    control_unit_id: str,
    chain: str,
    alpha_x_rsn: Optional[np.ndarray],
    alpha_y_rsn: Optional[np.ndarray],
    temp_rsn: Optional[np.ndarray],
    timestamps_rsn: Optional[np.ndarray],
    errors_rsn: Optional[np.ndarray],
    alpha_x_rsn_hr: Optional[np.ndarray],
    alpha_y_rsn_hr: Optional[np.ndarray],
    temp_rsn_hr: Optional[np.ndarray],
    timestamps_rsn_hr: Optional[np.ndarray],
    errors_rsn_hr: Optional[np.ndarray],
    load_data: Optional[np.ndarray],
    errors_ll: Optional[np.ndarray],
    timestamps_ll: Optional[np.ndarray]
) -> None:
    """
    Write processed data to database.

    Converts MATLAB database_write.m and DBwrite*.m functions.

    Args:
        conn: Database connection
        chain_schema: Chain node schema
        control_unit_id: Control unit identifier
        chain: Chain identifier
        alpha_x_rsn: RSN alpha X displacements
        alpha_y_rsn: RSN alpha Y displacements
        temp_rsn: RSN temperatures
        timestamps_rsn: RSN timestamps
        errors_rsn: RSN error flags
        alpha_x_rsn_hr: RSN HR alpha X displacements
        alpha_y_rsn_hr: RSN HR alpha Y displacements
        temp_rsn_hr: RSN HR temperatures
        timestamps_rsn_hr: RSN HR timestamps
        errors_rsn_hr: RSN HR error flags
        load_data: Load Link data
        errors_ll: Load Link error flags
        timestamps_ll: Load Link timestamps
    """
    logger.info("Writing processed data to database")

    # Write RSN Link data
    if alpha_x_rsn is not None:
        write_rsn_link_data(
            conn, control_unit_id, chain,
            alpha_x_rsn, alpha_y_rsn, temp_rsn,
            timestamps_rsn, errors_rsn
        )

    # Write RSN HR data
    if alpha_x_rsn_hr is not None:
        write_rsn_hr_data(
            conn, control_unit_id, chain,
            alpha_x_rsn_hr, alpha_y_rsn_hr, temp_rsn_hr,
            timestamps_rsn_hr, errors_rsn_hr
        )

    # Write Load Link data
    if load_data is not None:
        write_load_link_data(
            conn, control_unit_id, chain,
            load_data, timestamps_ll, errors_ll
        )

    logger.info("Database write completed")


def write_rsn_link_data(
    conn: DatabaseConnection,
    control_unit_id: str,
    chain: str,
    alpha_x: np.ndarray,
    alpha_y: np.ndarray,
    temperature: np.ndarray,
    timestamps: np.ndarray,
    errors: np.ndarray
) -> None:
    """
    Write RSN Link elaborated data.

    Converts MATLAB DBwriteRSN.m function.
    """
    query = """
        INSERT INTO elaborated_rsn_data
        (IDcentralina, DTcatena, timestamp, nodeID, alphaX, alphaY, temperature, error_flag)
        VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
        ON DUPLICATE KEY UPDATE
        alphaX = VALUES(alphaX),
        alphaY = VALUES(alphaY),
        temperature = VALUES(temperature),
        error_flag = VALUES(error_flag)
    """

    n_timestamps, n_sensors = alpha_x.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,  # Node ID
                float(alpha_x[t, s]),
                float(alpha_y[t, s]),
                float(temperature[t, s]),
                int(errors[s, t])
            ))

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


def write_rsn_hr_data(
    conn: DatabaseConnection,
    control_unit_id: str,
    chain: str,
    alpha_x: np.ndarray,
    alpha_y: np.ndarray,
    temperature: np.ndarray,
    timestamps: np.ndarray,
    errors: np.ndarray
) -> None:
    """
    Write RSN HR elaborated data.

    Converts MATLAB DBwriteRSNHR.m function.
    """
    query = """
        INSERT INTO elaborated_rsnhr_data
        (IDcentralina, DTcatena, timestamp, nodeID, alphaX, alphaY, temperature, error_flag)
        VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
        ON DUPLICATE KEY UPDATE
        alphaX = VALUES(alphaX),
        alphaY = VALUES(alphaY),
        temperature = VALUES(temperature),
        error_flag = VALUES(error_flag)
    """

    n_timestamps, n_sensors = alpha_x.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(alpha_x[t, s]),
                float(alpha_y[t, s]),
                float(temperature[t, s]),
                int(errors[s, t])
            ))

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


def write_load_link_data(
    conn: DatabaseConnection,
    control_unit_id: str,
    chain: str,
    load_data: np.ndarray,
    timestamps: np.ndarray,
    errors: np.ndarray
) -> None:
    """
    Write Load Link elaborated data.

    Converts MATLAB DBwriteLL.m function.
    """
    query = """
        INSERT INTO elaborated_loadlink_data
        (IDcentralina, DTcatena, timestamp, nodeID, load_value, error_flag)
        VALUES (%s, %s, %s, %s, %s, %s)
        ON DUPLICATE KEY UPDATE
        load_value = VALUES(load_value),
        error_flag = VALUES(error_flag)
    """

    n_timestamps, n_sensors = load_data.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(load_data[t, s]),
                int(errors[s, t])
            ))

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