// File-based JSON store for member vouchers.
// Each voucher: { code, tier, addedAt }

import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const STORE_PATH = path.join(__dirname, "..", "data", "vouchers.json");
const DELETED_VCH_PATH = path.join(__dirname, "..", "data", "deleted-vouchers.json");

function readDeletedVouchers() {
  try {
    if (fs.existsSync(DELETED_VCH_PATH)) return JSON.parse(fs.readFileSync(DELETED_VCH_PATH, "utf-8"));
  } catch {}
  return [];
}

function writeDeletedVouchers(list) {
  const dir = path.dirname(DELETED_VCH_PATH);
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
  fs.writeFileSync(DELETED_VCH_PATH, JSON.stringify(list, null, 2));
}

function addDeletedVoucher(code) {
  if (!code) return;
  const list = readDeletedVouchers();
  const cleanCode = code.trim().toUpperCase();
  if (!list.includes(cleanCode)) {
    list.push(cleanCode);
    writeDeletedVouchers(list);
  }
}


function ensureDir() {
  const dir = path.dirname(STORE_PATH);
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
}

function readAll() {
  ensureDir();
  if (!fs.existsSync(STORE_PATH)) return [];
  try {
    const list = JSON.parse(fs.readFileSync(STORE_PATH, "utf-8"));
    let migrated = false;
    for (const v of list) {
      if (v.tier !== "pro" && v.tier !== "vip") {
        v.tier = "pro";
        migrated = true;
      }
    }
    if (migrated) {
      fs.writeFileSync(STORE_PATH, JSON.stringify(list, null, 2));
    }
    return list;
  } catch {
    return [];
  }
}

function writeAll(list) {
  ensureDir();
  fs.writeFileSync(STORE_PATH, JSON.stringify(list, null, 2));
}

export function listVouchers() {
  return readAll();
}

export function addVoucher({ code, tier = "pro", whatsapp = "", duration = "1bulan", durationDays = 30, dailyLimit = 5, createdBy = "owner", createdByName = "Owner", pricePaid = 0, resellerCost = 0, commission = 0 }) {
  const cleanWhatsapp = whatsapp.trim();
  let cleanCode = code ? code.trim().toUpperCase() : "";

  if (!cleanCode) {
    if (!cleanWhatsapp) {
      throw new Error("Nomor Whatsapp Member wajib diisi jika Kode Voucher dikosongkan");
    }
    const digits = cleanWhatsapp.replace(/\D/g, "");
    if (digits.length < 5) {
      throw new Error("Nomor Whatsapp harus memiliki minimal 5 digit angka");
    }
    const last5 = digits.slice(-5);
    cleanCode = `TEKNO-${last5}`;
  }

  const list = readAll();
  if (list.some((v) => v.code === cleanCode)) {
    throw new Error(`Voucher "${cleanCode}" sudah terdaftar`);
  }

  // Calculate active period (expiresAt)
  let days = 30;
  if (duration === "custom") {
    days = parseInt(durationDays, 10);
    if (isNaN(days) || days <= 0) {
      throw new Error("Masa aktif (hari) harus berupa angka positif");
    }
  }
  const expiresAt = new Date(Date.now() + days * 24 * 60 * 60 * 1000).toISOString();

  // Validate daily limit
  const limit = parseInt(dailyLimit, 10);
  if (isNaN(limit) || limit <= 0) {
    throw new Error("Limit harian generate harus berupa angka positif");
  }

  const cleanTier = (tier === "vip") ? "vip" : "pro";
  const voucher = {
    code: cleanCode,
    tier: cleanTier,
    whatsapp: cleanWhatsapp,
    duration,
    durationDays: days,
    expiresAt,
    dailyLimit: limit,
    usage: {},
    addedAt: new Date().toISOString(),
    updatedAt: new Date().toISOString(),
    createdBy,
    createdByName,
    pricePaid: parseFloat(pricePaid) || 0,
    resellerCost: parseFloat(resellerCost) || 0,
    commission: parseFloat(commission) || 0,
  };

  list.push(voucher);
  writeAll(list);
  
  // Push to remote server if we are local PC/RDP
  pushVoucherToRemote(voucher).catch(() => {});
  
  return voucher;
}


export function deleteVoucher(code) {
  const cleanCode = code.trim().toUpperCase();
  const list = readAll();
  const idx = list.findIndex((v) => v.code === cleanCode);
  if (idx < 0) return false;
  
  list.splice(idx, 1);
  writeAll(list);
  
  // Blacklist deleted voucher code to prevent re-sync
  addDeletedVoucher(cleanCode);
  deleteVoucherFromRemote(cleanCode).catch(() => {});
  
  return true;
}


