/**
 * Credential lifecycle management operations
 */

import { query } from './client';

export interface CredentialStatusHistory {
  id: string;
  credential_id: string;
  status: string;
  reason?: string;
  changed_by?: string;
  changed_at: Date;
  metadata?: unknown;
}

export interface CredentialRevocation {
  id: string;
  credential_id: string;
  issuer_did: string;
  revocation_reason?: string;
  revoked_by?: string;
  revoked_at: Date;
  revocation_list_index?: number;
}

export interface CredentialAuditLog {
  id: string;
  credential_id: string;
  issuer_did: string;
  subject_did: string;
  credential_type: string[];
  action: 'issued' | 'revoked' | 'verified' | 'renewed';
  performed_by?: string;
  performed_at: Date;
  metadata?: unknown;
  ip_address?: string;
  user_agent?: string;
}

// Note: CredentialTemplate operations are now in credential-templates.ts
// This file focuses on lifecycle operations (status history, revocation, audit)

// Credential Status History operations
export async function addCredentialStatusHistory(
  history: Omit<CredentialStatusHistory, 'id' | 'changed_at'>
): Promise<CredentialStatusHistory> {
  const result = await query<CredentialStatusHistory>(
    `INSERT INTO credential_status_history (credential_id, status, reason, changed_by, metadata)
     VALUES ($1, $2, $3, $4, $5)
     RETURNING *`,
    [
      history.credential_id,
      history.status,
      history.reason || null,
      history.changed_by || null,
      history.metadata ? JSON.stringify(history.metadata) : null,
    ]
  );
  return result.rows[0]!;
}

export async function getCredentialStatusHistory(
  credentialId: string
): Promise<CredentialStatusHistory[]> {
  const result = await query<CredentialStatusHistory>(
    `SELECT * FROM credential_status_history 
     WHERE credential_id = $1 
     ORDER BY changed_at DESC`,
    [credentialId]
  );
  return result.rows;
}

// Credential Revocation operations
export async function revokeCredential(
  revocation: Omit<CredentialRevocation, 'id' | 'revoked_at' | 'revocation_list_index'>
): Promise<CredentialRevocation> {
  // First, update the credential as revoked
  await query(
    `UPDATE verifiable_credentials 
     SET revoked = TRUE, updated_at = NOW() 
     WHERE credential_id = $1`,
    [revocation.credential_id]
  );

  // Get the next revocation list index
  const indexResult = await query<{ max_index: number | null }>(
    `SELECT MAX(revocation_list_index) as max_index 
     FROM credential_revocation_registry 
     WHERE issuer_did = $1`,
    [revocation.issuer_did]
  );
  const nextIndex = (indexResult.rows[0]?.max_index ?? -1) + 1;

  // Add to revocation registry
  const result = await query<CredentialRevocation>(
    `INSERT INTO credential_revocation_registry 
     (credential_id, issuer_did, revocation_reason, revoked_by, revocation_list_index)
     VALUES ($1, $2, $3, $4, $5)
     RETURNING *`,
    [
      revocation.credential_id,
      revocation.issuer_did,
      revocation.revocation_reason || null,
      revocation.revoked_by || null,
      nextIndex,
    ]
  );
  return result.rows[0]!;
}

export async function isCredentialRevoked(credentialId: string): Promise<boolean> {
  const result = await query<{ revoked: boolean }>(
    `SELECT revoked FROM verifiable_credentials WHERE credential_id = $1`,
    [credentialId]
  );
  return result.rows[0]?.revoked ?? false;
}

export async function getRevocationRegistry(
  issuerDid: string,
  limit = 100,
  offset = 0
): Promise<CredentialRevocation[]> {
  const result = await query<CredentialRevocation>(
    `SELECT * FROM credential_revocation_registry 
     WHERE issuer_did = $1 
     ORDER BY revocation_list_index DESC 
     LIMIT $2 OFFSET $3`,
    [issuerDid, limit, offset]
  );
  return result.rows;
}

// Credential Audit Log operations
export async function logCredentialAction(
  audit: Omit<CredentialAuditLog, 'id' | 'performed_at'>
): Promise<CredentialAuditLog> {
  const result = await query<CredentialAuditLog>(
    `INSERT INTO credential_issuance_audit 
     (credential_id, issuer_did, subject_did, credential_type, action, performed_by, metadata, ip_address, user_agent)
     VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
     RETURNING *`,
    [
      audit.credential_id,
      audit.issuer_did,
      audit.subject_did,
      audit.credential_type,
      audit.action,
      audit.performed_by || null,
      audit.metadata ? JSON.stringify(audit.metadata) : null,
      audit.ip_address || null,
      audit.user_agent || null,
    ]
  );
  return result.rows[0]!;
}

export async function getCredentialAuditLog(
  credentialId: string,
  limit = 100
): Promise<CredentialAuditLog[]> {
  const result = await query<CredentialAuditLog>(
    `SELECT * FROM credential_issuance_audit 
     WHERE credential_id = $1 
     ORDER BY performed_at DESC 
     LIMIT $2`,
    [credentialId, limit]
  );
  return result.rows;
}

export async function getExpiringCredentials(
  daysAhead: number,
  limit = 100
): Promise<Array<{ credential_id: string; expiration_date: Date; subject_did: string; issuer_did: string; credential_type: string[]; credential_subject: unknown }>> {
  const result = await query<{ credential_id: string; expiration_date: Date; subject_did: string; issuer_did: string; credential_type: string[]; credential_subject: unknown }>(
    `SELECT credential_id, expiration_date, subject_did, issuer_did, credential_type, credential_subject
     FROM verifiable_credentials 
     WHERE expiration_date IS NOT NULL 
       AND expiration_date > NOW() 
       AND expiration_date < NOW() + INTERVAL '${daysAhead} days'
       AND revoked = FALSE
     ORDER BY expiration_date ASC
     LIMIT $1`,
    [limit]
  );
  return result.rows;
}

