from tablesqlite import SQLTableInfo
from ...query import (InsertQuery, INSERT, OnConflictQuery,
)
from ...types import SQLCol, SQLInput
from typing import Union, Dict, Tuple, List, Any


def insert_query_for(table: SQLTableInfo, *items: Union[Dict, Tuple[str, Any]],
                    or_action: str = None,
                    on_conflict: OnConflictQuery = None,
                    returning: List[SQLCol] = None,
                    if_column_exists: bool = True, resolve_by: str = "raise", **kwargs) -> InsertQuery:
    set_columns = kwargs
    set_columns_in_self = {key: value for key, value in set_columns.items() if key in table.column_dict}
    for item in items:
        if isinstance(item, dict):
            set_columns_in_self.update({key: value for key, value in item.items() if key in table.column_dict})
            set_columns.update(item)
        elif isinstance(item, tuple) and len(item) == 2 and isinstance(item[0], str):
            set_columns[item[0]] = item[1]
            if item[0] in table.column_dict:
                set_columns_in_self[item[0]] = item[1]
        else:
            raise ValueError(f"Invalid item format: {item}. Expected dict or (str, any) tuple.")
    if if_column_exists and set_columns != set_columns_in_self:
        if resolve_by.lower() == "raise":
            raise ValueError("If 'if_column_exists' is True, all provided columns must exist in the table.")
        elif resolve_by.lower() == "ignore":
            set_columns = set_columns_in_self
    if not set_columns:
        raise ValueError("No valid columns provided for insertion.")
    returning = returning or []
    iq: InsertQuery = INSERT().INTO(table.name).SET(set_columns).RETURNING(*returning)
    if on_conflict is not None:
        iq = iq.ON_CONFLICT(do=on_conflict.do_what,
                            conflict_cols=on_conflict.conflict_cols,
                            set=on_conflict.set_clauses,
                            where=on_conflict.condition)
    iq.or_action = or_action
    return iq

def insert_query(self:SQLTableInfo, *items:Union[Dict,Tuple[str,Any]],
                or_action: str = None,
                on_conflict:OnConflictQuery=None,
                returning: List[SQLCol] = None,
                if_column_exists = True, resolve_by:str = "raise", **kwargs) -> InsertQuery:
        """
        Create an INSERT query for the table with the provided data.
        """
        return insert_query_for(
            self,
            *items,
            or_action=or_action,
            on_conflict=on_conflict,
            returning=returning,
            if_column_exists=if_column_exists,
            resolve_by=resolve_by,
            **kwargs
        )
