const axios = require("axios");
const fs = require("fs");
const path = require("path");
const crypto = require("crypto");
const { DateTime } = require("luxon");
const logger = require("../../handlers/logger");
const {
  encryptData,
  decryptData,
  verifyMachine,
} = require("../../managers/licenseManager");
const {
  generateSystemFingerprint,
} = require("../../managers/systemFingerprint");

const safeAxios = require("../../managers/safeAxios");
const db = require("../../managers/dbConfig");

//const LICENSE_PATH = process.env.LICENSE_PATH;
const LICENSE_PATH =
  "C:\\Users\\Great_Ola\\Desktop\\javaScript-Course\\NodeExpress";
const LAST_SEEN_PATH = path.join(path.dirname(LICENSE_PATH), "last_seen.json");

const SECRET_KEY = process.env.LICENSE_SECRET; // 32-byte key

const SIGN_SECRET = process.env.LICENSE_SECRET;
const RENEW_URL = process.env.RENEW_URL;

async function renewLicense() {
  const hospitalId = await db.execute(
    "SELECT id FROM hospitals WHERE code_name = 'default' LIMIT 1"
  );
  const machineId = generateSystemFingerprint();

  let retries = 3;
  let lastError;

  while (retries--) {
    const [err, license] = await safeAxios.post(
      RENEW_URL,
      {
        hospital_id: hospitalId,
        machine_id: machineId,
      },
      {
        timeout: 10000, // 10 seconds
      }
    );

    if (err) {
      lastError = err;
      logger.warn(
        `License renew attempt failed. Retries left: ${retries} → ${err.message}`
      );
      await new Promise((r) => setTimeout(r, 1500));
      continue;
    }

    try {
      if (!license.signature || !license.expiry_date) {
        throw new Error("Invalid license response from server");
      }

      if (!validateSignature(license)) {
        throw new Error("License signature invalid or tampered");
      }

      const encrypted = encryptData(JSON.stringify(license), SECRET_KEY);
      fs.mkdirSync(path.dirname(LICENSE_PATH), { recursive: true });
      fs.writeFileSync(LICENSE_PATH, JSON.stringify(encrypted, null, 2));

      logger.info(`✅ License renewed for hospital ${hospitalId}`);
      return license;
    } catch (validationError) {
      lastError = validationError;
      logger.warn(`Validation error: ${validationError.message}`);
      break; // don't retry if response is invalid or tampered
    }
  }

  logger.error("❌ All license renewal attempts failed.");
  throw lastError;
}

// async function renewLicense() {
//   const hospitalId = 12;
//   const machineId = generateSystemFingerprint();

//   let retries = 3;
//   let lastError;

//   while (retries--) {
//     try {
//       const response = await axios.post(
//         RENEW_URL,
//         {
//           hospital_id: hospitalId,
//           machine_id: machineId,
//         },
//         {
//           timeout: 10000, // 10 seconds timeout
//         }
//       );

//       const license = response.data;

//       if (!license.signature || !license.expiry_date) {
//         throw new Error("Invalid license response from server");
//       }

//       if (!validateSignature(license)) {
//         throw new Error("License signature invalid or tampered");
//       }

//       const encrypted = encryptData(JSON.stringify(license), SECRET_KEY);
//       fs.mkdirSync(path.dirname(LICENSE_PATH), { recursive: true });
//       fs.writeFileSync(LICENSE_PATH, JSON.stringify(encrypted, null, 2));
//       logger.info(`License renewed for hospital ${hospitalId}`);

//       return license;
//     } catch (err) {
//       lastError = err;
//       logger.warn(`License renew attempt failed. Retries left: ${retries}`);
//       await new Promise((r) => setTimeout(r, 1500)); // delay before retry
//     }
//   }

//   logger.error("All license renewal attempts failed.");
//   throw lastError;
// }

function validateSignature(license) {
  const data = `${license.hospital_id}|${license.machine_id}|${license.expiry_date}|${license.plan}`;
  const signature = crypto
    .createHmac("sha256", SIGN_SECRET)
    .update(data)
    .digest("hex");
  return signature === license.signature;
}

function loadLastSeen() {
  if (!fs.existsSync(LAST_SEEN_PATH)) {
    return null;
  }

  try {
    const raw = fs.readFileSync(LAST_SEEN_PATH, "utf8");
    const decrypted = JSON.parse(decryptData(JSON.parse(raw), SECRET_KEY));
    return DateTime.fromISO(decrypted.last_seen);
  } catch (err) {
    logger.error("Failed to read last_seen.json:", err.message);
    return null;
  }
}

