/**
 * eResidency Application Database Operations
 */

import { query } from './client';
import {
  type eResidencyApplication,
  type eCitizenshipApplication,
  ApplicationStatus,
} from '@the-order/schemas';

/**
 * Map database row to application object
 */
function mapRowToApplication(row: any): eResidencyApplication {
  return {
    id: row.id,
    applicantDid: row.applicant_did || undefined,
    email: row.email,
    givenName: row.given_name,
    familyName: row.family_name,
    dateOfBirth: row.date_of_birth ? (row.date_of_birth instanceof Date ? row.date_of_birth.toISOString().split('T')[0] : row.date_of_birth) : undefined,
    nationality: row.nationality || undefined,
    phone: row.phone || undefined,
    address: row.address ? (typeof row.address === 'string' ? JSON.parse(row.address) : row.address) : undefined,
    deviceFingerprint: row.device_fingerprint || undefined,
    identityDocument: row.identity_document
      ? typeof row.identity_document === 'string'
        ? JSON.parse(row.identity_document)
        : row.identity_document
      : undefined,
    selfieLiveness: row.selfie_liveness
      ? typeof row.selfie_liveness === 'string'
        ? JSON.parse(row.selfie_liveness)
        : row.selfie_liveness
      : undefined,
    status: row.status as ApplicationStatus,
    submittedAt: row.submitted_at ? (row.submitted_at instanceof Date ? row.submitted_at.toISOString() : row.submitted_at) : undefined,
    reviewedAt: row.reviewed_at ? (row.reviewed_at instanceof Date ? row.reviewed_at.toISOString() : row.reviewed_at) : undefined,
    reviewedBy: row.reviewed_by || undefined,
    rejectionReason: row.rejection_reason || undefined,
    kycStatus: row.kyc_status || undefined,
    sanctionsStatus: row.sanctions_status || undefined,
    pepStatus: row.pep_status || undefined,
    riskScore: row.risk_score ? parseFloat(String(row.risk_score)) : undefined,
    kycResults: row.kyc_results ? (typeof row.kyc_results === 'string' ? JSON.parse(row.kyc_results) : row.kyc_results) : undefined,
    sanctionsResults: row.sanctions_results ? (typeof row.sanctions_results === 'string' ? JSON.parse(row.sanctions_results) : row.sanctions_results) : undefined,
    riskAssessment: row.risk_assessment ? (typeof row.risk_assessment === 'string' ? JSON.parse(row.risk_assessment) : row.risk_assessment) : undefined,
    createdAt: row.created_at instanceof Date ? row.created_at.toISOString() : row.created_at,
    updatedAt: row.updated_at instanceof Date ? row.updated_at.toISOString() : row.updated_at,
  };
}

/**
 * Create eResidency application
 */
export async function createEResidencyApplication(
  application: Omit<eResidencyApplication, 'id' | 'createdAt' | 'updatedAt'>
): Promise<eResidencyApplication> {
  const result = await query<eResidencyApplication>(
    `INSERT INTO eresidency_applications 
     (applicant_did, email, given_name, family_name, date_of_birth, nationality, phone, address, 
      device_fingerprint, identity_document, selfie_liveness, status, kyc_status, sanctions_status, pep_status)
     VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)
     RETURNING *`,
    [
      application.applicantDid || null,
      application.email,
      application.givenName,
      application.familyName,
      application.dateOfBirth || null,
      application.nationality || null,
      application.phone || null,
      application.address ? JSON.stringify(application.address) : null,
      application.deviceFingerprint || null,
      application.identityDocument ? JSON.stringify(application.identityDocument) : null,
      application.selfieLiveness ? JSON.stringify(application.selfieLiveness) : null,
      application.status,
      application.kycStatus || null,
      application.sanctionsStatus || null,
      application.pepStatus || null,
    ]
  );

  return mapRowToApplication(result.rows[0]!);
}

/**
 * Get eResidency application by ID
 */
export async function getEResidencyApplicationById(id: string): Promise<eResidencyApplication | null> {
  const result = await query<eResidencyApplication>(
    'SELECT * FROM eresidency_applications WHERE id = $1',
    [id]
  );

  if (!result.rows[0]) {
    return null;
  }

  return mapRowToApplication(result.rows[0]);
}

