/**
 * Backup Entity
 * Registro de backups del sistema
 *
 * @module Admin
 * @table admin.backups
 */

import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  CreateDateColumn,
  ManyToOne,
  JoinColumn,
  Index,
} from 'typeorm';
import { Tenant } from '../../core/entities/tenant.entity';
import { User } from '../../core/entities/user.entity';

export type BackupType = 'full' | 'incremental' | 'differential' | 'files' | 'snapshot';

export type BackupStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled' | 'expired';

export type BackupStorage = 'local' | 's3' | 'gcs' | 'azure' | 'offsite';

@Entity({ schema: 'admin', name: 'backups' })
@Index(['tenantId'])
@Index(['backupType'])
@Index(['status'])
@Index(['createdAt'])
@Index(['expiresAt'])
export class Backup {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column({ name: 'tenant_id', type: 'uuid' })
  tenantId: string;

  @Column({
    name: 'backup_type',
    type: 'varchar',
    length: 20,
  })
  backupType: BackupType;

  @Column({
    type: 'varchar',
    length: 20,
    default: 'pending',
  })
  status: BackupStatus;

  @Column({
    type: 'varchar',
    length: 200,
    comment: 'Descriptive name for the backup',
  })
  name: string;

  @Column({
    type: 'text',
    nullable: true,
  })
  description: string | null;

  @Column({
    name: 'file_path',
    type: 'varchar',
    length: 500,
    nullable: true,
  })
  filePath: string | null;

  @Column({
    name: 'file_name',
    type: 'varchar',
    length: 200,
    nullable: true,
  })
  fileName: string | null;

  @Column({
    name: 'file_size',
    type: 'bigint',
    nullable: true,
    comment: 'Size in bytes',
  })
  fileSize: number | null;

  @Column({
    name: 'storage_location',
    type: 'varchar',
    length: 20,
    default: 'local',
  })
  storageLocation: BackupStorage;

  @Column({
    name: 'storage_url',
    type: 'varchar',
    length: 1000,
    nullable: true,
    comment: 'Full URL or path to backup file',
  })
  storageUrl: string | null;

  @Column({
    type: 'varchar',
    length: 64,
    nullable: true,
    comment: 'SHA-256 checksum for integrity verification',
  })
  checksum: string | null;

  @Column({
    name: 'is_encrypted',
    type: 'boolean',
    default: true,
  })
  isEncrypted: boolean;

  @Column({
    name: 'encryption_key_id',
    type: 'varchar',
    length: 100,
    nullable: true,
    comment: 'Reference to encryption key used',
  })
  encryptionKeyId: string | null;

  @Column({
    name: 'is_compressed',
    type: 'boolean',
    default: true,
  })
  isCompressed: boolean;

  @Column({
    name: 'compression_type',
    type: 'varchar',
    length: 20,
    nullable: true,
    comment: 'gzip, lz4, zstd, etc.',
  })
  compressionType: string | null;

  @Column({
    name: 'database_version',
    type: 'varchar',
    length: 50,
    nullable: true,
    comment: 'PostgreSQL version at backup time',
  })
  databaseVersion: string | null;

  @Column({
    name: 'app_version',
    type: 'varchar',
    length: 50,
    nullable: true,
    comment: 'Application version at backup time',
  })
  appVersion: string | null;

  @Column({
    name: 'tables_included',
    type: 'varchar',
    array: true,
    nullable: true,
    comment: 'List of tables included in backup',
  })
  tablesIncluded: string[] | null;

  @Column({
    name: 'tables_excluded',
    type: 'varchar',
    array: true,
    nullable: true,
    comment: 'List of tables excluded from backup',
  })
  tablesExcluded: string[] | null;

  @Column({
    name: 'row_count',
    type: 'integer',
    nullable: true,
    comment: 'Total rows backed up',
  })
  rowCount: number | null;

  @Column({
    name: 'started_at',
    type: 'timestamptz',
    nullable: true,
  })
  startedAt: Date | null;

  @Column({
    name: 'completed_at',
    type: 'timestamptz',
    nullable: true,
  })
  completedAt: Date | null;

  @Column({
    name: 'duration_seconds',
    type: 'integer',
    nullable: true,
  })
  durationSeconds: number | null;

  @Column({
    name: 'expires_at',
    type: 'timestamptz',
    nullable: true,
    comment: 'When this backup will be automatically deleted',
  })
  expiresAt: Date | null;

  @Column({
    name: 'retention_policy',
    type: 'varchar',
    length: 50,
    nullable: true,
    comment: 'daily, weekly, monthly, yearly, permanent',
  })
  retentionPolicy: string | null;

  @Column({
    name: 'is_scheduled',
    type: 'boolean',
    default: false,
    comment: 'Was this a scheduled backup?',
  })
  isScheduled: boolean;

  @Column({
    name: 'schedule_id',
    type: 'varchar',
    length: 100,
    nullable: true,
    comment: 'Reference to schedule that triggered this backup',
  })
  scheduleId: string | null;

  @Column({
    name: 'is_verified',
    type: 'boolean',
    default: false,
    comment: 'Has restore been tested?',
  })
  isVerified: boolean;

  @Column({
    name: 'verified_at',
    type: 'timestamptz',
    nullable: true,
  })
  verifiedAt: Date | null;

  @Column({
    name: 'verified_by',
    type: 'uuid',
    nullable: true,
  })
  verifiedById: string | null;

  @Column({
    name: 'error_message',
    type: 'text',
    nullable: true,
  })
  errorMessage: string | null;

  @Column({
    type: 'jsonb',
    nullable: true,
    comment: 'Additional backup metadata',
  })
  metadata: Record<string, any> | null;

  @CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
  createdAt: Date;

  @Column({ name: 'created_by', type: 'uuid', nullable: true })
  createdById: string | null;

  // Relations
  @ManyToOne(() => Tenant)
  @JoinColumn({ name: 'tenant_id' })
  tenant: Tenant;

  @ManyToOne(() => User)
  @JoinColumn({ name: 'created_by' })
  createdBy: User | null;

  @ManyToOne(() => User)
  @JoinColumn({ name: 'verified_by' })
  verifiedBy: User | null;
}
