import pool from '../config/database';
import logger from '../utils/logger';
import {
  AtemschutzTraeger,
  AtemschutzUebersicht,
  AtemschutzStats,
  CreateAtemschutzData,
  UpdateAtemschutzData,
} from '../models/atemschutz.model';

const ATEMSCHUTZ_PRIVILEGED = ['dashboard_admin', 'dashboard_kommando', 'dashboard_atemschutz', 'dashboard_moderator'];

class AtemschutzService {
  // =========================================================================
  // ÜBERSICHT (ALL RECORDS)
  // =========================================================================

  async getAll(userGroups: string[], userId: string): Promise<AtemschutzUebersicht[]> {
    const isPrivileged = userGroups.some(g => ATEMSCHUTZ_PRIVILEGED.includes(g));
    try {
      let result;
      if (isPrivileged) {
        result = await pool.query(`
          SELECT *
          FROM atemschutz_uebersicht
          WHERE mitglied_status IS NULL OR mitglied_status IN ('aktiv')
          ORDER BY user_family_name, user_given_name
        `);
      } else {
        result = await pool.query(`
          SELECT *
          FROM atemschutz_uebersicht
          WHERE user_id = $1
        `, [userId]);
      }

      return result.rows.map((row) => ({
        ...row,
        untersuchung_tage_rest: row.untersuchung_tage_rest != null
          ? parseInt(row.untersuchung_tage_rest, 10) : null,
        leistungstest_tage_rest: row.leistungstest_tage_rest != null
          ? parseInt(row.leistungstest_tage_rest, 10) : null,
      })) as AtemschutzUebersicht[];
    } catch (error) {
      logger.error('AtemschutzService.getAll fehlgeschlagen', { error });
      throw new Error('Atemschutzträger konnten nicht geladen werden');
    }
  }

  // =========================================================================
  // EINZELNER DATENSATZ (BY ID)
  // =========================================================================

  async getById(id: string): Promise<AtemschutzUebersicht | null> {
    try {
      const result = await pool.query(
        `SELECT * FROM atemschutz_uebersicht WHERE id = $1`,
        [id]
      );

      if (result.rows.length === 0) return null;

      const row = result.rows[0];
      return {
        ...row,
        untersuchung_tage_rest: row.untersuchung_tage_rest != null
          ? parseInt(row.untersuchung_tage_rest, 10) : null,
        leistungstest_tage_rest: row.leistungstest_tage_rest != null
          ? parseInt(row.leistungstest_tage_rest, 10) : null,
      } as AtemschutzUebersicht;
    } catch (error) {
      logger.error('AtemschutzService.getById fehlgeschlagen', { error, id });
      throw new Error('Atemschutzträger konnte nicht geladen werden');
    }
  }

  // =========================================================================
  // EINZELNER DATENSATZ (BY USER_ID)
  // =========================================================================

  async getByUserId(userId: string): Promise<AtemschutzUebersicht | null> {
    try {
      const result = await pool.query(
        `SELECT * FROM atemschutz_uebersicht WHERE user_id = $1`,
        [userId]
      );

      if (result.rows.length === 0) return null;

      const row = result.rows[0];
      return {
        ...row,
        untersuchung_tage_rest: row.untersuchung_tage_rest != null
          ? parseInt(row.untersuchung_tage_rest, 10) : null,
        leistungstest_tage_rest: row.leistungstest_tage_rest != null
          ? parseInt(row.leistungstest_tage_rest, 10) : null,
      } as AtemschutzUebersicht;
    } catch (error) {
      logger.error('AtemschutzService.getByUserId fehlgeschlagen', { error, userId });
      throw new Error('Atemschutzträger konnte nicht geladen werden');
    }
  }

  // =========================================================================
  // CREATE
  // =========================================================================

