import nodemailer from "nodemailer";
import { Property } from "../types/property";
import { Filter } from "../types/filter";
import { EmailOptions } from "../types/email";
import { FilterModel } from "../models/filterModel";
import { PropertyModel } from "../models/propertyModel";
import path from "path";
import fs from "fs";

function escapeHtml(value: unknown): string {
  return String(value ?? "").replace(/[&<>"']/g, char => ({
    "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;",
  }[char] || char));
}

function safeHttpUrl(value: string): string {
  try {
    const url = new URL(value);
    return url.protocol === "http:" || url.protocol === "https:" ? url.toString() : "#";
  } catch {
    return "#";
  }
}

export class EmailService {
  private transporter: nodemailer.Transporter;

  constructor() {
    this.transporter = nodemailer.createTransport({
      host: process.env.EMAIL_HOST || "smtp.gmail.com",
      port: Number(process.env.EMAIL_PORT) || 587,
      secure: process.env.EMAIL_SECURE === "true",
      auth: {
        user: process.env.EMAIL_USER,
        pass: process.env.EMAIL_PASS,
      },
    });
  }

  async sendEmail(options: EmailOptions): Promise<void> {
    await this.transporter.sendMail({
      from: process.env.EMAIL_FROM || "Lliria Properties <no-reply@lliria.local>",
      to: options.to,
      subject: options.subject,
      text: options.text,
      html: options.html,
    });
  }

  async sendAlerts(properties: Property[], recipient?: string): Promise<void> {
    const to = recipient || process.env.EMAIL_TO || "";
    if (!to || properties.length === 0) return;

    const rows = properties.slice(0, 20).map((p) =>
      `<tr>
        <td><a href="${escapeHtml(safeHttpUrl(p.url))}" target="_blank" rel="noopener noreferrer">${escapeHtml(p.title)}</a></td>
        <td>${p.price.toLocaleString("es-ES")} €</td>
        <td>${escapeHtml(p.municipality || p.location)}</td>
        <td>${escapeHtml(p.property_type)}</td>
        <td>${p.rooms || "-"}</td>
        <td>${p.size_m2 ? p.size_m2 + " m²" : "-"}</td>
        <td>${escapeHtml(p.source)}</td>
      </tr>`
    ).join("");

    const html = `
      <h2>Nuevas propiedades en Lliria y alrededores</h2>
      <p>Se han encontrado <strong>${properties.length}</strong> propiedades que coinciden con tus filtros.</p>
      <table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;font-family:sans-serif;font-size:13px">
        <thead style="background:#0d6efd;color:#fff">
          <tr><th>Título</th><th>Precio</th><th>Municipio</th><th>Tipo</th><th>Hab.</th><th>Superficie</th><th>Portal</th></tr>
        </thead>
        <tbody>${rows}</tbody>
      </table>
      <p style="font-size:11px;color:#888;margin-top:20px">Lliria Properties Scraper - Alerta automática</p>
    `;

    await this.sendEmail({
      to,
      subject: `Alerta: ${properties.length} propiedades nuevas en Lliria`,
      html,
    });
    console.log(`Alerta enviada a ${to} con ${properties.length} propiedades`);
  }

  async sendFilteredAlerts(): Promise<void> {
    const filters = await FilterModel.findEmailAlerts();
    for (const filter of filters) {
      const props = await PropertyModel.filterAdvanced(
        filter.min_price, filter.max_price, filter.property_type,
        filter.municipality, filter.min_rooms, filter.min_size_m2,
        filter.operation_type, undefined, filter.portal
      );
      const pending = filter.id ? await FilterModel.excludeDelivered(filter.id, props) : props;
      if (pending.length > 0) {
        await this.sendAlerts(pending, filter.recipient_email);
        if (filter.id) {
          await FilterModel.markDelivered(filter.id, pending.map(property => property.id!).filter(Boolean));
        }
      }
    }
  }
}

export default new EmailService();
