/**
 * Document Retention Management
 * Handles retention policies and disposal workflows
 */

import { query } from './client';
import { z } from 'zod';

export const RetentionPolicySchema = z.object({
  id: z.string().uuid(),
  name: z.string(),
  description: z.string().optional(),
  document_type: z.string().optional(),
  matter_type: z.string().optional(),
  retention_period_years: z.number().int().positive(),
  retention_trigger: z.enum(['creation', 'matter_close', 'last_access']),
  disposal_action: z.enum(['archive', 'delete', 'review']),
  is_active: z.boolean(),
  created_by: z.string().uuid().optional(),
  created_at: z.date(),
  updated_at: z.date(),
});

export type RetentionPolicy = z.infer<typeof RetentionPolicySchema>;

export const RetentionRecordSchema = z.object({
  id: z.string().uuid(),
  document_id: z.string().uuid(),
  policy_id: z.string().uuid(),
  retention_start_date: z.date(),
  retention_end_date: z.date(),
  status: z.enum(['active', 'expired', 'disposed', 'extended']),
  disposed_at: z.date().optional(),
  disposed_by: z.string().uuid().optional(),
  notes: z.string().optional(),
  created_at: z.date(),
  updated_at: z.date(),
});

export type RetentionRecord = z.infer<typeof RetentionRecordSchema>;

export interface CreateRetentionPolicyInput {
  name: string;
  description?: string;
  document_type?: string;
  matter_type?: string;
  retention_period_years: number;
  retention_trigger?: 'creation' | 'matter_close' | 'last_access';
  disposal_action?: 'archive' | 'delete' | 'review';
  is_active?: boolean;
  created_by?: string;
}

/**
 * Create retention policy
 */
export async function createRetentionPolicy(
  input: CreateRetentionPolicyInput
): Promise<RetentionPolicy> {
  const result = await query<RetentionPolicy>(
    `INSERT INTO document_retention_policies 
     (name, description, document_type, matter_type, retention_period_years,
      retention_trigger, disposal_action, is_active, created_by)
     VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
     RETURNING *`,
    [
      input.name,
      input.description || null,
      input.document_type || null,
      input.matter_type || null,
      input.retention_period_years,
      input.retention_trigger || 'creation',
      input.disposal_action || 'archive',
      input.is_active !== false,
      input.created_by || null,
    ]
  );

  return result.rows[0]!;
}

/**
 * Get policy by ID
 */
export async function getRetentionPolicy(id: string): Promise<RetentionPolicy | null> {
  const result = await query<RetentionPolicy>(
    `SELECT * FROM document_retention_policies WHERE id = $1`,
    [id]
  );
  return result.rows[0] || null;
}

/**
 * List retention policies
 */
export async function listRetentionPolicies(
  active_only = true
): Promise<RetentionPolicy[]> {
  const whereClause = active_only ? 'WHERE is_active = TRUE' : '';
  const result = await query<RetentionPolicy>(
    `SELECT * FROM document_retention_policies 
     ${whereClause}
     ORDER BY name`
  );
  return result.rows;
}

/**
 * Apply retention policy to document
 */
export async function applyRetentionPolicy(
  document_id: string,
  policy_id: string
): Promise<RetentionRecord> {
  const policy = await getRetentionPolicy(policy_id);
  if (!policy) {
    throw new Error(`Retention policy ${policy_id} not found`);
  }

  // Calculate retention dates based on trigger
  let retention_start_date: Date;
  const retention_end_date = new Date();

  if (policy.retention_trigger === 'creation') {
    // Get document creation date
    const docResult = await query<{ created_at: Date }>(
      `SELECT created_at FROM documents WHERE id = $1`,
      [document_id]
    );
    retention_start_date = docResult.rows[0]?.created_at || new Date();
    retention_end_date.setFullYear(
      retention_start_date.getFullYear() + policy.retention_period_years
    );
  } else if (policy.retention_trigger === 'matter_close') {
    // Get matter close date (would need to query matter)
    retention_start_date = new Date();
    retention_end_date.setFullYear(
      retention_start_date.getFullYear() + policy.retention_period_years
    );
  } else {
    // last_access - start from now
    retention_start_date = new Date();
    retention_end_date.setFullYear(
      retention_start_date.getFullYear() + policy.retention_period_years
    );
  }

  const result = await query<RetentionRecord>(
    `INSERT INTO document_retention_records 
     (document_id, policy_id, retention_start_date, retention_end_date, status)
     VALUES ($1, $2, $3, $4, $5)
     ON CONFLICT (document_id) 
     DO UPDATE SET policy_id = EXCLUDED.policy_id,
                    retention_start_date = EXCLUDED.retention_start_date,
                    retention_end_date = EXCLUDED.retention_end_date,
                    status = 'active',
                    updated_at = NOW()
     RETURNING *`,
    [document_id, policy_id, retention_start_date, retention_end_date, 'active']
  );

  return result.rows[0]!;
}

