// services/notification.service.ts
import type { FastifyInstance } from 'fastify';
import {secrets} from "../utils/secrets";
import { eq } from "drizzle-orm";
import { notificationsEventTypes, notificationsItems } from "../../db/schema";

export type NotificationStatus = 'queued' | 'sent' | 'failed';

export interface TriggerInput {
    tenantId: number;
    userId: string;                 // muss auf public.auth_users.id zeigen
    eventType: string;              // muss in notifications_event_types existieren
    title: string;                  // Betreff/Title
    message: string;                // Klartext-Inhalt
    payload?: Record<string, unknown>;
}

export interface UserDirectoryInfo {
    email?: string;
}

export type UserDirectory = (server: FastifyInstance, userId: string, tenantId: number) => Promise<UserDirectoryInfo | null>;

export class NotificationService {
    constructor(
        private server: FastifyInstance,
        private getUser: UserDirectory
    ) {}

    /**
     * Löst eine E-Mail-Benachrichtigung aus:
     *  - Validiert den Event-Typ
     *  - Legt einen Datensatz in notifications_items an (status: queued)
     *  - Versendet E-Mail (FEDEO Branding)
     *  - Aktualisiert status/sent_at bzw. error
     */
    async trigger(input: TriggerInput) {
        const { tenantId, userId, eventType, title, message, payload } = input;

        // 1) Event-Typ prüfen (aktiv?)
        const eventTypeRows = await this.server.db
            .select()
            .from(notificationsEventTypes)
            .where(eq(notificationsEventTypes.eventKey, eventType))
            .limit(1)
        const eventTypeRow = eventTypeRows[0]

        if (!eventTypeRow || eventTypeRow.isActive !== true) {
            throw new Error(`Unbekannter oder inaktiver Event-Typ: ${eventType}`);
        }

        // 2) Zieladresse beschaffen
        const user = await this.getUser(this.server, userId, tenantId);
        if (!user?.email) {
            throw new Error(`Nutzer ${userId} hat keine E-Mail-Adresse`);
        }

        // 3) Notification anlegen (status: queued)
        const insertedRows = await this.server.db
            .insert(notificationsItems)
            .values({
                tenantId,
                userId,
                eventType,
                title,
                message,
                payload: payload ?? null,
                channel: 'email',
                status: 'queued'
            })
            .returning({ id: notificationsItems.id })
        const inserted = insertedRows[0]

        if (!inserted) {
            throw new Error("Fehler beim Einfügen der Notification");
        }

        // 4) E-Mail versenden
        try {
            await this.sendEmail(user.email, title, message);

            await this.server.db
                .update(notificationsItems)
                .set({ status: 'sent', sentAt: new Date() })
                .where(eq(notificationsItems.id, inserted.id));

            return { success: true, id: inserted.id };
        } catch (err: any) {
            await this.server.db
                .update(notificationsItems)
                .set({ status: 'failed', error: String(err?.message || err) })
                .where(eq(notificationsItems.id, inserted.id));

            this.server.log.error({ err, notificationId: inserted.id }, 'E-Mail Versand fehlgeschlagen');
            return { success: false, error: err?.message || 'E-Mail Versand fehlgeschlagen' };
        }
    }

    // ---- private helpers ------------------------------------------------------

    private async sendEmail(to: string, subject: string, message: string) {
        const nodemailer = await import('nodemailer');

        const transporter = nodemailer.createTransport({
            host: secrets.MAILER_SMTP_HOST,
            port: Number(secrets.MAILER_SMTP_PORT),
            secure: secrets.MAILER_SMTP_SSL === 'true',
            auth: {
                user: secrets.MAILER_SMTP_USER,
                pass: secrets.MAILER_SMTP_PASS
            }
        });

        const html = this.renderFedeoHtml(subject, message);

        await transporter.sendMail({
            from: secrets.MAILER_FROM,
            to,
            subject,
            text: message,
            html
        });
    }

    private renderFedeoHtml(title: string, message: string) {
        return `
      <html><body style="font-family:sans-serif;color:#222">
        <div style="border:1px solid #ddd;border-radius:8px;padding:16px;max-width:600px;margin:auto">
          <h2 style="color:#0f62fe;margin:0 0 12px">FEDEO</h2>
          <h3 style="margin:0 0 8px">${this.escapeHtml(title)}</h3>
          <p>${this.nl2br(this.escapeHtml(message))}</p>
          <hr style="margin:16px 0;border:none;border-top:1px solid #eee"/>
          <p style="font-size:12px;color:#666">Automatisch generiert von FEDEO</p>
        </div>
      </body></html>
    `;
    }

    // simple escaping (ausreichend für unser Template)
    private escapeHtml(s: string) {
        return s
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;');
    }

    private nl2br(s: string) {
        return s.replace(/\n/g, '<br/>');
    }
}