/**
 * Update eResidency application
 */
export async function updateEResidencyApplication(
  id: string,
  updates: {
    status?: ApplicationStatus;
    kycStatus?: 'pending' | 'passed' | 'failed' | 'requires_edd';
    sanctionsStatus?: 'pending' | 'clear' | 'flag';
    pepStatus?: 'pending' | 'clear' | 'flag';
    riskScore?: number;
    kycResults?: unknown;
    sanctionsResults?: unknown;
    riskAssessment?: unknown;
    reviewedAt?: string;
    reviewedBy?: string;
    rejectionReason?: string;
  }
): Promise<eResidencyApplication> {
  const fields: string[] = [];
  const values: unknown[] = [];
  let paramIndex = 1;

  if (updates.status !== undefined) {
    fields.push(`status = $${paramIndex++}`);
    values.push(updates.status);
  }
  if (updates.kycStatus !== undefined) {
    fields.push(`kyc_status = $${paramIndex++}`);
    values.push(updates.kycStatus);
  }
  if (updates.sanctionsStatus !== undefined) {
    fields.push(`sanctions_status = $${paramIndex++}`);
    values.push(updates.sanctionsStatus);
  }
  if (updates.pepStatus !== undefined) {
    fields.push(`pep_status = $${paramIndex++}`);
    values.push(updates.pepStatus);
  }
  if (updates.riskScore !== undefined) {
    fields.push(`risk_score = $${paramIndex++}`);
    values.push(updates.riskScore);
  }
  if (updates.kycResults !== undefined) {
    fields.push(`kyc_results = $${paramIndex++}`);
    values.push(JSON.stringify(updates.kycResults));
  }
  if (updates.sanctionsResults !== undefined) {
    fields.push(`sanctions_results = $${paramIndex++}`);
    values.push(JSON.stringify(updates.sanctionsResults));
  }
  if (updates.riskAssessment !== undefined) {
    fields.push(`risk_assessment = $${paramIndex++}`);
    values.push(JSON.stringify(updates.riskAssessment));
  }
  if (updates.reviewedAt !== undefined) {
    fields.push(`reviewed_at = $${paramIndex++}`);
    values.push(updates.reviewedAt);
  }
  if (updates.reviewedBy !== undefined) {
    fields.push(`reviewed_by = $${paramIndex++}`);
    values.push(updates.reviewedBy);
  }
  if (updates.rejectionReason !== undefined) {
    fields.push(`rejection_reason = $${paramIndex++}`);
    values.push(updates.rejectionReason);
  }

  fields.push(`updated_at = NOW()`);
  values.push(id);

  const result = await query<eResidencyApplication>(
    `UPDATE eresidency_applications SET ${fields.join(', ')} WHERE id = $${paramIndex} RETURNING *`,
    values
  );

  return mapRowToApplication(result.rows[0]!);
}

/**
 * Get review queue
 */
export async function getReviewQueue(filters: {
  riskBand?: 'low' | 'medium' | 'high';
  status?: ApplicationStatus;
  assignedTo?: string;
  limit?: number;
  offset?: number;
}): Promise<{ applications: eResidencyApplication[]; total: number }> {
  const conditions: string[] = [];
  const params: unknown[] = [];
  let paramIndex = 1;

  if (filters.riskBand) {
    // Map risk band to risk score range
    const riskRanges: Record<'low' | 'medium' | 'high', [number, number]> = {
      low: [0, 0.3],
      medium: [0.3, 0.8],
      high: [0.8, 1.0],
    };
    const [min, max] = riskRanges[filters.riskBand];
    conditions.push(`risk_score >= $${paramIndex++} AND risk_score < $${paramIndex++}`);
    params.push(min, max);
  }

  if (filters.status) {
    conditions.push(`status = $${paramIndex++}`);
    params.push(filters.status);
  }

  if (filters.assignedTo) {
    conditions.push(`reviewed_by = $${paramIndex++}`);
    params.push(filters.assignedTo);
  }

  const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
  const limit = filters.limit || 50;
  const offset = filters.offset || 0;

  // Get total count
  const countResult = await query<{ count: string }>(
    `SELECT COUNT(*) as count FROM eresidency_applications ${whereClause}`,
    params
  );
  const total = parseInt(countResult.rows[0]?.count || '0', 10);

  // Get applications
  const result = await query<eResidencyApplication>(
    `SELECT * FROM eresidency_applications 
     ${whereClause}
     ORDER BY created_at DESC 
     LIMIT $${paramIndex++} OFFSET $${paramIndex++}`,
    [...params, limit, offset]
  );

  const applications = result.rows.map((row) => mapRowToApplication(row));

  return { applications, total };
}