function saveLastSeen(dateTime = DateTime.now()) {
  const data = { last_seen: dateTime.toISO() };
  const encrypted = encryptData(JSON.stringify(data), SECRET_KEY);

  fs.mkdirSync(path.dirname(LAST_SEEN_PATH), { recursive: true });
  fs.writeFileSync(LAST_SEEN_PATH, JSON.stringify(encrypted, null, 2));
}

async function checkLicense() {
  const filePath = path.resolve(LICENSE_PATH);
  if (!fs.existsSync(filePath)) {
    throw new Error("License file not found");
  }

  const raw = fs.readFileSync(filePath, "utf8");
  const encrypted = JSON.parse(raw);
  const decrypted = JSON.parse(decryptData(encrypted, SECRET_KEY));

  const machineId = generateSystemFingerprint();

  if (decrypted.machine_id !== machineId) {
    throw new Error("Unrecognized machine, contact support");
  }

  if (!validateSignature(decrypted)) {
    throw new Error("License signature invalid or tampered");
  }

  const now = DateTime.utc();
  const expiry = DateTime.fromISO(decrypted.expiry_date, { zone: "utc" });
  const graceEnd = expiry.plus({ days: 3 });

  // Check for date tampering
  const lastSeen = loadLastSeen();
  if (lastSeen && now < lastSeen.minus({ minutes: 5 })) {
    throw new Error("System clock tampering detected.");
  }

  // Save new last seen
  saveLastSeen(now);

  if (now > graceEnd) {
    throw new Error("License expired. Please renew.");
  }

  return {
    status: now > expiry ? "grace" : "valid",
    license: decrypted,
  };
}
module.exports = { renewLicense, checkLicense };

// const db = require("../../managers/dbConfig");
// const generateLicenseKey = require("../../managers/generateLicenseKey");
// const logger = require("../../handlers/logger");

// // Get License by Hospital ID
// exports.getLicense = async (hospital_id) => {
//   const [rows] = await db.execute(
//     "SELECT * FROM licenses WHERE hospital_id = ?",
//     [hospital_id]
//   );
//   return rows[0] || null;
// };

// // Renew License
// exports.renewLicense = async (hospitalId) => {
//   const connection = await db.getConnection();
//   await connection.beginTransaction();

//   try {
//     // Fetch current plan details
//     const [plans] = await connection.query(
//       `SELECT sp.duration, sp.price, w.balance
//              FROM subscription_plans sp
//              JOIN hospitals hs ON hs.plan_id = sp.id
//              JOIN wallets w ON w.hospital_id = hs.id
//              WHERE hs.id = ?`,
//       [hospitalId]
//     );

//     if (!plans || plans.length === 0) {
//       throw "Subscription plan not found";
//     }

//     const { duration, price, balance } = plans[0];

//     if (balance < price) {
//       throw "Insufficient funds in wallet";
//     }

//     // Deduct amount from wallet
//     const newBalance = balance - price;
//     await connection.query(
//       `UPDATE wallets SET balance = ? WHERE hospital_id = ?`,
//       [newBalance, hospitalId]
//     );

//     // Log transaction
//     await connection.query(
//       `INSERT INTO wallet_transactions
//              (hospital_id, transaction_type, amount, balance_before, balance_after, description)
//              VALUES (?, 'debit', ?, ?, ?, 'License renewal')`,
//       [hospitalId, price, balance, newBalance]
//     );

//     // Generate new license key
//     const newLicenseKey = generateLicenseKey();

//     // Update license expiry date
//     await connection.query(
//       `UPDATE licenses
//              SET license_key = ?, expiry_date = DATE_ADD(NOW(), INTERVAL ? DAY)
//              WHERE hospital_id = ?`,
//       [newLicenseKey, duration, hospitalId]
//     );

//     await connection.commit();

//     logger.info(
//       `License renewed for hospital ${hospitalId}. New key: ${newLicenseKey}`
//     );

//     return {
//       status: "success",
//       message: "License renewed successfully",
//       newLicenseKey,
//     };
//   } catch (error) {
//     await connection.rollback();

//     logger.error(
//       `License renewal failed for hospital ${hospitalId}: ${error.message}`
//     );

//     return { status: "failed", message: error.message };
//   } finally {
//     connection.release();
//   }
// };

// // Reset License (Admin action)
// exports.resetLicense = async (hospital_id, new_machine_id) => {
//   await db.execute("UPDATE licenses SET machine_id = ? WHERE hospital_id = ?", [
//     new_machine_id,
//     hospital_id,
//   ]);
// };
//module.exports = { renewLicense };
