/**
 * Supabase-like wrapper for direct PostgreSQL
 * Provides similar API to @supabase/supabase-js but uses pg pool directly
 */
const { pool } = require('./database');

class QueryBuilder {
  constructor(tableName) {
    this.tableName = tableName;
    this._select = '*';
    this._where = [];
    this._whereParams = [];
    this._orderBy = null;
    this._limit = null;
    this._offset = null;
    this._single = false;
    this._returning = true;
    this._count = false;
  }

  select(columns, options = {}) {
    if (typeof columns === 'string') {
      this._select = columns || '*';
    } else {
      this._select = '*';
    }
    if (options && options.count === 'exact') {
      this._count = true;
    }
    return this;
  }

  eq(column, value) {
    this._where.push(`"${column}" = $${this._whereParams.length + 1}`);
    this._whereParams.push(value);
    return this;
  }

  neq(column, value) {
    this._where.push(`"${column}" != $${this._whereParams.length + 1}`);
    this._whereParams.push(value);
    return this;
  }

  gt(column, value) {
    this._where.push(`"${column}" > $${this._whereParams.length + 1}`);
    this._whereParams.push(value);
    return this;
  }

  gte(column, value) {
    this._where.push(`"${column}" >= $${this._whereParams.length + 1}`);
    this._whereParams.push(value);
    return this;
  }

  lt(column, value) {
    this._where.push(`"${column}" < $${this._whereParams.length + 1}`);
    this._whereParams.push(value);
    return this;
  }

  lte(column, value) {
    this._where.push(`"${column}" <= $${this._whereParams.length + 1}`);
    this._whereParams.push(value);
    return this;
  }

  is(column, value) {
    if (value === null) {
      this._where.push(`"${column}" IS NULL`);
    } else {
      this._where.push(`"${column}" IS $${this._whereParams.length + 1}`);
      this._whereParams.push(value);
    }
    return this;
  }

  in(column, values) {
    const placeholders = values.map((_, i) => `$${this._whereParams.length + i + 1}`).join(', ');
    this._where.push(`"${column}" IN (${placeholders})`);
    this._whereParams.push(...values);
    return this;
  }

  order(column, options = {}) {
    const direction = options.ascending === false ? 'DESC' : 'ASC';
    this._orderBy = `"${column}" ${direction}`;
    return this;
  }

  limit(count) {
    this._limit = count;
    return this;
  }

  range(from, to) {
    this._offset = from;
    this._limit = to - from + 1;
    return this;
  }

  single() {
    this._single = true;
    this._limit = 1;
    return this;
  }

  async _buildSelectQuery() {
    let query = `SELECT ${this._select} FROM "${this.tableName}"`;

    if (this._where.length > 0) {
      query += ` WHERE ${this._where.join(' AND ')}`;
    }

    if (this._orderBy) {
      query += ` ORDER BY ${this._orderBy}`;
    }

    if (this._limit) {
      query += ` LIMIT ${this._limit}`;
    }

    if (this._offset) {
      query += ` OFFSET ${this._offset}`;
    }

    return query;
  }

  async _buildCountQuery() {
    let query = `SELECT COUNT(*) as count FROM "${this.tableName}"`;

    if (this._where.length > 0) {
      query += ` WHERE ${this._where.join(' AND ')}`;
    }

    return query;
  }

  async then(resolve, reject) {
    try {
      const query = await this._buildSelectQuery();
      const result = await pool.query(query, this._whereParams);

      let count = null;
      if (this._count) {
        const countQuery = await this._buildCountQuery();
        const countResult = await pool.query(countQuery, this._whereParams);
        count = parseInt(countResult.rows[0]?.count || 0);
      }

      if (this._single) {
        if (result.rows.length === 0) {
          resolve({ data: null, error: { code: 'PGRST116', message: 'No rows returned' }, count });
        } else {
          resolve({ data: result.rows[0], error: null, count });
        }
      } else {
        resolve({ data: result.rows, error: null, count });
      }
    } catch (error) {
      resolve({ data: null, error: { code: error.code, message: error.message, details: error.detail, hint: error.hint }, count: null });
    }
  }
}

class InsertBuilder {
  constructor(tableName, data) {
    this.tableName = tableName;
    this.data = Array.isArray(data) ? data : [data];
    this._select = null;
    this._single = false;
  }

  select(columns) {
    this._select = columns || '*';
    return this;
  }

  single() {
    this._single = true;
    return this;
  }

