import { sql } from 'drizzle-orm';
import { CommandNotFoundError } from './errors.js';
import { mapCommandRow, selectCommandById } from './shared.js';
import type {
  CommandDb,
  CommandStatus,
  RenewCommandLeaseInput,
  RenewCommandLeaseResult,
} from './types.js';

interface UpdatedCommandRow {
  id: string;
  command_key: string;
  command_type: string;
  aggregate_type: string;
  aggregate_id: string;
  payload_hash: string;
  payload: unknown;
  status: CommandStatus;
  claimed_by: string;
  claimed_at: Date | string;
  claim_generation: number | string;
  lease_expires_at: Date | string;
  completed_at: Date | string | null;
  failed_at: Date | string | null;
  result_payload: unknown;
  failure_code: string | null;
  failure_message: string | null;
}

type UpdatedCommandRowResult = { rows: UpdatedCommandRow[] };

export async function renewCommandLease(
  db: CommandDb,
  input: RenewCommandLeaseInput,
): Promise<RenewCommandLeaseResult> {
  const updated = (await db.execute(sql`
    UPDATE "command_records"
    SET "lease_expires_at" = CURRENT_TIMESTAMP + INTERVAL '10 minutes'
    WHERE "id" = ${input.commandId}::uuid
      AND "status" = 'CLAIMED'
      AND "claimed_by" = ${input.expectedClaimedBy}
      AND "claim_generation" = ${input.expectedClaimGeneration}
      AND "lease_expires_at" > CURRENT_TIMESTAMP
    RETURNING
      "id", "command_key", "command_type", "aggregate_type", "aggregate_id",
      "payload_hash", "payload", "status", "claimed_by", "claimed_at",
      "claim_generation", "lease_expires_at", "completed_at", "failed_at",
      "result_payload", "failure_code", "failure_message"
  `)) as UpdatedCommandRowResult;
  const updatedRow = updated.rows[0];
  if (updatedRow) return { renewed: true, record: mapCommandRow(updatedRow) };
  const existing = await selectCommandById(db, input.commandId);
  if (!existing) throw new CommandNotFoundError(input.commandId);
  return { renewed: false, record: existing };
}
