import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
import mysql from 'mysql2/promise';
import { CreateLoginUserDto } from './dto/create-login-user.dto.js';
import { UpdateLoginUserDto } from './dto/update-login-user.dto.js';

@Injectable()
export class LoginUsersService implements OnModuleInit, OnModuleDestroy {
  private pool: mysql.Pool;

  constructor() {
    this.pool = mysql.createPool({
      host: process.env.DB_HOST || '127.0.0.1',
      port: parseInt(process.env.DB_PORT || '3306', 10),
      user: process.env.DB_USERNAME || 'root',
      password: process.env.DB_PASSWORD || '',
      database: process.env.DB_DATABASE || 'ninjasage',
      waitForConnections: true,
      connectionLimit: 10,
      queueLimit: 0,
    });
  }

  async onModuleInit() {
    // Optional: Test connection
    try {
      const conn = await this.pool.getConnection();
      conn.release();
    } catch (e) {
      console.error('Failed to connect to MySQL from NestJS:', e);
    }
  }

  async onModuleDestroy() {
    await this.pool.end();
  }

  async findAll() {
    const [rows] = await this.pool.query('SELECT * FROM ninja_sage_login_users ORDER BY sort_order ASC, id DESC');
    return rows;
  }

  async findOne(id: number) {
    const [rows] = await this.pool.query('SELECT * FROM ninja_sage_login_users WHERE id = ?', [id]);
    const users = rows as any[];
    return users.length > 0 ? users[0] : null;
  }

  async create(createLoginUserDto: CreateLoginUserDto) {
    const {
      username,
      password_hash,
      auth_token,
      auth_signature,
      auth_device_id,
      note,
      sort_order,
      is_active,
    } = createLoginUserDto;

    const [result] = await this.pool.execute(
      `INSERT INTO ninja_sage_login_users 
      (username, password_hash_hash, auth_token, auth_signature, auth_device_id, note, sort_order, is_active, created_at, updated_at) 
      VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())`,
      [
        username,
        // Assuming password_hash is stored in password_hash_hash (SHA256) as per Laravel controller
        // However, Laravel controller does: 'password_hash_hash' => hash('sha256', $passwordHash)
        // I should replicate that logic or just store raw if that's what's expected.
        // Laravel controller:
        // 'password_hash_hash' => $passwordHash !== '' ? hash('sha256', $passwordHash) : null,
        // 'password_hash_enc' => $passwordHash !== '' ? Crypt::encryptString($passwordHash) : null,
        // This is complex to replicate in NestJS without the APP_KEY.
        // For now, I will store the SHA256 hash in password_hash_hash.
        // Encryption (password_hash_enc) requires Laravel's APP_KEY and algorithm.
        // I will SKIP password_hash_enc for now or store null, and note it.
        // Or I can just store the raw hash provided if the user provided a pre-hashed value?
        // The DTO says "password_hash", likely the raw string "spA+..."
        require('crypto').createHash('sha256').update(password_hash).digest('hex'),
        auth_token || null,
        auth_signature || null,
        auth_device_id || null,
        note || null,
        sort_order || null,
        is_active ?? true,
      ]
    );
    const insertId = (result as any).insertId;
    return this.findOne(insertId);
  }

  async update(id: number, updateLoginUserDto: UpdateLoginUserDto) {
    // Dynamic update query
    const fields: string[] = [];
    const values: any[] = [];

    if (updateLoginUserDto.username !== undefined) {
      fields.push('username = ?');
      values.push(updateLoginUserDto.username);
    }
    if (updateLoginUserDto.password_hash !== undefined) {
        // Same logic as create
        fields.push('password_hash_hash = ?');
        values.push(require('crypto').createHash('sha256').update(updateLoginUserDto.password_hash).digest('hex'));
    }
    if (updateLoginUserDto.auth_token !== undefined) {
      fields.push('auth_token = ?');
      values.push(updateLoginUserDto.auth_token || null);
    }
    if (updateLoginUserDto.auth_signature !== undefined) {
      fields.push('auth_signature = ?');
      values.push(updateLoginUserDto.auth_signature || null);
    }
    if (updateLoginUserDto.auth_device_id !== undefined) {
      fields.push('auth_device_id = ?');
      values.push(updateLoginUserDto.auth_device_id || null);
    }
    if (updateLoginUserDto.note !== undefined) {
      fields.push('note = ?');
      values.push(updateLoginUserDto.note || null);
    }
    if (updateLoginUserDto.sort_order !== undefined) {
      fields.push('sort_order = ?');
      values.push(updateLoginUserDto.sort_order || null);
    }
    if (updateLoginUserDto.is_active !== undefined) {
      fields.push('is_active = ?');
      values.push(updateLoginUserDto.is_active);
    }

    if (fields.length === 0) return this.findOne(id);

    fields.push('updated_at = NOW()');
    
    const query = `UPDATE ninja_sage_login_users SET ${fields.join(', ')} WHERE id = ?`;
    values.push(id);

    await this.pool.execute(query, values);
    return this.findOne(id);
  }

  async remove(id: number) {
    await this.pool.execute('DELETE FROM ninja_sage_login_users WHERE id = ?', [id]);
    return { deleted: true };
  }
}
