import { v4 as uuidv4 } from "uuid";
import { getAdapter } from "../driver.js";
import { rowToPackage, rowToUserPackage } from "../schemaHelpers.js";

export async function getAllPackages() {
  const db = await getAdapter();
  const rows = db.all(`SELECT * FROM packages ORDER BY createdAt ASC`);
  return rows.map(rowToPackage);
}

export async function getPackageById(id) {
  const db = await getAdapter();
  const row = db.get(`SELECT * FROM packages WHERE id = ?`, [id]);
  return rowToPackage(row);
}

export async function createPackage(data) {
  const db = await getAdapter();
  const id = uuidv4();
  const now = new Date().toISOString();

  const pkg = {
    id,
    name: data.name,
    description: data.description || "",
    rtpMinute: data.rtpMinute,
    rtpDay: data.rtpDay,
    tokenLimitMonthly: data.tokenLimitMonthly,
    creditLimit: data.creditLimit,
    creditToTokenRatio: data.creditToTokenRatio || 1000,
    maxConcurrent: data.maxConcurrent,
    durationDays: data.durationDays,
    price: data.price || 0,
    isActive: data.isActive !== false,
    createdAt: now,
    updatedAt: now,
  };

  db.run(
    `INSERT INTO packages (id, name, description, rtpMinute, rtpDay, tokenLimitMonthly, creditLimit, creditToTokenRatio, maxConcurrent, durationDays, price, isActive, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
    [
      pkg.id,
      pkg.name,
      pkg.description,
      pkg.rtpMinute,
      pkg.rtpDay,
      pkg.tokenLimitMonthly,
      pkg.creditLimit,
      pkg.creditToTokenRatio,
      pkg.maxConcurrent,
      pkg.durationDays,
      pkg.price,
      pkg.isActive ? 1 : 0,
      pkg.createdAt,
      pkg.updatedAt,
    ]
  );

  return pkg;
}

export async function updatePackage(id, data) {
  const db = await getAdapter();
  const existing = await getPackageById(id);
  if (!existing) return null;

  const now = new Date().toISOString();
  const merged = { ...existing, ...data, updatedAt: now };

  db.run(
    `UPDATE packages SET name = ?, description = ?, rtpMinute = ?, rtpDay = ?, tokenLimitMonthly = ?, creditLimit = ?, creditToTokenRatio = ?, maxConcurrent = ?, durationDays = ?, price = ?, isActive = ?, updatedAt = ? WHERE id = ?`,
    [
      merged.name,
      merged.description,
      merged.rtpMinute,
      merged.rtpDay,
      merged.tokenLimitMonthly,
      merged.creditLimit,
      merged.creditToTokenRatio,
      merged.maxConcurrent,
      merged.durationDays,
      merged.price,
      merged.isActive ? 1 : 0,
      merged.updatedAt,
      id,
    ]
  );

  return merged;
}

export async function deletePackage(id) {
  const db = await getAdapter();
  const res = db.run(`DELETE FROM packages WHERE id = ?`, [id]);
  return (res?.changes ?? 0) > 0;
}

export async function getActivePackages() {
  const db = await getAdapter();
  const rows = db.all(`SELECT * FROM packages WHERE isActive = 1 ORDER BY createdAt ASC`);
  return rows.map(rowToPackage);
}

// User-package assignment functions

export async function assignPackage(userId, packageId, overrides = {}) {
  const db = await getAdapter();
  const id = uuidv4();
  const now = new Date().toISOString();

  const pkg = await getPackageById(packageId);
  if (!pkg) throw new Error("Package not found");

  const userPackage = {
    id,
    userId,
    packageId,
    rtpMinuteOverride: overrides.rtpMinuteOverride ?? null,
    rtpDayOverride: overrides.rtpDayOverride ?? null,
    tokenLimitMonthlyOverride: overrides.tokenLimitMonthlyOverride ?? null,
    creditLimitOverride: overrides.creditLimitOverride ?? null,
    maxConcurrentOverride: overrides.maxConcurrentOverride ?? null,
    assignedAt: now,
    expiresAt: overrides.expiresAt || null,
  };

  db.run(
    `INSERT INTO userPackages (id, userId, packageId, rtpMinuteOverride, rtpDayOverride, tokenLimitMonthlyOverride, creditLimitOverride, maxConcurrentOverride, assignedAt, expiresAt) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
    [
      userPackage.id,
      userPackage.userId,
      userPackage.packageId,
      userPackage.rtpMinuteOverride,
      userPackage.rtpDayOverride,
      userPackage.tokenLimitMonthlyOverride,
      userPackage.creditLimitOverride,
      userPackage.maxConcurrentOverride,
      userPackage.assignedAt,
      userPackage.expiresAt,
    ]
  );

  // Update rateLimits for backward compat
  const limits = {
    rtpMinute: overrides.rtpMinuteOverride ?? pkg.rtpMinute,
    rtpDay: overrides.rtpDayOverride ?? pkg.rtpDay,
    tokenLimitMonthly: overrides.tokenLimitMonthlyOverride ?? pkg.tokenLimitMonthly,
    creditLimit: overrides.creditLimitOverride ?? pkg.creditLimit,
    maxConcurrent: overrides.maxConcurrentOverride ?? pkg.maxConcurrent,
  };

  // Use dynamic import to avoid circular dependency
  const { updateLimits } = await import("./rateLimitRepo.js");
  await updateLimits(userId, limits);

  return userPackage;
}