export function updateVoucher(code, patch) {
  const cleanCode = code.trim().toUpperCase();
  const list = readAll();
  const idx = list.findIndex((v) => v.code === cleanCode);
  if (idx < 0) throw new Error("Voucher tidak ditemukan");

  const v = list[idx];

  if (patch.tier !== undefined) {
    v.tier = (patch.tier === "vip") ? "vip" : "pro";
  }
  if (patch.whatsapp !== undefined) {
    v.whatsapp = patch.whatsapp.trim();
  }
  if (patch.dailyLimit !== undefined) {
    const limit = parseInt(patch.dailyLimit, 10);
    if (isNaN(limit) || limit <= 0) {
      throw new Error("Limit harian generate harus berupa angka positif");
    }
    v.dailyLimit = limit;
  }
  if (patch.expiresAt !== undefined) {
    const date = new Date(patch.expiresAt);
    if (isNaN(date.getTime())) {
      throw new Error("Tanggal kedaluwarsa tidak valid");
    }
    v.expiresAt = date.toISOString();
  }
  if (patch.pricePaid !== undefined) {
    v.pricePaid = parseFloat(patch.pricePaid) || 0;
  }
  if (patch.resellerCost !== undefined) {
    v.resellerCost = parseFloat(patch.resellerCost) || 0;
  }
  if (patch.commission !== undefined) {
    v.commission = parseFloat(patch.commission) || 0;
  }
  
  v.updatedAt = new Date().toISOString();

  writeAll(list);
  
  // Push update to remote server
  pushVoucherToRemote(v).catch(() => {});
  
  return v;
}


export function validateVoucher(code) {
  if (!code) return { ok: false, error: "Kode voucher harus diisi" };
  const cleanCode = code.trim().toUpperCase();
  const list = readAll();
  const voucher = list.find((v) => v.code === cleanCode);
  
  if (!voucher) {
    return { ok: false, error: "Kode voucher tidak valid" };
  }
  
  // Check active period
  if (voucher.expiresAt && Date.now() > new Date(voucher.expiresAt).getTime()) {
    return { ok: false, error: "Masa aktif voucher sudah habis (expired)" };
  }
  
  return { ok: true, tier: voucher.tier, voucher };
}

export function hasBatchRecord(code, batchId) {
  if (!batchId) return false;
  const cleanCode = code.trim().toUpperCase();
  const list = readAll();
  const v = list.find((x) => x.code === cleanCode);
  return v && v.usedBatches && v.usedBatches.includes(batchId);
}

export function incrementUsage(code, batchId = null) {
  const cleanCode = code.trim().toUpperCase();
  const list = readAll();
  const idx = list.findIndex((v) => v.code === cleanCode);
  if (idx >= 0) {
    const todayStr = new Date().toISOString().split("T")[0];
    if (!list[idx].usage) list[idx].usage = {};

    if (batchId) {
      if (!list[idx].usedBatches) list[idx].usedBatches = [];
      if (list[idx].usedBatches.includes(batchId)) {
        return true; // Already counted
      }
      list[idx].usedBatches.push(batchId);
    }

    list[idx].usage[todayStr] = (list[idx].usage[todayStr] || 0) + 1;
    list[idx].updatedAt = new Date().toISOString();
    writeAll(list);
    
    // Push update to remote server
    pushVoucherToRemote(list[idx]).catch(() => {});
    
    return true;
  }
  return false;
}

export async function pushVoucherToRemote(vch) {
  const remoteUrl = process.env.REMOTE_SERVER_URL;
  const remotePass = process.env.REMOTE_ADMIN_PASSWORD || process.env.ADMIN_PASSWORD;
  if (!remoteUrl) return;
  const url = remoteUrl.replace(/\/$/, "");
  try {
    await fetch(`${url}/api/admin/vouchers/sync-push`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "x-admin-password": remotePass,
      },
      body: JSON.stringify({ voucher: vch }),
    });
  } catch (err) {
    console.error(`[Sync-Voucher] Gagal push ke remote: ${err.message}`);
  }
}

