import { prisma } from "../lib/prisma.js";
import { runFormEngineForClient } from "../lib/form-engine.js";

function getArgValue(flag: string) {
  const index = process.argv.indexOf(flag);
  if (index < 0) {
    return null;
  }
  return process.argv[index + 1] ?? null;
}

async function resolveClient() {
  const explicitClientId = getArgValue("--client-id");
  if (explicitClientId) {
    const [client] = await prisma.$queryRaw<Array<{
      id: string;
      law_firm_id: string;
      first_name: string;
      last_name: string;
    }>>`
      SELECT id, law_firm_id, first_name, last_name
      FROM clients
      WHERE id = ${explicitClientId}
      LIMIT 1
    `;
    return client ?? null;
  }

  const [client] = await prisma.$queryRaw<Array<{
    id: string;
    law_firm_id: string;
    first_name: string;
    last_name: string;
  }>>`
    SELECT id, law_firm_id, first_name, last_name
    FROM clients
    WHERE UPPER(first_name) LIKE '%HOMAIRA%'
       OR UPPER(last_name) LIKE '%HOSSAIN%'
    ORDER BY created_at DESC
    LIMIT 1
  `;

  return client ?? null;
}

async function resolveActorUserId(lawFirmId: string) {
  const explicitUserId = getArgValue("--user-id");
  if (explicitUserId) {
    return explicitUserId;
  }

  const [membership] = await prisma.$queryRaw<Array<{ user_id: string }>>`
    SELECT wm.user_id
    FROM workspace_memberships wm
    JOIN users u ON u.id = wm.user_id
    WHERE wm.law_firm_id = ${lawFirmId}
      AND u.deleted_at IS NULL
      AND u.is_active = 1
    ORDER BY wm.is_default DESC, wm.joined_at ASC
    LIMIT 1
  `;

  return membership?.user_id ?? null;
}

async function resolveCaseId(lawFirmId: string, clientId: string) {
  const explicitCaseId = getArgValue("--case-id");
  if (explicitCaseId) {
    return explicitCaseId;
  }

  const [caseRow] = await prisma.$queryRaw<Array<{ id: string }>>`
    SELECT id
    FROM cases
    WHERE law_firm_id = ${lawFirmId}
      AND client_id = ${clientId}
      AND deleted_at IS NULL
    ORDER BY created_at DESC
    LIMIT 1
  `;

  return caseRow?.id ?? null;
}

async function main() {
  const client = await resolveClient();
  if (!client) {
    throw new Error("Unable to resolve the HOMAIRA BINTA HOSSAIN client in the current database.");
  }

  const actorUserId = await resolveActorUserId(client.law_firm_id);
  if (!actorUserId) {
    throw new Error("Unable to resolve an active actor user for the client workspace.");
  }

  const caseId = await resolveCaseId(client.law_firm_id, client.id);
  const agentCode = getArgValue("--agent-code");
  const targetCoverage = Number(getArgValue("--target-coverage") ?? "0.8");
  const maxIterations = Number(getArgValue("--max-iterations") ?? "2");

  const result = await runFormEngineForClient({
    lawFirmId: client.law_firm_id,
    actorUserId,
    clientId: client.id,
    caseId,
    agentCodes: agentCode ? [agentCode] : ["uscis_i_485"],
    targetCoverage: Number.isFinite(targetCoverage) ? targetCoverage : 0.8,
    maxIterations: Number.isFinite(maxIterations) ? maxIterations : 2,
  });

  console.log(
    JSON.stringify(
      {
        runId: result.runId,
        clientId: result.clientId,
        caseId: result.caseId,
        caseAnalysis: result.caseAnalysis,
        results: result.results.map((item) => ({
          agentCode: item.agentCode,
          formName: item.formName,
          percentFilled: Number(item.metrics.percentFilled.toFixed(4)),
          percentHighConfidence: Number(item.metrics.percentHighConfidence.toFixed(4)),
          questionsNeeded: item.metrics.questionsNeeded,
          reuseFromOtherForms: item.metrics.reuseFromOtherForms,
          learningGainFromMemory: Number(item.metrics.learningGainFromMemory.toFixed(4)),
          conflictRate: Number(item.metrics.conflictRate.toFixed(4)),
          iterations: item.iterations,
          unresolvedFields: item.unresolvedFields.slice(0, 30),
          fileName: item.fileName,
        })),
      },
      null,
      2,
    ),
  );
}

main()
  .catch((error) => {
    console.error(error);
    process.exitCode = 1;
  })
  .finally(async () => {
    await prisma.$disconnect();
  });