/**
 * Create eCitizenship application
 */
export async function createECitizenshipApplication(
  application: Omit<eCitizenshipApplication, 'id' | 'createdAt' | 'updatedAt'>
): Promise<eCitizenshipApplication> {
  const result = await query<any>(
    `INSERT INTO ecitizenship_applications 
     (applicant_did, resident_did, residency_tenure, sponsor_did, service_merit, video_interview, 
      background_attestations, oath_ceremony, status)
     VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
     RETURNING *`,
    [
      application.applicantDid,
      application.residentDid,
      application.residencyTenure,
      application.sponsorDid || null,
      application.serviceMerit ? JSON.stringify(application.serviceMerit) : null,
      application.videoInterview ? JSON.stringify(application.videoInterview) : null,
      application.backgroundAttestations ? JSON.stringify(application.backgroundAttestations) : null,
      application.oathCeremony ? JSON.stringify(application.oathCeremony) : null,
      application.status,
    ]
  );

  const row: any = result.rows[0]!;
  return {
    id: row.id,
    applicantDid: row.applicant_did,
    residentDid: row.resident_did,
    residencyTenure: row.residency_tenure || undefined,
    sponsorDid: row.sponsor_did || undefined,
    serviceMerit: row.service_merit
      ? typeof row.service_merit === 'string'
        ? JSON.parse(row.service_merit)
        : row.service_merit
      : undefined,
    videoInterview: row.video_interview
      ? typeof row.video_interview === 'string'
        ? JSON.parse(row.video_interview)
        : row.video_interview
      : undefined,
    backgroundAttestations: row.background_attestations
      ? typeof row.background_attestations === 'string'
        ? JSON.parse(row.background_attestations)
        : row.background_attestations
      : undefined,
    oathCeremony: row.oath_ceremony
      ? typeof row.oath_ceremony === 'string'
        ? JSON.parse(row.oath_ceremony)
        : row.oath_ceremony
      : undefined,
    status: row.status as ApplicationStatus,
    submittedAt: row.submitted_at ? (row.submitted_at instanceof Date ? row.submitted_at.toISOString() : row.submitted_at) : undefined,
    reviewedAt: row.reviewed_at ? (row.reviewed_at instanceof Date ? row.reviewed_at.toISOString() : row.reviewed_at) : undefined,
    reviewedBy: row.reviewed_by || undefined,
    rejectionReason: row.rejection_reason || undefined,
    createdAt: row.created_at instanceof Date ? row.created_at.toISOString() : row.created_at,
    updatedAt: row.updated_at instanceof Date ? row.updated_at.toISOString() : row.updated_at,
  };
}

/**
 * Get eCitizenship application by ID
 */