  async then(resolve, reject) {
    try {
      const record = this.data[0];
      const columns = Object.keys(record);
      const values = Object.values(record);
      const placeholders = columns.map((_, i) => `$${i + 1}`).join(', ');

      let query = `INSERT INTO "${this.tableName}" ("${columns.join('", "')}") VALUES (${placeholders})`;

      if (this._select) {
        query += ` RETURNING ${this._select}`;
      } else {
        query += ' RETURNING *';
      }

      const result = await pool.query(query, values);

      if (this._single) {
        resolve({ data: result.rows[0] || null, error: null });
      } else {
        resolve({ data: result.rows, error: null });
      }
    } catch (error) {
      resolve({ data: null, error: { code: error.code, message: error.message, details: error.detail, hint: error.hint } });
    }
  }
}

class UpdateBuilder {
  constructor(tableName, data) {
    this.tableName = tableName;
    this.data = data;
    this._where = [];
    this._whereParams = [];
    this._select = null;
    this._single = false;
  }

  eq(column, value) {
    this._where.push({ column, value });
    return this;
  }

  select(columns) {
    this._select = columns || '*';
    return this;
  }

  single() {
    this._single = true;
    return this;
  }

  async then(resolve, reject) {
    try {
      const columns = Object.keys(this.data);
      const values = Object.values(this.data);

      const setClause = columns.map((col, i) => `"${col}" = $${i + 1}`).join(', ');

      let paramIndex = columns.length + 1;
      const whereClause = this._where.map(w => {
        values.push(w.value);
        return `"${w.column}" = $${paramIndex++}`;
      }).join(' AND ');

      let query = `UPDATE "${this.tableName}" SET ${setClause}`;
      if (whereClause) {
        query += ` WHERE ${whereClause}`;
      }

      if (this._select) {
        query += ` RETURNING ${this._select}`;
      } else {
        query += ' RETURNING *';
      }

      const result = await pool.query(query, values);

      if (this._single) {
        resolve({ data: result.rows[0] || null, error: null });
      } else {
        resolve({ data: result.rows, error: null });
      }
    } catch (error) {
      resolve({ data: null, error: { code: error.code, message: error.message, details: error.detail, hint: error.hint } });
    }
  }
}

class UpsertBuilder {
  constructor(tableName, data, options = {}) {
    this.tableName = tableName;
    this.data = Array.isArray(data) ? data : [data];
    this.onConflict = options.onConflict;
    this._select = null;
    this._single = false;
  }

  select(columns) {
    this._select = columns || '*';
    return this;
  }

  single() {
    this._single = true;
    return this;
  }

  async then(resolve, reject) {
    try {
      const record = this.data[0];
      const columns = Object.keys(record);
      const values = Object.values(record);
      const placeholders = columns.map((_, i) => `$${i + 1}`).join(', ');

      const updateClause = columns
        .filter(col => col !== this.onConflict)
        .map(col => `"${col}" = EXCLUDED."${col}"`)
        .join(', ');

      let query = `INSERT INTO "${this.tableName}" ("${columns.join('", "')}") VALUES (${placeholders})`;
      query += ` ON CONFLICT ("${this.onConflict}") DO UPDATE SET ${updateClause}`;
      query += ' RETURNING *';

      const result = await pool.query(query, values);

      if (this._single) {
        resolve({ data: result.rows[0] || null, error: null });
      } else {
        resolve({ data: result.rows, error: null });
      }
    } catch (error) {
      resolve({ data: null, error: { code: error.code, message: error.message, details: error.detail, hint: error.hint } });
    }
  }
}

class DeleteBuilder {
  constructor(tableName) {
    this.tableName = tableName;
    this._where = [];
    this._whereParams = [];
  }

  eq(column, value) {
    this._where.push(`"${column}" = $${this._whereParams.length + 1}`);
    this._whereParams.push(value);
    return this;
  }

  is(column, value) {
    if (value === null) {
      this._where.push(`"${column}" IS NULL`);
    }
    return this;
  }

  async then(resolve, reject) {
    try {
      let query = `DELETE FROM "${this.tableName}"`;

      if (this._where.length > 0) {
        query += ` WHERE ${this._where.join(' AND ')}`;
      }

      const result = await pool.query(query, this._whereParams);
      resolve({ data: null, error: null, count: result.rowCount });
    } catch (error) {
      resolve({ data: null, error: { code: error.code, message: error.message, details: error.detail, hint: error.hint } });
    }
  }
}

class TableClient {
  constructor(tableName) {
    this.tableName = tableName;
  }

  select(columns) {
    const builder = new QueryBuilder(this.tableName);
    return builder.select(columns);
  }

  insert(data) {
    return new InsertBuilder(this.tableName, data);
  }

  update(data) {
    return new UpdateBuilder(this.tableName, data);
  }

  upsert(data, options) {
    return new UpsertBuilder(this.tableName, data, options);
  }

  delete() {
    return new DeleteBuilder(this.tableName);
  }
}

// Supabase-compatible client
const supabase = {
  from: (tableName) => new TableClient(tableName)
};

module.exports = { supabase };
