<?php
namespace nur\sery\db\_private;

use nur\sery\cl;
use nur\sery\ValueException;

trait Tinsert {
  static function isa(string $sql): bool {
    return preg_match("/^insert\b/i", $sql);
  }

  /**
   * parser une chaine de la forme
   * "insert [into] [TABLE] [(COLS)] [values (VALUES)]"
   */
  static function parse(array $query, ?array &$bindings=null): string {
    # fusionner d'abord toutes les parties séquentielles
    $usersql = $tmpsql = self::merge_seq($query);

    ### vérifier la présence des parties nécessaires
    $sql = [];
    if (($prefix = $query["prefix"] ?? null) !== null) $sql[] = $prefix;

    ## insert
    self::consume('(insert(?:\s+or\s+(?:ignore|replace))?)\s*', $tmpsql, $ms);
    $sql[] = $ms[1];

    ## into
    self::consume('into\s*', $tmpsql);
    $sql[] = "into";
    $into = $query["into"] ?? null;
    if (self::consume('([a-z_][a-z0-9_]*)\s*', $tmpsql, $ms)) {
      if ($into === null) $into = $ms[1];
      $sql[] = $into;
    } elseif ($into !== null) {
      $sql[] = $into;
    } else {
      throw new ValueException("expected table name: $usersql");
    }

    ## cols & values
    $usercols = [];
    $uservalues = [];
    if (self::consume('\(([^)]*)\)\s*', $tmpsql, $ms)) {
      $usercols = array_merge($usercols, preg_split("/\s*,\s*/", $ms[1]));
    }
    $cols = cl::withn($query["cols"] ?? null);
    $values = cl::withn($query["values"] ?? null);
    $schema = $query["schema"] ?? null;
    if ($cols === null) {
      if ($usercols) {
        $cols = $usercols;
      } elseif ($values) {
        $cols = array_keys($values);
        $usercols = array_merge($usercols, $cols);
      } elseif ($schema && is_array($schema)) {
        #XXX implémenter support AssocSchema
        $cols = array_keys($schema);
        $usercols = array_merge($usercols, $cols);
      }
    }
    if (self::consume('values\s+\(\s*(.*)\s*\)\s*', $tmpsql, $ms)) {
      if ($ms[1]) $uservalues[] = $ms[1];
    }
    if ($cols !== null && !$uservalues) {
      if (!$usercols) $usercols = $cols;
      foreach ($cols as $col) {
        $uservalues[] = ":$col";
        $bindings[$col] = $values[$col] ?? null;
      }
    }
    $sql[] = "(" . implode(", ", $usercols) . ")";
    $sql[] = "values (" . implode(", ", $uservalues) . ")";

    ## suffixe
    if (($suffix = $query["suffix"] ?? null) !== null) $sql[] = $suffix;

    ## fin de la requête
    self::check_eof($tmpsql, $usersql);
    return implode(" ", $sql);
  }
}