export async function getECitizenshipApplicationById(id: string): Promise<eCitizenshipApplication | null> {
  const result = await query<any>(
    'SELECT * FROM ecitizenship_applications WHERE id = $1',
    [id]
  );

  if (!result.rows[0]) {
    return null;
  }

  const row: any = result.rows[0]!;
  return {
    id: row.id,
    applicantDid: row.applicant_did,
    residentDid: row.resident_did,
    residencyTenure: row.residency_tenure || undefined,
    sponsorDid: row.sponsor_did || undefined,
    serviceMerit: row.service_merit
      ? typeof row.service_merit === 'string'
        ? JSON.parse(row.service_merit)
        : row.service_merit
      : undefined,
    videoInterview: row.video_interview
      ? typeof row.video_interview === 'string'
        ? JSON.parse(row.video_interview)
        : row.video_interview
      : undefined,
    backgroundAttestations: row.background_attestations
      ? typeof row.background_attestations === 'string'
        ? JSON.parse(row.background_attestations)
        : row.background_attestations
      : undefined,
    oathCeremony: row.oath_ceremony
      ? typeof row.oath_ceremony === 'string'
        ? JSON.parse(row.oath_ceremony)
        : row.oath_ceremony
      : undefined,
    status: row.status as ApplicationStatus,
    submittedAt: row.submitted_at ? (row.submitted_at instanceof Date ? row.submitted_at.toISOString() : row.submitted_at) : undefined,
    reviewedAt: row.reviewed_at ? (row.reviewed_at instanceof Date ? row.reviewed_at.toISOString() : row.reviewed_at) : undefined,
    reviewedBy: row.reviewed_by || undefined,
    rejectionReason: row.rejection_reason || undefined,
    createdAt: row.created_at instanceof Date ? row.created_at.toISOString() : row.created_at,
    updatedAt: row.updated_at instanceof Date ? row.updated_at.toISOString() : row.updated_at,
  };
}

/**
 * Update eCitizenship application
 */
export async function updateECitizenshipApplication(
  id: string,
  updates: {
    status?: ApplicationStatus;
    reviewedAt?: string;
    reviewedBy?: string;
    rejectionReason?: string;
  }
): Promise<eCitizenshipApplication> {
  const fields: string[] = [];
  const values: unknown[] = [];
  let paramIndex = 1;

  if (updates.status !== undefined) {
    fields.push(`status = $${paramIndex++}`);
    values.push(updates.status);
  }
  if (updates.reviewedAt !== undefined) {
    fields.push(`reviewed_at = $${paramIndex++}`);
    values.push(updates.reviewedAt);
  }
  if (updates.reviewedBy !== undefined) {
    fields.push(`reviewed_by = $${paramIndex++}`);
    values.push(updates.reviewedBy);
  }
  if (updates.rejectionReason !== undefined) {
    fields.push(`rejection_reason = $${paramIndex++}`);
    values.push(updates.rejectionReason);
  }

  fields.push(`updated_at = NOW()`);
  values.push(id);

  const result = await query<eCitizenshipApplication>(
    `UPDATE ecitizenship_applications SET ${fields.join(', ')} WHERE id = $${paramIndex} RETURNING *`,
    values
  );

  const row: any = result.rows[0]!;
  return {
    id: row.id,
    applicantDid: row.applicant_did,
    residentDid: row.resident_did,
    residencyTenure: row.residency_tenure || undefined,
    sponsorDid: row.sponsor_did || undefined,
    serviceMerit: row.service_merit
      ? typeof row.service_merit === 'string'
        ? JSON.parse(row.service_merit)
        : row.service_merit
      : undefined,
    videoInterview: row.video_interview
      ? typeof row.video_interview === 'string'
        ? JSON.parse(row.video_interview)
        : row.video_interview
      : undefined,
    backgroundAttestations: row.background_attestations
      ? typeof row.background_attestations === 'string'
        ? JSON.parse(row.background_attestations)
        : row.background_attestations
      : undefined,
    oathCeremony: row.oath_ceremony
      ? typeof row.oath_ceremony === 'string'
        ? JSON.parse(row.oath_ceremony)
        : row.oath_ceremony
      : undefined,
    status: row.status as ApplicationStatus,
    submittedAt: row.submitted_at ? (row.submitted_at instanceof Date ? row.submitted_at.toISOString() : row.submitted_at) : undefined,
    reviewedAt: row.reviewed_at ? (row.reviewed_at instanceof Date ? row.reviewed_at.toISOString() : row.reviewed_at) : undefined,
    reviewedBy: row.reviewed_by || undefined,
    rejectionReason: row.rejection_reason || undefined,
    createdAt: row.created_at instanceof Date ? row.created_at.toISOString() : row.created_at,
    updatedAt: row.updated_at instanceof Date ? row.updated_at.toISOString() : row.updated_at,
  };
}

