import { User, CreateUserDto, UpdateUserDto } from '../models/User';
import { query, queryOne } from '../db/pool';

interface UserRow {
  id: number;
  name: string;
  email: string;
  created_at: Date;
}

function mapRowToUser(row: UserRow): User {
  return {
    id: row.id,
    name: row.name,
    email: row.email,
    createdAt: row.created_at,
  };
}

export const userRepository = {

  async findAll(): Promise<User[]> {
    const rows = await query<UserRow>('SELECT * FROM users ORDER BY id');
    return rows.map(mapRowToUser);
  },

  async findById(id: number): Promise<User | undefined> {
    const row = await queryOne<UserRow>('SELECT * FROM users WHERE id = $1', [id]);
    return row ? mapRowToUser(row) : undefined;
  },

  async create(dto: CreateUserDto): Promise<User> {
    const row = await queryOne<UserRow>(
      'INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *',
      [dto.name, dto.email],
    );
    return mapRowToUser(row!);
  },

  async update(id: number, dto: UpdateUserDto): Promise<User | undefined> {
    const sets: string[] = [];
    const params: unknown[] = [id];
    let i = 2;

    if (dto.name) {
      sets.push(`name = $${i++}`);
      params.push(dto.name);
    }
    if (dto.email) {
      sets.push(`email = $${i++}`);
      params.push(dto.email);
    }
    if (sets.length === 0) return this.findById(id);

    const row = await queryOne<UserRow>(
      `UPDATE users SET ${sets.join(', ')} WHERE id = $1 RETURNING *`,
      params,
    );
    return row ? mapRowToUser(row) : undefined;
  },

  async delete(id: number): Promise<boolean> {
    const row = await queryOne<{ id: number }>(
      'DELETE FROM users WHERE id = $1 RETURNING id',
      [id],
    );
    return row !== undefined;
  },

};