export async function getUserPackage(userId) {
  const db = await getAdapter();
  const row = db.get(
    `SELECT up.*, p.* FROM userPackages up LEFT JOIN packages p ON up.packageId = p.id WHERE up.userId = ?`,
    [userId]
  );

  if (!row) return null;

  const userPkg = rowToUserPackage(row);
  const pkg = rowToPackage(row);

  // Merge package defaults with user overrides
  return {
    userId: userPkg.userId,
    packageId: userPkg.packageId,
    rtpMinute: userPkg.rtpMinuteOverride ?? pkg?.rtpMinute,
    rtpDay: userPkg.rtpDayOverride ?? pkg?.rtpDay,
    tokenLimitMonthly: userPkg.tokenLimitMonthlyOverride ?? pkg?.tokenLimitMonthly,
    creditLimit: userPkg.creditLimitOverride ?? pkg?.creditLimit,
    maxConcurrent: userPkg.maxConcurrentOverride ?? pkg?.maxConcurrent,
    assignedAt: userPkg.assignedAt,
    expiresAt: userPkg.expiresAt,
    packageName: pkg?.name,
    packageDescription: pkg?.description,
  };
}

export async function removeUserPackage(userId) {
  const db = await getAdapter();
  const res = db.run(`DELETE FROM userPackages WHERE userId = ?`, [userId]);
  return (res?.changes ?? 0) > 0;
}

export async function updateUserPackageOverrides(userId, overrides) {
  const db = await getAdapter();
  const now = new Date().toISOString();

  const fields = [];
  const values = [];

  if (overrides.rtpMinuteOverride !== undefined) {
    fields.push("rtpMinuteOverride = ?");
    values.push(overrides.rtpMinuteOverride);
  }
  if (overrides.rtpDayOverride !== undefined) {
    fields.push("rtpDayOverride = ?");
    values.push(overrides.rtpDayOverride);
  }
  if (overrides.tokenLimitMonthlyOverride !== undefined) {
    fields.push("tokenLimitMonthlyOverride = ?");
    values.push(overrides.tokenLimitMonthlyOverride);
  }
  if (overrides.creditLimitOverride !== undefined) {
    fields.push("creditLimitOverride = ?");
    values.push(overrides.creditLimitOverride);
  }
  if (overrides.maxConcurrentOverride !== undefined) {
    fields.push("maxConcurrentOverride = ?");
    values.push(overrides.maxConcurrentOverride);
  }

  if (fields.length === 0) return null;

  values.push(userId);

  db.run(`UPDATE userPackages SET ${fields.join(", ")} WHERE userId = ?`, values);

  // Update rateLimits for backward compat
  const userPkg = await getUserPackage(userId);
  if (userPkg) {
    const limits = {
      rtpMinute: userPkg.rtpMinute,
      rtpDay: userPkg.rtpDay,
      tokenLimitMonthly: userPkg.tokenLimitMonthly,
      creditLimit: userPkg.creditLimit,
      maxConcurrent: userPkg.maxConcurrent,
    };
    const { updateLimits } = await import("./rateLimitRepo.js");
    await updateLimits(userId, limits);
  }

  return await getUserPackage(userId);
}
