/**
 * eTerra Health Check — server-side singleton.
 *
 * Periodically pings eTerra to detect availability / maintenance.
 * The result is cached for `CHECK_INTERVAL_MS` to avoid hammering the server.
 *
 * When eTerra is down, the session route will block login attempts and
 * the UI will show a friendly "mentenanță" message instead of login errors.
 */

import axios from "axios";

/* ------------------------------------------------------------------ */
/*  Types                                                              */
/* ------------------------------------------------------------------ */

export type EterraHealthStatus = {
  /** Whether eTerra responded within timeout */
  available: boolean;
  /** Human message for the UI */
  message: string;
  /** ISO timestamp of last successful check */
  lastCheckedAt: string;
  /** ISO timestamp of last time eTerra was actually reachable */
  lastAvailableAt: string | null;
  /** How many consecutive failures */
  consecutiveFailures: number;
  /** Whether we detected a maintenance page (vs generic timeout/error) */
  maintenance: boolean;
};

/* ------------------------------------------------------------------ */
/*  Constants                                                          */
/* ------------------------------------------------------------------ */

const BASE_URL = "https://eterra.ancpi.ro/eterra";

/** How often to re-check (3 minutes) */
const CHECK_INTERVAL_MS = 3 * 60 * 1000;

/** Timeout for the health ping itself (10 seconds) */
const PING_TIMEOUT_MS = 10_000;

/** After this many failures, consider it definitely maintenance */
const MAINTENANCE_THRESHOLD = 2;

/**
 * Keywords in eTerra HTML responses that indicate maintenance.
 * These are actual strings observed on the eTerra login page during downtime.
 * Matched case-insensitively against the response body.
 */
const MAINTENANCE_KEYWORDS = [
  // Observed on eterra.ancpi.ro/#/login during real maintenance (2026-03-08)
  "serviciu indisponibil",
  "activități de mentenanță",
  "activitati de mentenanta",
  "mentenanță",
  "mentenanta",
  // Generic maintenance patterns
  "maintenance",
  "indisponibil",
  "în desfășurare",
  "in desfasurare",
  "temporar indisponibil",
  "lucrări",
  "lucrari",
  "întrerupere",
  "intrerupere",
  "revenim",
  "service unavailable",
  "503",
];

/* ------------------------------------------------------------------ */
/*  Global singleton state                                             */
/* ------------------------------------------------------------------ */

type HealthState = {
  status: EterraHealthStatus;
  lastCheckStarted: number;
};

const g = globalThis as { __eterraHealthState?: HealthState };

function getState(): HealthState {
  if (!g.__eterraHealthState) {
    g.__eterraHealthState = {
      status: {
        available: true, // Optimistic default: assume available until checked
        message: "Verificare în curs…",
        lastCheckedAt: new Date(0).toISOString(),
        lastAvailableAt: null,
        consecutiveFailures: 0,
        maintenance: false,
      },
      lastCheckStarted: 0,
    };
  }
  return g.__eterraHealthState;
}

/* ------------------------------------------------------------------ */
/*  Helpers                                                            */
/* ------------------------------------------------------------------ */

/**
 * Try to extract a human-readable maintenance message from the HTML body.
 * eTerra's login page shows messages like:
 *   "Serviciu indisponibil"
 *   "activități de mentenanță sunt în desfășurare"
 */
function extractMaintenanceMessage(body: string): string | null {
  // Try common patterns in the eTerra maintenance page
  // Pattern: text between tags that contains maintenance keywords
  const patterns = [
    /serviciu\s+indisponibil[^<]*/i,
    /activit[aă][tț]i\s+de\s+mentenan[tț][aă]\s+[^<]*/i,
    /mentenan[tț][aă]\s+[^<]{0,100}/i,
  ];
  for (const pattern of patterns) {
    const match = body.match(pattern);
    if (match) {
      // Capitalize first letter, trim, remove trailing HTML artifacts
      const raw = match[0].replace(/<[^>]*>/g, "").trim();
      if (raw.length > 5 && raw.length < 200) {
        return raw.charAt(0).toUpperCase() + raw.slice(1);
      }
    }
  }
  return null;
}