  async create(data: CreateAtemschutzData, createdBy: string): Promise<AtemschutzTraeger> {
    try {
      const result = await pool.query(
        `INSERT INTO atemschutz_traeger (
           id, user_id, atemschutz_lehrgang, lehrgang_datum,
           untersuchung_datum, untersuchung_gueltig_bis, untersuchung_ergebnis,
           leistungstest_datum, leistungstest_gueltig_bis, leistungstest_bestanden,
           bemerkung
         ) VALUES (uuid_generate_v4(),$1,$2,$3,$4,$5,$6,$7,$8,$9,$10)
         RETURNING *`,
        [
          data.user_id,
          data.atemschutz_lehrgang      ?? false,
          data.lehrgang_datum           ?? null,
          data.untersuchung_datum       ?? null,
          data.untersuchung_gueltig_bis ?? null,
          data.untersuchung_ergebnis    ?? null,
          data.leistungstest_datum      ?? null,
          data.leistungstest_gueltig_bis ?? null,
          data.leistungstest_bestanden  ?? null,
          data.bemerkung                ?? null,
        ]
      );

      const record = result.rows[0] as AtemschutzTraeger;
      logger.info('Atemschutzträger erstellt', { id: record.id, userId: data.user_id, by: createdBy });
      return record;
    } catch (error: any) {
      if (error?.code === '23505') {
        // unique constraint on user_id
        throw new Error('Für diesen Benutzer existiert bereits ein Atemschutz-Eintrag');
      }
      logger.error('AtemschutzService.create fehlgeschlagen', { error, createdBy });
      throw new Error('Atemschutzträger konnte nicht erstellt werden');
    }
  }

  // =========================================================================
  // UPDATE
  // =========================================================================

  async update(id: string, data: UpdateAtemschutzData, updatedBy: string): Promise<AtemschutzTraeger | null> {
    try {
      const fields: string[] = [];
      const values: unknown[] = [];
      let p = 1;

      const addField = (col: string, value: unknown) => {
        fields.push(`${col} = $${p++}`);
        values.push(value);
      };

      if (data.atemschutz_lehrgang      !== undefined) addField('atemschutz_lehrgang',      data.atemschutz_lehrgang);
      if (data.lehrgang_datum           !== undefined) addField('lehrgang_datum',           data.lehrgang_datum);
      if (data.untersuchung_datum       !== undefined) addField('untersuchung_datum',       data.untersuchung_datum);
      if (data.untersuchung_gueltig_bis !== undefined) addField('untersuchung_gueltig_bis', data.untersuchung_gueltig_bis);
      if (data.untersuchung_ergebnis    !== undefined) addField('untersuchung_ergebnis',    data.untersuchung_ergebnis);
      if (data.leistungstest_datum      !== undefined) addField('leistungstest_datum',      data.leistungstest_datum);
      if (data.leistungstest_gueltig_bis !== undefined) addField('leistungstest_gueltig_bis', data.leistungstest_gueltig_bis);
      if (data.leistungstest_bestanden  !== undefined) addField('leistungstest_bestanden',  data.leistungstest_bestanden);
      if (data.bemerkung                !== undefined) addField('bemerkung',                data.bemerkung);

      if (fields.length === 0) {
        throw new Error('No fields to update');
      }

      // always bump updated_at
      fields.push(`updated_at = NOW()`);

      values.push(id);
      const result = await pool.query(
        `UPDATE atemschutz_traeger SET ${fields.join(', ')} WHERE id = $${p} RETURNING *`,
        values
      );

      if (result.rows.length === 0) {
        return null;
      }

      const record = result.rows[0] as AtemschutzTraeger;
      logger.info('Atemschutzträger aktualisiert', { id, by: updatedBy });
      return record;
    } catch (error) {
      logger.error('AtemschutzService.update fehlgeschlagen', { error, id, updatedBy });
      throw error;
    }
  }

  // =========================================================================
  // DELETE (hard delete — qualification record)
  // =========================================================================

  async delete(id: string, deletedBy: string): Promise<boolean> {
    try {
      const result = await pool.query(
        `DELETE FROM atemschutz_traeger WHERE id = $1 RETURNING id`,
        [id]
      );

      if (result.rows.length === 0) {
        return false;
      }

      logger.info('Atemschutzträger gelöscht', { id, by: deletedBy });
      return true;
    } catch (error) {
      logger.error('AtemschutzService.delete fehlgeschlagen', { error, id });
      throw error;
    }
  }

  // =========================================================================
  // EXPIRING CERTIFICATIONS
  // =========================================================================