/**
 * Get retention record for document
 */
export async function getDocumentRetentionRecord(
  document_id: string
): Promise<RetentionRecord | null> {
  const result = await query<RetentionRecord>(
    `SELECT * FROM document_retention_records 
     WHERE document_id = $1 
     ORDER BY created_at DESC 
     LIMIT 1`,
    [document_id]
  );
  return result.rows[0] || null;
}

/**
 * Get expired retention records
 */
export async function getExpiredRetentionRecords(): Promise<RetentionRecord[]> {
  const result = await query<RetentionRecord>(
    `SELECT * FROM document_retention_records 
     WHERE status = 'active' 
     AND retention_end_date <= CURRENT_DATE
     ORDER BY retention_end_date ASC`
  );
  return result.rows;
}

/**
 * Mark retention record as disposed
 */
export async function disposeDocument(
  document_id: string,
  disposed_by: string,
  notes?: string
): Promise<RetentionRecord | null> {
  const result = await query<RetentionRecord>(
    `UPDATE document_retention_records 
     SET status = 'disposed', disposed_at = NOW(), disposed_by = $1, notes = $2, updated_at = NOW()
     WHERE document_id = $3
     RETURNING *`,
    [disposed_by, notes || null, document_id]
  );
  return result.rows[0] || null;
}

/**
 * Extend retention period
 */
export async function extendRetention(
  document_id: string,
  additional_years: number
): Promise<RetentionRecord | null> {
  const result = await query<RetentionRecord>(
    `UPDATE document_retention_records 
     SET retention_end_date = retention_end_date + INTERVAL '${additional_years} years',
         status = 'extended',
         updated_at = NOW()
     WHERE document_id = $1
     RETURNING *`,
    [document_id]
  );
  return result.rows[0] || null;
}

/**
 * Place document on legal hold (suspends retention)
 */
export async function placeOnLegalHold(
  document_id: string,
  notes?: string
): Promise<RetentionRecord | null> {
  const result = await query<RetentionRecord>(
    `UPDATE document_retention_records 
     SET status = 'extended', notes = COALESCE(notes || E'\n', '') || 'Legal Hold: ' || $1, updated_at = NOW()
     WHERE document_id = $2
     RETURNING *`,
    [notes || 'Legal hold placed', document_id]
  );
  return result.rows[0] || null;
}

/**
 * Get retention statistics
 */
export interface RetentionStatistics {
  total_documents: number;
  active_retention: number;
  expired_retention: number;
  disposed: number;
  on_hold: number;
  upcoming_expirations: number; // Next 30 days
}

export async function getRetentionStatistics(): Promise<RetentionStatistics> {
  const statsResult = await query<{
    status: string;
    count: string;
  }>(
    `SELECT status, COUNT(*) as count 
     FROM document_retention_records 
     GROUP BY status`
  );

  const upcomingResult = await query<{ count: string }>(
    `SELECT COUNT(*) as count 
     FROM document_retention_records 
     WHERE status = 'active'
     AND retention_end_date >= CURRENT_DATE
     AND retention_end_date <= CURRENT_DATE + INTERVAL '30 days'`
  );

  const stats: RetentionStatistics = {
    total_documents: 0,
    active_retention: 0,
    expired_retention: 0,
    disposed: 0,
    on_hold: 0,
    upcoming_expirations: parseInt(upcomingResult.rows[0]?.count || '0', 10),
  };

  for (const row of statsResult.rows) {
    const count = parseInt(row.count, 10);
    stats.total_documents += count;
    if (row.status === 'active') {
      stats.active_retention = count;
    } else if (row.status === 'expired') {
      stats.expired_retention = count;
    } else if (row.status === 'disposed') {
      stats.disposed = count;
    } else if (row.status === 'extended') {
      stats.on_hold += count;
    }
  }

  return stats;
}

