import { MigrationInterface, QueryRunner, Table } from "typeorm";

export class CreateTallerParametros1780700000000 implements MigrationInterface {
  name = "CreateTallerParametros1780700000000";

  public async up(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.createTable(
      new Table({
        name: "taller_parametros",
        columns: [
          { name: "id", type: "int", isPrimary: true, isGenerated: true, generationStrategy: "increment" },
          { name: "clave", type: "varchar", length: "100" },
          { name: "ambito", type: "enum", enum: ["tenant", "tienda"] },
          { name: "tienda_id", type: "int", default: 0 },
          { name: "destino", type: "varchar", length: "32", default: "''" },
          { name: "tipo_dato", type: "enum", enum: ["boolean", "string", "number", "json"] },
          { name: "valor", type: "text", isNullable: true },
          { name: "valor_cifrado", type: "text", isNullable: true },
          { name: "created_at", type: "timestamp", default: "CURRENT_TIMESTAMP" },
          {
            name: "updated_at",
            type: "timestamp",
            default: "CURRENT_TIMESTAMP",
            onUpdate: "CURRENT_TIMESTAMP",
          },
        ],
        uniques: [
          { name: "UQ_taller_parametros_clave_tienda_destino", columnNames: ["clave", "tienda_id", "destino"] },
        ],
      }),
      true,
    );

    await queryRunner.createTable(
      new Table({
        name: "taller_parametros_historial",
        columns: [
          { name: "id", type: "int", isPrimary: true, isGenerated: true, generationStrategy: "increment" },
          { name: "clave", type: "varchar", length: "100" },
          { name: "ambito", type: "enum", enum: ["tenant", "tienda"] },
          { name: "tienda_id", type: "int", default: 0 },
          { name: "destino", type: "varchar", length: "32", default: "''" },
          { name: "valor_anterior", type: "text", isNullable: true },
          { name: "valor_nuevo", type: "text", isNullable: true },
          { name: "usuario_id", type: "int" },
          { name: "created_at", type: "timestamp", default: "CURRENT_TIMESTAMP" },
        ],
      }),
      true,
    );

    await this.backfillFacturacionPos(queryRunner);
  }

  // Copia taller_facturacion_pos_* de maetie -> filas tienda-scope de
  // taller_parametros. Misma base, misma conexion: se copia tal cual, sin
  // descifrar la contraseña. INSERT IGNORE + UNIQUE(clave, tienda_id,
  // destino) hace esto seguro de reintentar. Si maetie todavia no tiene
  // esas columnas (tenant que nunca corrio AddTiendaFacturacionPosConfig),
  // el SELECT falla y se omite el backfill sin abortar la migracion --
  // la tabla nueva igual queda creada.
  private async backfillFacturacionPos(queryRunner: QueryRunner): Promise<void> {
    let filasMaetie: Array<Record<string, any>>;
    try {
      filasMaetie = await queryRunner.query(
        `SELECT tienda,
                taller_facturacion_pos_habilitada AS habilitada,
                taller_facturacion_pos_url AS url,
                taller_facturacion_pos_username AS username,
                taller_facturacion_pos_password_encrypted AS password_encrypted,
                taller_facturacion_pos_computadora AS computadora,
                taller_facturacion_pos_precio_decimales AS precio_decimales
         FROM maetie
         WHERE taller_facturacion_pos_habilitada = 1
            OR taller_facturacion_pos_url IS NOT NULL
            OR taller_facturacion_pos_username IS NOT NULL
            OR taller_facturacion_pos_password_encrypted IS NOT NULL
            OR taller_facturacion_pos_computadora IS NOT NULL
            OR taller_facturacion_pos_precio_decimales IS NOT NULL`,
      );
    } catch (error) {
      console.warn(`[CreateTallerParametros] backfillFacturacionPos: SELECT from maetie failed: ${error instanceof Error ? error.message : String(error)}`);
      return;
    }

    for (const t of filasMaetie) {
      const filas: Array<{ clave: string; tipo: string; valor: string | null; valorCifrado: string | null }> = [
        { clave: "facturacion_pos.habilitada", tipo: "boolean", valor: t.habilitada ? "true" : "false", valorCifrado: null },
        { clave: "facturacion_pos.url", tipo: "string", valor: t.url, valorCifrado: null },
        { clave: "facturacion_pos.username", tipo: "string", valor: t.username, valorCifrado: null },
        { clave: "facturacion_pos.password", tipo: "string", valor: null, valorCifrado: t.password_encrypted },
        { clave: "facturacion_pos.computadora", tipo: "string", valor: t.computadora, valorCifrado: null },
        {
          clave: "facturacion_pos.precio_decimales",
          tipo: "number",
          valor: t.precio_decimales !== null && t.precio_decimales !== undefined ? String(t.precio_decimales) : null,
          valorCifrado: null,
        },
      ];

      for (const fila of filas) {
        if (fila.valor === null && fila.valorCifrado === null) continue;
        await queryRunner.query(
          `INSERT IGNORE INTO taller_parametros (clave, ambito, tienda_id, destino, tipo_dato, valor, valor_cifrado)
           VALUES (?, 'tienda', ?, '', ?, ?, ?)`,
          [fila.clave, t.tienda, fila.tipo, fila.valor, fila.valorCifrado],
        );
      }
    }
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.dropTable("taller_parametros_historial", true);
    await queryRunner.dropTable("taller_parametros", true);
  }
}
