import pool from '../config/database';
import logger from '../utils/logger';

class AusruestungTypService {
  async getAll() {
    try {
      const result = await pool.query(
        `SELECT * FROM ausruestung_typen ORDER BY name ASC`
      );
      return result.rows;
    } catch (error) {
      logger.error('AusruestungTypService.getAll failed', { error });
      throw new Error('Ausrüstungs-Typen konnten nicht geladen werden');
    }
  }

  async getById(id: number) {
    try {
      const result = await pool.query(
        `SELECT * FROM ausruestung_typen WHERE id = $1`,
        [id]
      );
      return result.rows[0] || null;
    } catch (error) {
      logger.error('AusruestungTypService.getById failed', { error, id });
      throw new Error('Ausrüstungs-Typ konnte nicht geladen werden');
    }
  }

  async create(data: { name: string; beschreibung?: string; icon?: string }) {
    try {
      const result = await pool.query(
        `INSERT INTO ausruestung_typen (name, beschreibung, icon)
         VALUES ($1, $2, $3)
         RETURNING *`,
        [data.name, data.beschreibung ?? null, data.icon ?? null]
      );
      return result.rows[0];
    } catch (error) {
      logger.error('AusruestungTypService.create failed', { error });
      throw new Error('Ausrüstungs-Typ konnte nicht erstellt werden');
    }
  }

  async update(id: number, data: { name?: string; beschreibung?: string; icon?: string }) {
    try {
      const setClauses: string[] = [];
      const values: any[] = [];
      let idx = 1;

      if (data.name !== undefined) {
        setClauses.push(`name = $${idx}`);
        values.push(data.name);
        idx++;
      }
      if (data.beschreibung !== undefined) {
        setClauses.push(`beschreibung = $${idx}`);
        values.push(data.beschreibung);
        idx++;
      }
      if (data.icon !== undefined) {
        setClauses.push(`icon = $${idx}`);
        values.push(data.icon);
        idx++;
      }

      if (setClauses.length === 0) {
        return this.getById(id);
      }

      values.push(id);
      const result = await pool.query(
        `UPDATE ausruestung_typen SET ${setClauses.join(', ')} WHERE id = $${idx} RETURNING *`,
        values
      );
      return result.rows[0] || null;
    } catch (error) {
      logger.error('AusruestungTypService.update failed', { error, id });
      throw new Error('Ausrüstungs-Typ konnte nicht aktualisiert werden');
    }
  }

  async delete(id: number) {
    try {
      // Check if any equipment uses this type
      const usage = await pool.query(
        `SELECT COUNT(*) FROM ausruestung_ausruestung_typen WHERE ausruestung_typ_id = $1`,
        [id]
      );
      if (parseInt(usage.rows[0].count, 10) > 0) {
        throw new Error('Typ wird noch von Ausrüstung verwendet');
      }

      const result = await pool.query(
        `DELETE FROM ausruestung_typen WHERE id = $1 RETURNING *`,
        [id]
      );
      return result.rows[0] || null;
    } catch (error) {
      logger.error('AusruestungTypService.delete failed', { error, id });
      throw error;
    }
  }

  async getTypesForEquipment(ausruestungId: string) {
    try {
      const result = await pool.query(
        `SELECT at.* FROM ausruestung_typen at
         JOIN ausruestung_ausruestung_typen aat ON aat.ausruestung_typ_id = at.id
         WHERE aat.ausruestung_id = $1
         ORDER BY at.name ASC`,
        [ausruestungId]
      );
      return result.rows;
    } catch (error) {
      logger.error('AusruestungTypService.getTypesForEquipment failed', { error, ausruestungId });
      throw new Error('Ausrüstungs-Typen konnten nicht geladen werden');
    }
  }

  async setTypesForEquipment(ausruestungId: string, typIds: number[]) {
    const client = await pool.connect();
    try {
      await client.query('BEGIN');

      await client.query(
        `DELETE FROM ausruestung_ausruestung_typen WHERE ausruestung_id = $1`,
        [ausruestungId]
      );

      for (const typId of typIds) {
        await client.query(
          `INSERT INTO ausruestung_ausruestung_typen (ausruestung_id, ausruestung_typ_id) VALUES ($1, $2)`,
          [ausruestungId, typId]
        );
      }

      await client.query('COMMIT');

      return this.getTypesForEquipment(ausruestungId);
    } catch (error) {
      await client.query('ROLLBACK').catch(() => {});
      logger.error('AusruestungTypService.setTypesForEquipment failed', { error, ausruestungId });
      throw new Error('Ausrüstungs-Typen konnten nicht gesetzt werden');
    } finally {
      client.release();
    }
  }
}

export default new AusruestungTypService();
