import nodemailer from "nodemailer";

import { env } from "../../config/env.js";
import { HttpError } from "../../lib/http-error.js";
import { query, queryOne } from "../../lib/db.js";
import { getInspectionEmailSettings } from "./settings.service.js";

const getTransporter = () => {
  if (!env.SMTP_HOST || !env.SMTP_USER || !env.SMTP_PASSWORD) {
    throw new HttpError(500, "SMTP nie jest skonfigurowane");
  }

  return nodemailer.createTransport({
    host: env.SMTP_HOST,
    port: env.SMTP_PORT,
    secure: env.SMTP_SECURE,
    auth: {
      user: env.SMTP_USER,
      pass: env.SMTP_PASSWORD,
    },
  });
};

export const sendTrackingTestEmail = async () => {
  const transporter = getTransporter();
  const from = env.SMTP_FROM ?? env.SMTP_USER!;
  const sentAt = new Date().toLocaleString("pl-PL", {
    dateStyle: "short",
    timeStyle: "medium",
  });

  const result = await transporter.sendMail({
    from: `"VISAU AUTOTRACKING" <${from}>`,
    to: env.TEST_MAIL_RECIPIENT,
    subject: "VISAU TRACKING: test wysyłki maila",
    text: [
      "To jest testowy mail z panelu VISAU TRACKING.",
      "",
      `Czas wysyłki: ${sentAt}`,
      "Jeśli dostałeś tę wiadomość, konfiguracja SMTP działa poprawnie.",
    ].join("\n"),
    html: `
      <div style="font-family:Arial,sans-serif;background:#0b1220;color:#e8eefc;padding:24px">
        <div style="max-width:560px;margin:0 auto;border:1px solid rgba(88,255,125,.35);border-radius:18px;padding:24px;background:#121b2b">
          <div style="font-size:13px;letter-spacing:.22em;text-transform:uppercase;color:#78caff;margin-bottom:10px">VISAU AUTOTRACKING</div>
          <div style="font-size:24px;font-weight:700;color:#ffffff;margin-bottom:14px">Test wysyłki maila</div>
          <div style="font-size:15px;line-height:1.6;color:#c9d6ef">
            To jest testowy mail z panelu <strong>VISAU TRACKING</strong>.<br />
            Czas wysyłki: <strong>${sentAt}</strong><br />
            Jeśli dostałeś tę wiadomość, konfiguracja SMTP działa poprawnie.
          </div>
        </div>
      </div>
    `,
  });

  return {
    accepted: result.accepted,
    rejected: result.rejected,
    messageId: result.messageId,
  };
};

const normalizeInspectionDate = (value?: string | null) => {
  if (!value) {
    return null;
  }

  const trimmed = value.trim();
  if (!trimmed) {
    return null;
  }

  const dateOnlyMatch = trimmed.match(/^(\d{4}-\d{2}-\d{2})/);
  if (dateOnlyMatch) {
    return dateOnlyMatch[1] ?? null;
  }

  const parsed = new Date(trimmed);
  if (Number.isNaN(parsed.getTime())) {
    return null;
  }

  return parsed.toISOString().slice(0, 10);
};

const getDayDiff = (normalizedInspectionDate: string) => {
  const today = new Date();
  const todayUtc = Date.UTC(today.getFullYear(), today.getMonth(), today.getDate());
  const due = new Date(`${normalizedInspectionDate}T00:00:00`);
  const dueUtc = Date.UTC(due.getFullYear(), due.getMonth(), due.getDate());

  if (Number.isNaN(dueUtc)) {
    return null;
  }

  return Math.floor((dueUtc - todayUtc) / 86400000);
};

export const sendInspectionDueSoonEmailIfNeeded = async (input: {
  vehicleId: string;
  vehicleName: string;
  plateNumber?: string | null;
  inspectionDueDate?: string | null;
}) => {
  const normalizedInspectionDate = normalizeInspectionDate(input.inspectionDueDate);
  if (!normalizedInspectionDate) {
    return;
  }

  const dayDiff = getDayDiff(normalizedInspectionDate);
  if (dayDiff == null || dayDiff > 14) {
    return;
  }

  const settings = await getInspectionEmailSettings();
  const recipients = settings.recipients;
  if (recipients.length === 0) {
    return;
  }

  const inserted = await queryOne<{ vehicle_id: string }>(
    `
      insert into vehicle_inspection_email_events (
        vehicle_id,
        inspection_due_date,
        notification_type,
        recipients,
        sent_at
      )
      values ($1, $2::date, 'inspection-due-soon', $3::text[], now())
      on conflict (vehicle_id, inspection_due_date, notification_type) do nothing
      returning vehicle_id
    `,
    [input.vehicleId, normalizedInspectionDate, recipients],
  );

  if (!inserted) {
    return;
  }

  const transporter = getTransporter();
  const from = env.SMTP_FROM ?? env.SMTP_USER!;
  const dueDateLabel = new Date(`${normalizedInspectionDate}T00:00:00`).toLocaleDateString("pl-PL");
  const daysLabel = dayDiff <= 0 ? "Termin przeglądu już minął." : `Do terminu przeglądu zostało ${dayDiff} dni.`;
  const vehicleLabel = input.plateNumber?.trim()
    ? `${input.vehicleName} (${input.plateNumber.trim()})`
    : input.vehicleName;

  try {
    await transporter.sendMail({
      from: `"VISAU AUTOTRACKING" <${from}>`,
      to: recipients.join(", "),
      subject: `VISAU TRACKING: przegląd pojazdu ${vehicleLabel}`,
      text: [
        `Pojazd: ${vehicleLabel}`,
        `Termin przeglądu: ${dueDateLabel}`,
        daysLabel,
        "",
        "Pojazd wszedł w próg 14 dni do terminu przeglądu.",
      ].join("\n"),
      html: `
        <div style="font-family:Arial,sans-serif;background:#0b1220;color:#e8eefc;padding:24px">
          <div style="max-width:560px;margin:0 auto;border:1px solid rgba(88,255,125,.35);border-radius:18px;padding:24px;background:#121b2b">
            <div style="font-size:13px;letter-spacing:.22em;text-transform:uppercase;color:#78caff;margin-bottom:10px">VISAU AUTOTRACKING</div>
            <div style="font-size:24px;font-weight:700;color:#ffffff;margin-bottom:14px">Przegląd pojazdu</div>
            <div style="font-size:15px;line-height:1.6;color:#c9d6ef">
              Pojazd: <strong>${vehicleLabel}</strong><br />
              Termin przeglądu: <strong>${dueDateLabel}</strong><br />
              ${daysLabel}
            </div>
          </div>
        </div>
      `,
    });
  } catch (error) {
    await query(
      `
        delete from vehicle_inspection_email_events
        where vehicle_id = $1
          and inspection_due_date = $2::date
          and notification_type = 'inspection-due-soon'
      `,
      [input.vehicleId, normalizedInspectionDate],
    );

    throw error;
  }
};
