import { v4 as uuidv4 } from "uuid";
import { getAdapter } from "../driver.js";

function rowToUsageRecord(row) {
  if (!row) return null;
  return {
    id: row.id,
    userId: row.userId,
    apiKeyId: row.apiKeyId,
    model: row.model,
    inputTokens: row.inputTokens || 0,
    outputTokens: row.outputTokens || 0,
    totalTokens: row.totalTokens || 0,
    cost: row.cost || 0,
    creditUsed: row.creditUsed || 0,
    status: row.status,
    errorMessage: row.errorMessage,
    endpoint: row.endpoint,
    timestamp: row.timestamp,
  };
}

export async function logUsage(data) {
  const db = await getAdapter();
  const id = uuidv4();
  const timestamp = data.timestamp || new Date().toISOString();

  await db.run(
    `INSERT INTO usage_records (id, userId, apiKeyId, model, inputTokens, outputTokens, totalTokens, cost, creditUsed, status, errorMessage, endpoint, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
    [
      id,
      data.userId,
      data.apiKeyId,
      data.model,
      data.inputTokens || 0,
      data.outputTokens || 0,
      data.totalTokens || 0,
      data.cost || 0,
      data.creditUsed || 0,
      data.status,
      data.errorMessage,
      data.endpoint,
      timestamp,
    ]
  );

  return id;
}

export async function getUsageByUser(userId, filters = {}) {
  const db = await getAdapter();
  const {
    startDate,
    endDate,
    model,
    page = 1,
    limit = 50,
  } = filters;

  const safeLimit = Math.min(Math.max(limit, 1), 100);
  const offset = (page - 1) * safeLimit;

  let whereClauses = ["userId = ?"];
  let params = [userId];

  if (startDate) {
    whereClauses.push("timestamp >= ?");
    params.push(startDate);
  }
  if (endDate) {
    whereClauses.push("timestamp <= ?");
    params.push(endDate);
  }
  if (model) {
    whereClauses.push("model = ?");
    params.push(model);
  }

  const whereClause = whereClauses.length > 0 ? `WHERE ${whereClauses.join(" AND ")}` : "";
  const sqlQuery = `SELECT * FROM usage_records ${whereClause} ORDER BY timestamp DESC LIMIT ? OFFSET ?`;
  
  const rows = await db.all(sqlQuery, [...params, safeLimit, offset]);

  const countQuery = `SELECT COUNT(*) as total FROM usage_records ${whereClause}`;
  const countRow = await db.get(countQuery, params);
  const total = countRow?.total || 0;
  const totalPages = Math.ceil(total / safeLimit);

  return {
    records: rows.map(rowToUsageRecord),
    total,
    page,
    totalPages,
  };
}

export async function getUsageSummary(userId, startDate, endDate) {
  const db = await getAdapter();
  let whereClauses = ["userId = ?"];
  let params = [userId];

  if (startDate) {
    whereClauses.push("timestamp >= ?");
    params.push(startDate);
  }
  if (endDate) {
    whereClauses.push("timestamp <= ?");
    params.push(endDate);
  }

  const whereClause = whereClauses.length > 0 ? `WHERE ${whereClauses.join(" AND ")}` : "";
  const sqlQuery = `
    SELECT 
      COALESCE(SUM(inputTokens), 0) as totalInputTokens,
      COALESCE(SUM(outputTokens), 0) as totalOutputTokens,
      COALESCE(SUM(totalTokens), 0) as totalTokens,
      COALESCE(SUM(cost), 0) as totalCost,
      COALESCE(SUM(creditUsed), 0) as totalCreditUsed,
      COUNT(*) as requestCount,
      COUNT(CASE WHEN status = 'error' THEN 1 END) as errorCount
    FROM usage_records 
    ${whereClause}
  `;

  const row = await db.get(sqlQuery, params);
  return {
    totalInputTokens: row?.totalInputTokens || 0,
    totalOutputTokens: row?.totalOutputTokens || 0,
    totalTokens: row?.totalTokens || 0,
    totalCost: row?.totalCost || 0,
    totalCreditUsed: row?.totalCreditUsed || 0,
    requestCount: row?.requestCount || 0,
    errorCount: row?.errorCount || 0,
  };
}

export async function getUsageByModel(userId, startDate, endDate) {
  const db = await getAdapter();
  let whereClauses = ["userId = ?"];
  let params = [userId];

  if (startDate) {
    whereClauses.push("timestamp >= ?");
    params.push(startDate);
  }
  if (endDate) {
    whereClauses.push("timestamp <= ?");
    params.push(endDate);
  }

  const whereClause = whereClauses.length > 0 ? `WHERE ${whereClauses.join(" AND ")}` : "";
  const sqlQuery = `
    SELECT 
      model,
      COUNT(*) as requestCount,
      COALESCE(SUM(totalTokens), 0) as totalTokens,
      COALESCE(SUM(cost), 0) as totalCost
    FROM usage_records 
    ${whereClause}
    GROUP BY model
    ORDER BY totalTokens DESC
  `;

  const rows = await db.all(sqlQuery, params);
  return rows.map((row) => ({
    model: row.model,
    requestCount: row.requestCount,
    totalTokens: row.totalTokens,
    totalCost: row.totalCost,
  }));
}

export async function getUsageDaily(userId, startDate, endDate) {
  const db = await getAdapter();
  let whereClauses = ["userId = ?"];
  let params = [userId];

  if (startDate) {
    whereClauses.push("timestamp >= ?");
    params.push(startDate);
  }
  if (endDate) {
    whereClauses.push("timestamp <= ?");
    params.push(endDate);
  }

  const whereClause = whereClauses.length > 0 ? `WHERE ${whereClauses.join(" AND ")}` : "";

  // SQLite specific date formatting
  const sqlQuery = `
    SELECT 
      DATE(timestamp) as date,
      COUNT(*) as requestCount,
      COALESCE(SUM(totalTokens), 0) as totalTokens,
      COALESCE(SUM(cost), 0) as totalCost
    FROM usage_records 
    ${whereClause}
    GROUP BY DATE(timestamp)
    ORDER BY date DESC
  `;

  const rows = await db.all(sqlQuery, params);
  return rows.map((row) => ({
    date: row.date,
    requestCount: row.requestCount,
    totalTokens: row.totalTokens,
    totalCost: row.totalCost,
  }));
}

export async function getAllUsersUsage(startDate, endDate) {
  const db = await getAdapter();
  let whereClauses = [];
  let params = [];

  if (startDate) {
    whereClauses.push("timestamp >= ?");
    params.push(startDate);
  }
  if (endDate) {
    whereClauses.push("timestamp <= ?");
    params.push(endDate);
  }

  const whereClause = whereClauses.length > 0 ? `WHERE ${whereClauses.join(" AND ")}` : "";
  
  // Assuming a 'users' table exists with 'id' and 'username' columns
  const sqlQuery = `
    SELECT 
      ur.userId,
      u.username,
      COUNT(ur.id) as requestCount,
      COALESCE(SUM(ur.totalTokens), 0) as totalTokens,
      COALESCE(SUM(ur.cost), 0) as totalCost
    FROM usage_records ur
    LEFT JOIN users u ON ur.userId = u.id
    ${whereClause}
    GROUP BY ur.userId, u.username
    ORDER BY totalTokens DESC
  `;

  const rows = await db.all(sqlQuery, params);
  return rows.map((row) => ({
    userId: row.userId,
    username: row.username,
    requestCount: row.requestCount,
    totalTokens: row.totalTokens,
    totalCost: row.totalCost,
  }));
}

export async function cleanupOldRecords(daysToKeep = 90) {
  const db = await getAdapter();
  const cutoffDate = new Date();
  cutoffDate.setDate(cutoffDate.getDate() - daysToKeep);
  const cutoffISOString = cutoffDate.toISOString();

  const res = await db.run(
    `DELETE FROM usage_records WHERE timestamp < ?`,
    [cutoffISOString]
  );

  return { deleted: res?.changes || 0 };
}