export async function deleteVoucherFromRemote(code) {
  const remoteUrl = process.env.REMOTE_SERVER_URL;
  const remotePass = process.env.REMOTE_ADMIN_PASSWORD || process.env.ADMIN_PASSWORD;
  if (!remoteUrl) return;
  const url = remoteUrl.replace(/\/$/, "");
  try {
    await fetch(`${url}/api/admin/vouchers/${encodeURIComponent(code)}`, {
      method: "DELETE",
      headers: {
        "x-admin-password": remotePass,
      },
    });
  } catch (err) {
    console.error(`[Sync-Voucher] Gagal hapus di remote: ${err.message}`);
  }
}

export function syncVoucherState(vch) {
  const list = readAll();
  const idx = list.findIndex(v => v.code === vch.code);
  if (idx < 0) {
    list.push(vch);
  } else {
    // Merge usage maps
    const localVch = list[idx];
    const mergedUsage = { ...(localVch.usage || {}) };
    for (const [date, count] of Object.entries(vch.usage || {})) {
      mergedUsage[date] = Math.max(mergedUsage[date] || 0, count);
    }
    const mergedBatches = Array.from(new Set([...(localVch.usedBatches || []), ...(vch.usedBatches || [])]));

    list[idx] = {
      ...vch,
      usage: mergedUsage,
      usedBatches: mergedBatches
    };
  }
  writeAll(list);
  return vch;
}

export async function syncVouchersWithRemote() {
  const remoteUrl = process.env.REMOTE_SERVER_URL;
  const remotePass = process.env.REMOTE_ADMIN_PASSWORD || process.env.ADMIN_PASSWORD;

  if (!remoteUrl) return { ok: false, error: "REMOTE_SERVER_URL not configured" };

  const url = remoteUrl.replace(/\/$/, "");
  console.log(`[Sync-Voucher] Sinkronisasi voucher dengan remote server di ${url}...`);

  try {
    const res = await fetch(`${url}/api/admin/vouchers`, {
      method: "GET",
      headers: {
        "x-admin-password": remotePass,
      },
    });

    if (!res.ok) {
      const data = await res.json().catch(() => ({}));
      throw new Error(data.error || `HTTP ${res.status}`);
    }

    const { vouchers: remoteVouchers } = await res.json();
    if (!Array.isArray(remoteVouchers)) {
      throw new Error("Invalid response format from remote server");
    }

    const localVouchers = readAll();
    const deletedVouchers = readDeletedVouchers();
    let updated = false;

    // 1. Merge remote vouchers ke lokal
    for (const rVch of remoteVouchers) {
      if (deletedVouchers.includes(rVch.code)) {
        continue;
      }

      const lIdx = localVouchers.findIndex(v => v.code === rVch.code);
      if (lIdx < 0) {
        localVouchers.push(rVch);
        updated = true;
        console.log(`[Sync-Voucher] Voucher baru diunduh: ${rVch.code}`);
      } else {
        const lVch = localVouchers[lIdx];
        const rTime = rVch.updatedAt ? new Date(rVch.updatedAt).getTime() : 0;
        const lTime = lVch.updatedAt ? new Date(lVch.updatedAt).getTime() : 0;

        if (rTime > lTime) {
          const mergedUsage = { ...(lVch.usage || {}) };
          for (const [date, count] of Object.entries(rVch.usage || {})) {
            mergedUsage[date] = Math.max(mergedUsage[date] || 0, count);
          }
          const mergedBatches = Array.from(new Set([...(lVch.usedBatches || []), ...(rVch.usedBatches || [])]));

          localVouchers[lIdx] = {
            ...rVch,
            usage: mergedUsage,
            usedBatches: mergedBatches
          };
          updated = true;
          console.log(`[Sync-Voucher] Mengupdate voucher lokal: ${rVch.code}`);
        } else if (lTime > rTime) {
          pushVoucherToRemote(lVch).catch(() => {});
        }
      }
    }

    // 2. Upload local vouchers yang belum ada di remote
    for (const lVch of localVouchers) {
      const rIdx = remoteVouchers.findIndex(v => v.code === lVch.code);
      if (rIdx < 0) {
        console.log(`[Sync-Voucher] Voucher lokal ${lVch.code} tidak ada di remote. Mengupload...`);
        await pushVoucherToRemote(lVch).catch(() => {});
      }
    }

    if (updated) {
      writeAll(localVouchers);
    }

    return { ok: true, msg: "Vouchers sync successful" };
  } catch (err) {
    console.error(`[Sync-Voucher] ❌ Error sinkronisasi: ${err.message}`);
    return { ok: false, error: err.message };
  }
}