/* ------------------------------------------------------------------ */
/*  Core check                                                         */
/* ------------------------------------------------------------------ */

async function performHealthCheck(): Promise<EterraHealthStatus> {
  const state = getState();
  const now = Date.now();
  state.lastCheckStarted = now;

  try {
    // A lightweight GET to the eTerra root — we only care about reachability.
    // We follow redirects (login page redirect is fine — means eTerra is UP).
    const response = await axios.get(BASE_URL, {
      timeout: PING_TIMEOUT_MS,
      maxRedirects: 5,
      validateStatus: () => true, // Accept any HTTP status as "response received"
      headers: {
        "User-Agent":
          "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
      },
    });

    const status = response.status;
    const body =
      typeof response.data === "string" ? response.data.toLowerCase() : "";

    // Check if the page content indicates maintenance
    const matchedKeyword = MAINTENANCE_KEYWORDS.find((kw) => body.includes(kw));
    const isMaintenance = status === 503 || !!matchedKeyword;

    if (isMaintenance) {
      // Try to extract the actual maintenance message from the page
      const extractedMsg = extractMaintenanceMessage(body);
      state.status = {
        available: false,
        message: extractedMsg || "eTerra este în mentenanță programată",
        lastCheckedAt: new Date().toISOString(),
        lastAvailableAt: state.status.lastAvailableAt,
        consecutiveFailures: state.status.consecutiveFailures + 1,
        maintenance: true,
      };
    } else if (status >= 200 && status < 500) {
      // 2xx/3xx/4xx = server is responsive (4xx like 401/403 = login required = UP)
      state.status = {
        available: true,
        message: "eTerra disponibil",
        lastCheckedAt: new Date().toISOString(),
        lastAvailableAt: new Date().toISOString(),
        consecutiveFailures: 0,
        maintenance: false,
      };
    } else {
      // 5xx (but not 503 maintenance) — server error
      state.status = {
        available: false,
        message: `eTerra indisponibil (HTTP ${status})`,
        lastCheckedAt: new Date().toISOString(),
        lastAvailableAt: state.status.lastAvailableAt,
        consecutiveFailures: state.status.consecutiveFailures + 1,
        maintenance:
          state.status.consecutiveFailures + 1 >= MAINTENANCE_THRESHOLD,
      };
    }
  } catch (error) {
    const err = error as { code?: string; message?: string };
    const isTimeout =
      err.code === "ECONNABORTED" ||
      err.code === "ETIMEDOUT" ||
      err.code === "ECONNREFUSED" ||
      err.code === "ECONNRESET" ||
      err.code === "ENOTFOUND";

    const failures = state.status.consecutiveFailures + 1;

    state.status = {
      available: false,
      message: isTimeout
        ? "eTerra nu răspunde (timeout)"
        : `eTerra indisponibil: ${err.message ?? "eroare necunoscută"}`,
      lastCheckedAt: new Date().toISOString(),
      lastAvailableAt: state.status.lastAvailableAt,
      consecutiveFailures: failures,
      maintenance: failures >= MAINTENANCE_THRESHOLD,
    };
  }

  return state.status;
}

/* ------------------------------------------------------------------ */
/*  Public API                                                         */
/* ------------------------------------------------------------------ */

/**
 * Get current eTerra health status.
 * Triggers a fresh check if the cached one is stale.
 * Returns immediately with the cached value (the check runs in background).
 */
export function getEterraHealth(): EterraHealthStatus {
  const state = getState();
  const now = Date.now();
  const age = now - new Date(state.status.lastCheckedAt).getTime();

  // If stale, trigger a background refresh (non-blocking)
  if (age > CHECK_INTERVAL_MS) {
    // Prevent parallel checks
    if (now - state.lastCheckStarted > PING_TIMEOUT_MS + 2000) {
      void performHealthCheck();
    }
  }

  return state.status;
}

/**
 * Force an immediate health check (blocking).
 * Used when explicitly requested or on first load.
 */
export async function checkEterraHealthNow(): Promise<EterraHealthStatus> {
  return performHealthCheck();
}

/**
 * Returns true if eTerra is believed to be available for login.
 * Quick synchronous check for use in session route guards.
 */
export function isEterraAvailable(): boolean {
  return getState().status.available;
}