  async getExpiringCertifications(daysAhead = 30): Promise<any[]> {
    try {
      const result = await pool.query(`
        SELECT
          at.id, at.user_id, u.email,
          COALESCE(u.name, u.email) as user_name,
          at.untersuchung_gueltig_bis,
          at.leistungstest_gueltig_bis,
          CASE
            WHEN at.untersuchung_gueltig_bis < CURRENT_DATE THEN 'abgelaufen'
            WHEN at.untersuchung_gueltig_bis <= CURRENT_DATE + $1::interval THEN 'bald_faellig'
            ELSE 'ok'
          END as untersuchung_status,
          CASE
            WHEN at.leistungstest_gueltig_bis < CURRENT_DATE THEN 'abgelaufen'
            WHEN at.leistungstest_gueltig_bis <= CURRENT_DATE + $1::interval THEN 'bald_faellig'
            ELSE 'ok'
          END as leistungstest_status
        FROM atemschutz_traeger at
        JOIN users u ON u.id = at.user_id
        WHERE at.einsatzbereit = TRUE
          AND (
            at.untersuchung_gueltig_bis <= CURRENT_DATE + $1::interval
            OR at.leistungstest_gueltig_bis <= CURRENT_DATE + $1::interval
          )
        ORDER BY LEAST(at.untersuchung_gueltig_bis, at.leistungstest_gueltig_bis) ASC
      `, [`${daysAhead} days`]);

      return result.rows;
    } catch (error) {
      logger.error('AtemschutzService.getExpiringCertifications fehlgeschlagen', { error });
      throw new Error('Ablaufende Atemschutz-Zertifizierungen konnten nicht geladen werden');
    }
  }

  // =========================================================================
  // DASHBOARD KPI / STATISTIKEN
  // =========================================================================

  async getStats(userGroups: string[], _userId: string): Promise<AtemschutzStats> {
    const isPrivileged = userGroups.some(g => ATEMSCHUTZ_PRIVILEGED.includes(g));
    if (!isPrivileged) {
      return {
        total: 0,
        mitLehrgang: 0,
        untersuchungGueltig: 0,
        untersuchungAbgelaufen: 0,
        untersuchungBaldFaellig: 0,
        leistungstestGueltig: 0,
        leistungstestAbgelaufen: 0,
        leistungstestBaldFaellig: 0,
        einsatzbereit: 0,
      };
    }
    try {
      const result = await pool.query(`
        SELECT
          COUNT(*)                                                          AS total,
          COUNT(*) FILTER (WHERE atemschutz_lehrgang = TRUE)               AS mit_lehrgang,
          COUNT(*) FILTER (WHERE untersuchung_gueltig = TRUE)              AS untersuchung_gueltig,
          COUNT(*) FILTER (
            WHERE untersuchung_gueltig_bis IS NOT NULL
              AND untersuchung_gueltig_bis < CURRENT_DATE
          )                                                                AS untersuchung_abgelaufen,
          COUNT(*) FILTER (
            WHERE untersuchung_gueltig_bis IS NOT NULL
              AND untersuchung_gueltig_bis >= CURRENT_DATE
              AND untersuchung_gueltig_bis <= CURRENT_DATE + INTERVAL '90 days'
          )                                                                AS untersuchung_bald_faellig,
          COUNT(*) FILTER (WHERE leistungstest_gueltig = TRUE)             AS leistungstest_gueltig,
          COUNT(*) FILTER (
            WHERE leistungstest_gueltig_bis IS NOT NULL
              AND leistungstest_gueltig_bis < CURRENT_DATE
          )                                                                AS leistungstest_abgelaufen,
          COUNT(*) FILTER (
            WHERE leistungstest_gueltig_bis IS NOT NULL
              AND leistungstest_gueltig_bis >= CURRENT_DATE
              AND leistungstest_gueltig_bis <= CURRENT_DATE + INTERVAL '30 days'
          )                                                                AS leistungstest_bald_faellig,
          COUNT(*) FILTER (WHERE einsatzbereit = TRUE)                     AS einsatzbereit
        FROM atemschutz_uebersicht
        WHERE mitglied_status IS NULL OR mitglied_status IN ('aktiv')
      `);

      const row = result.rows[0] ?? {};

      return {
        total:                    parseInt(row.total ?? '0', 10),
        mitLehrgang:              parseInt(row.mit_lehrgang ?? '0', 10),
        untersuchungGueltig:      parseInt(row.untersuchung_gueltig ?? '0', 10),
        untersuchungAbgelaufen:   parseInt(row.untersuchung_abgelaufen ?? '0', 10),
        untersuchungBaldFaellig:  parseInt(row.untersuchung_bald_faellig ?? '0', 10),
        leistungstestGueltig:     parseInt(row.leistungstest_gueltig ?? '0', 10),
        leistungstestAbgelaufen:  parseInt(row.leistungstest_abgelaufen ?? '0', 10),
        leistungstestBaldFaellig: parseInt(row.leistungstest_bald_faellig ?? '0', 10),
        einsatzbereit:            parseInt(row.einsatzbereit ?? '0', 10),
      };
    } catch (error) {
      logger.error('AtemschutzService.getStats fehlgeschlagen', { error });
      throw new Error('Atemschutz-Statistiken konnten nicht geladen werden');
    }
  }
}

export default new AtemschutzService();
