import { Component, inject, signal, computed } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select';
import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatTooltipModule } from '@angular/material/tooltip';
import { MatChipsModule } from '@angular/material/chips';
import { Clipboard } from '@angular/cdk/clipboard';
import { DocumentService } from '../services/document.service';
import { NotificationService } from '../../../core/services/notification.service';
import { DocumentType, DocumentResponseDto } from '../../../api/models';
import {
  INPUT_LIMITS,
  noScriptValidator,
  noNullBytesValidator,
  normalizeWhitespace,
} from '../../../shared/utils/form-validators';
import { createSubmitDebounce } from '../../../shared/utils/form-utils';

export interface DocumentUploadDialogData {
  requestId: string;
}

type UploadState = 'idle' | 'uploading' | 'processing' | 'complete' | 'error';

@Component({
  selector: 'app-document-upload',
  standalone: true,
  imports: [
    CommonModule,
    ReactiveFormsModule,
    MatDialogModule,
    MatFormFieldModule,
    MatSelectModule,
    MatInputModule,
    MatButtonModule,
    MatIconModule,
    MatProgressBarModule,
    MatProgressSpinnerModule,
    MatTooltipModule,
    MatChipsModule,
  ],
  template: `
    <div class="upload-dialog">
      <!-- Header -->
      <div class="dialog-header">
        <div class="header-icon">
          <mat-icon>cloud_upload</mat-icon>
        </div>
        <div class="header-text">
          <h2>Upload Document</h2>
          <p>Add a document to your request</p>
        </div>
      </div>

      <mat-dialog-content>
        @if (uploadState() === 'complete' && uploadedDocument()) {
          <!-- Success State -->
          <div class="success-state">
            <div class="success-icon">
              <mat-icon>check_circle</mat-icon>
            </div>
            <h3>Document Uploaded Successfully</h3>
            <p class="success-message">Your document has been securely uploaded and hashed on the blockchain.</p>

            <!-- Document Info Card -->
            <div class="document-card">
              <div class="doc-preview">
                @if (isImageFile()) {
                  <img [src]="previewUrl()" alt="Document preview" class="preview-image" />
                } @else {
                  <div class="file-icon-large">
                    <mat-icon>{{ getFileIcon() }}</mat-icon>
                  </div>
                }
              </div>
              <div class="doc-info">
                <div class="doc-name">{{ uploadedDocument()!.originalFilename }}</div>
                <div class="doc-meta">
                  <span class="meta-item">
                    <mat-icon>folder</mat-icon>
                    {{ formatDocType(uploadedDocument()!.docType) }}
                  </span>
                  <span class="meta-item">
                    <mat-icon>schedule</mat-icon>
                    Just now
                  </span>
                </div>
              </div>
            </div>

            <!-- Blockchain Hash Display -->
            <div class="hash-section">
              <div class="hash-header">
                <mat-icon>fingerprint</mat-icon>
                <span>Document Hash (SHA-256)</span>
                <div class="verified-badge">
                  <mat-icon>verified</mat-icon>
                  Blockchain Verified
                </div>
              </div>
              <div class="hash-display">
                <code class="hash-value">{{ uploadedDocument()!.currentHash }}</code>
                <button
                  mat-icon-button
                  (click)="copyHash()"
                  matTooltip="Copy hash to clipboard"
                  class="copy-btn"
                >
                  <mat-icon>{{ hashCopied() ? 'check' : 'content_copy' }}</mat-icon>
                </button>
              </div>
              <p class="hash-hint">
                This cryptographic hash uniquely identifies your document and is permanently recorded on the blockchain.
              </p>
            </div>
          </div>
        } @else {
          <!-- Upload Form -->
          <form [formGroup]="form" class="upload-form">
            <!-- Document Type -->
            <mat-form-field appearance="outline" class="full-width">
              <mat-label>Document Type</mat-label>
              <mat-icon matPrefix>category</mat-icon>
              <mat-select formControlName="docType">
                @for (type of documentTypes; track type.value) {
                  <mat-option [value]="type.value">
                    <div class="type-option">
                      <mat-icon>{{ type.icon }}</mat-icon>
                      {{ type.label }}
                    </div>
                  </mat-option>
                }
              </mat-select>
              @if (form.controls.docType.hasError('required')) {
                <mat-error>Please select a document type</mat-error>
              }
            </mat-form-field>

            <!-- Description -->
            <mat-form-field appearance="outline" class="full-width">
              <mat-label>Description (optional)</mat-label>
              <mat-icon matPrefix>notes</mat-icon>
              <textarea
                matInput
                formControlName="description"
                rows="2"
                placeholder="Add any additional notes about this document"
                [maxlength]="limits.DESCRIPTION_MAX"
              ></textarea>
              @if (form.controls.description.hasError('maxlength')) {
                <mat-error>Maximum {{ limits.DESCRIPTION_MAX }} characters allowed</mat-error>
              }
              @if (form.controls.description.hasError('dangerousContent')) {
                <mat-error>Invalid characters detected</mat-error>
              }
              <mat-hint align="end">{{ form.controls.description.value?.length || 0 }}/{{ limits.DESCRIPTION_MAX }}</mat-hint>
            </mat-form-field>

            <!-- Drop Zone -->
            <div
              class="drop-zone"
              [class.has-file]="selectedFile()"
              [class.drag-over]="isDragOver()"
              [class.uploading]="uploadState() === 'uploading'"
              [class.error]="uploadState() === 'error'"
              (dragover)="onDragOver($event)"
              (dragleave)="onDragLeave($event)"
              (drop)="onDrop($event)"
              (click)="uploadState() !== 'uploading' && fileInput.click()"
            >
              <input
                #fileInput
                type="file"
                hidden
                accept=".pdf,.jpg,.jpeg,.png,.doc,.docx"
                (change)="onFileSelected($event)"
              />

              @if (uploadState() === 'uploading' || uploadState() === 'processing') {
                <!-- Uploading State -->
                <div class="upload-progress-container">
                  <div class="progress-circle">
                    <svg viewBox="0 0 100 100">
                      <circle class="progress-bg" cx="50" cy="50" r="45" />
                      <circle
                        class="progress-fill"
                        cx="50"
                        cy="50"
                        r="45"
                        [style.stroke-dashoffset]="getProgressOffset()"
                      />
                    </svg>
                    <div class="progress-text">
                      @if (uploadState() === 'processing') {
                        <mat-icon class="processing-icon">sync</mat-icon>
                      } @else {
                        <span class="percentage">{{ uploadProgress() }}%</span>
                      }
                    </div>
                  </div>
                  <div class="upload-status">
                    @if (uploadState() === 'processing') {
                      <span class="status-text">Generating blockchain hash...</span>
                    } @else {
                      <span class="status-text">Uploading {{ selectedFile()?.name }}</span>
                      <span class="status-detail">{{ formatBytes(uploadedBytes()) }} / {{ formatBytes(totalBytes()) }}</span>
                    }
                  </div>
                </div>
              } @else if (selectedFile()) {
                <!-- File Selected State -->
                <div class="file-selected">
                  @if (isImageFile()) {
                    <img [src]="previewUrl()" alt="Preview" class="preview-thumb" />
                  } @else {
                    <div class="file-icon">
                      <mat-icon>{{ getFileIcon() }}</mat-icon>
                    </div>
                  }
                  <div class="file-details">
                    <span class="file-name">{{ selectedFile()!.name }}</span>
                    <span class="file-size">{{ formatFileSize(selectedFile()!.size) }}</span>
                  </div>
                  <button
                    mat-icon-button
                    (click)="clearFile($event)"
                    matTooltip="Remove file"
                    class="remove-btn"
                  >
                    <mat-icon>close</mat-icon>
                  </button>
                </div>
              } @else {
                <!-- Empty State -->
                <div class="empty-state">
                  <div class="upload-icon-wrapper">
                    <mat-icon>cloud_upload</mat-icon>
                  </div>
                  <span class="primary-text">Drag & drop a file here</span>
                  <span class="secondary-text">or click to browse</span>
                  <div class="file-types">
                    <mat-chip-set>
                      <mat-chip>PDF</mat-chip>
                      <mat-chip>JPG</mat-chip>
                      <mat-chip>PNG</mat-chip>
                      <mat-chip>DOC</mat-chip>
                    </mat-chip-set>
                  </div>
                  <span class="size-limit">Maximum file size: 10MB</span>
                </div>
              }
            </div>

            @if (uploadState() === 'error') {
              <div class="error-message">
                <mat-icon>error</mat-icon>
                <span>{{ errorMessage() }}</span>
                <button mat-button color="primary" (click)="resetUpload()">Try Again</button>
              </div>
            }

            <!-- Progress Bar (linear backup) -->
            @if (uploadState() === 'uploading') {
              <mat-progress-bar
                mode="determinate"
                [value]="uploadProgress()"
                class="linear-progress"
              ></mat-progress-bar>
            }
          </form>
        }
      </mat-dialog-content>

      <mat-dialog-actions align="end">
        @if (uploadState() === 'complete') {
          <button mat-flat-button color="primary" (click)="onDone()">
            <mat-icon>check</mat-icon>
            Done
          </button>
        } @else {
          <button mat-button (click)="onCancel()" [disabled]="uploadState() === 'uploading'">
            Cancel
          </button>
          <button
            mat-flat-button
            color="primary"
            (click)="onUpload()"
            [disabled]="!canUpload() || uploadState() === 'uploading'"
          >
            @if (uploadState() === 'uploading') {
              <mat-spinner diameter="20" class="btn-spinner"></mat-spinner>
              Uploading...
            } @else {
              <ng-container>
                <mat-icon>upload</mat-icon>
                Upload Document
              </ng-container>
            }
          </button>
        }
      </mat-dialog-actions>
    </div>
  `,
  styles: [`
    .upload-dialog {
      min-width: 480px;
      max-width: 560px;
    }

    .dialog-header {
      display: flex;
      align-items: center;
      gap: 16px;
      padding: 20px 24px;
      background: linear-gradient(135deg, var(--dbim-blue-dark, #1D0A69) 0%, var(--dbim-blue-mid, #2563EB) 100%);
      margin: -24px -24px 24px -24px;
      color: white;

      .header-icon {
        width: 48px;
        height: 48px;
        border-radius: 12px;
        background: rgba(255, 255, 255, 0.2);
        display: flex;
        align-items: center;
        justify-content: center;

        mat-icon {
          font-size: 28px;
          width: 28px;
          height: 28px;
        }
      }

      .header-text {
        h2 {
          margin: 0;
          font-size: 1.25rem;
          font-weight: 600;
        }
        p {
          margin: 4px 0 0;
          font-size: 0.85rem;
          opacity: 0.85;
        }
      }
    }

    .upload-form {
      display: flex;
      flex-direction: column;
      gap: 16px;
    }

    .full-width {
      width: 100%;
    }

    .type-option {
      display: flex;
      align-items: center;
      gap: 8px;

      mat-icon {
        font-size: 18px;
        width: 18px;
        height: 18px;
        color: var(--dbim-grey-2, #8E8E8E);
      }
    }

    /* Drop Zone */
    .drop-zone {
      border: 2px dashed var(--dbim-grey-1, #C6C6C6);
      border-radius: 12px;
      padding: 32px;
      text-align: center;
      cursor: pointer;
      transition: all 0.3s ease;
      background: var(--dbim-linen, #EBEAEA);
      min-height: 180px;
      display: flex;
      align-items: center;
      justify-content: center;

      &:hover:not(.uploading) {
        border-color: var(--dbim-blue-mid, #2563EB);
        background: rgba(37, 99, 235, 0.05);
      }

      &.drag-over {
        border-color: var(--dbim-blue-mid, #2563EB);
        background: rgba(37, 99, 235, 0.1);
        transform: scale(1.01);
      }

      &.has-file {
        border-style: solid;
        border-color: var(--dbim-success, #198754);
        background: rgba(25, 135, 84, 0.05);
      }

      &.uploading {
        cursor: default;
        border-color: var(--dbim-blue-mid, #2563EB);
        background: rgba(37, 99, 235, 0.05);
      }

      &.error {
        border-color: var(--dbim-error, #DC3545);
        background: rgba(220, 53, 69, 0.05);
      }
    }

    .empty-state {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 8px;

      .upload-icon-wrapper {
        width: 64px;
        height: 64px;
        border-radius: 50%;
        background: linear-gradient(135deg, var(--dbim-blue-dark, #1D0A69), var(--dbim-blue-mid, #2563EB));
        display: flex;
        align-items: center;
        justify-content: center;
        margin-bottom: 8px;

        mat-icon {
          font-size: 32px;
          width: 32px;
          height: 32px;
          color: white;
        }
      }

      .primary-text {
        font-size: 1rem;
        font-weight: 500;
        color: var(--dbim-brown, #150202);
      }

      .secondary-text {
        font-size: 0.9rem;
        color: var(--dbim-grey-2, #8E8E8E);
      }

      .file-types {
        margin-top: 8px;

        mat-chip {
          font-size: 0.7rem;
          min-height: 24px;
        }
      }

      .size-limit {
        font-size: 0.75rem;
        color: var(--dbim-grey-2, #8E8E8E);
        margin-top: 4px;
      }
    }

    .file-selected {
      display: flex;
      align-items: center;
      gap: 16px;
      width: 100%;

      .preview-thumb {
        width: 64px;
        height: 64px;
        object-fit: cover;
        border-radius: 8px;
        border: 1px solid var(--dbim-grey-1, #C6C6C6);
      }

      .file-icon {
        width: 64px;
        height: 64px;
        border-radius: 8px;
        background: var(--dbim-blue-subtle, #DBEAFE);
        display: flex;
        align-items: center;
        justify-content: center;

        mat-icon {
          font-size: 32px;
          width: 32px;
          height: 32px;
          color: var(--dbim-blue-mid, #2563EB);
        }
      }

      .file-details {
        flex: 1;
        text-align: left;

        .file-name {
          display: block;
          font-weight: 500;
          color: var(--dbim-brown, #150202);
          word-break: break-word;
        }

        .file-size {
          display: block;
          font-size: 0.85rem;
          color: var(--dbim-grey-2, #8E8E8E);
          margin-top: 4px;
        }
      }

      .remove-btn {
        color: var(--dbim-grey-2, #8E8E8E);

        &:hover {
          color: var(--dbim-error, #DC3545);
        }
      }
    }

    /* Upload Progress */
    .upload-progress-container {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 16px;

      .progress-circle {
        position: relative;
        width: 100px;
        height: 100px;

        svg {
          transform: rotate(-90deg);
          width: 100%;
          height: 100%;
        }

        .progress-bg {
          fill: none;
          stroke: var(--dbim-grey-1, #C6C6C6);
          stroke-width: 8;
        }

        .progress-fill {
          fill: none;
          stroke: var(--dbim-blue-mid, #2563EB);
          stroke-width: 8;
          stroke-linecap: round;
          stroke-dasharray: 283;
          transition: stroke-dashoffset 0.3s ease;
        }

        .progress-text {
          position: absolute;
          inset: 0;
          display: flex;
          align-items: center;
          justify-content: center;

          .percentage {
            font-size: 1.25rem;
            font-weight: 600;
            color: var(--dbim-blue-mid, #2563EB);
          }

          .processing-icon {
            font-size: 32px;
            width: 32px;
            height: 32px;
            color: var(--dbim-blue-mid, #2563EB);
            animation: spin 1s linear infinite;
          }
        }
      }

      .upload-status {
        text-align: center;

        .status-text {
          display: block;
          font-weight: 500;
          color: var(--dbim-brown, #150202);
        }

        .status-detail {
          display: block;
          font-size: 0.85rem;
          color: var(--dbim-grey-2, #8E8E8E);
          margin-top: 4px;
        }
      }
    }

    @keyframes spin {
      from { transform: rotate(0deg); }
      to { transform: rotate(360deg); }
    }

    .linear-progress {
      margin-top: 8px;
      border-radius: 4px;
    }

    .error-message {
      display: flex;
      align-items: center;
      gap: 8px;
      padding: 12px 16px;
      background: rgba(220, 53, 69, 0.1);
      border-radius: 8px;
      color: var(--dbim-error, #DC3545);

      mat-icon {
        font-size: 20px;
        width: 20px;
        height: 20px;
      }

      span {
        flex: 1;
        font-size: 0.9rem;
      }
    }

    /* Success State */
    .success-state {
      text-align: center;

      .success-icon {
        width: 72px;
        height: 72px;
        border-radius: 50%;
        background: rgba(25, 135, 84, 0.1);
        display: flex;
        align-items: center;
        justify-content: center;
        margin: 0 auto 16px;

        mat-icon {
          font-size: 40px;
          width: 40px;
          height: 40px;
          color: var(--dbim-success, #198754);
        }
      }

      h3 {
        margin: 0 0 8px;
        font-size: 1.25rem;
        color: var(--dbim-brown, #150202);
      }

      .success-message {
        margin: 0 0 24px;
        color: var(--dbim-grey-2, #8E8E8E);
        font-size: 0.9rem;
      }
    }

    .document-card {
      display: flex;
      align-items: center;
      gap: 16px;
      padding: 16px;
      background: var(--dbim-linen, #EBEAEA);
      border-radius: 12px;
      margin-bottom: 20px;
      text-align: left;

      .doc-preview {
        .preview-image {
          width: 64px;
          height: 64px;
          object-fit: cover;
          border-radius: 8px;
        }

        .file-icon-large {
          width: 64px;
          height: 64px;
          border-radius: 8px;
          background: var(--dbim-blue-subtle, #DBEAFE);
          display: flex;
          align-items: center;
          justify-content: center;

          mat-icon {
            font-size: 32px;
            width: 32px;
            height: 32px;
            color: var(--dbim-blue-mid, #2563EB);
          }
        }
      }

      .doc-info {
        flex: 1;

        .doc-name {
          font-weight: 500;
          color: var(--dbim-brown, #150202);
          word-break: break-word;
        }

        .doc-meta {
          display: flex;
          gap: 16px;
          margin-top: 8px;

          .meta-item {
            display: flex;
            align-items: center;
            gap: 4px;
            font-size: 0.8rem;
            color: var(--dbim-grey-2, #8E8E8E);

            mat-icon {
              font-size: 14px;
              width: 14px;
              height: 14px;
            }
          }
        }
      }
    }

    .hash-section {
      background: linear-gradient(135deg, rgba(29, 10, 105, 0.05), rgba(37, 99, 235, 0.05));
      border: 1px solid rgba(37, 99, 235, 0.2);
      border-radius: 12px;
      padding: 16px;
      text-align: left;

      .hash-header {
        display: flex;
        align-items: center;
        gap: 8px;
        margin-bottom: 12px;

        mat-icon {
          font-size: 20px;
          width: 20px;
          height: 20px;
          color: var(--dbim-blue-mid, #2563EB);
        }

        span {
          font-weight: 500;
          color: var(--dbim-brown, #150202);
        }

        .verified-badge {
          margin-left: auto;
          display: flex;
          align-items: center;
          gap: 4px;
          padding: 4px 10px;
          background: rgba(25, 135, 84, 0.1);
          border-radius: 16px;
          font-size: 0.75rem;
          color: var(--dbim-success, #198754);

          mat-icon {
            font-size: 14px;
            width: 14px;
            height: 14px;
            color: var(--dbim-success, #198754);
          }
        }
      }

      .hash-display {
        display: flex;
        align-items: center;
        gap: 8px;
        background: white;
        border-radius: 8px;
        padding: 12px;
        border: 1px solid var(--dbim-grey-1, #C6C6C6);

        .hash-value {
          flex: 1;
          font-family: 'Monaco', 'Consolas', monospace;
          font-size: 0.75rem;
          word-break: break-all;
          color: var(--dbim-blue-dark, #1D0A69);
        }

        .copy-btn {
          flex-shrink: 0;
          width: 36px;
          height: 36px;
          color: var(--dbim-blue-mid, #2563EB);
        }
      }

      .hash-hint {
        margin: 12px 0 0;
        font-size: 0.75rem;
        color: var(--dbim-grey-2, #8E8E8E);
        line-height: 1.5;
      }
    }

    .btn-spinner {
      display: inline-block;
      margin-right: 8px;
    }

    mat-dialog-actions {
      padding: 16px 24px !important;
      margin: 0 -24px -24px !important;
      border-top: 1px solid var(--dbim-linen, #EBEAEA);
    }
  `],
})
export class DocumentUploadComponent {
  private readonly fb = inject(FormBuilder);
  private readonly documentService = inject(DocumentService);
  private readonly notification = inject(NotificationService);
  private readonly dialogRef = inject(MatDialogRef<DocumentUploadComponent>);
  private readonly data: DocumentUploadDialogData = inject(MAT_DIALOG_DATA);
  private readonly clipboard = inject(Clipboard);

  /** Debounce handler to prevent double-click submissions */
  private readonly submitDebounce = createSubmitDebounce(500);

  /** Input limits exposed for template binding */
  readonly limits = INPUT_LIMITS;

  // State signals
  readonly uploadState = signal<UploadState>('idle');
  readonly selectedFile = signal<File | null>(null);
  readonly isDragOver = signal(false);
  readonly uploadProgress = signal(0);
  readonly uploadedBytes = signal(0);
  readonly totalBytes = signal(0);
  readonly uploadedDocument = signal<DocumentResponseDto | null>(null);
  readonly errorMessage = signal('');
  readonly previewUrl = signal<string | null>(null);
  readonly hashCopied = signal(false);

  readonly documentTypes: { value: DocumentType; label: string; icon: string }[] = [
    { value: 'ID_PROOF', label: 'Identity Proof', icon: 'badge' },
    { value: 'ADDRESS_PROOF', label: 'Address Proof', icon: 'location_on' },
    { value: 'FIRE_SAFETY', label: 'Fire Safety Certificate', icon: 'local_fire_department' },
    { value: 'FLOOR_PLAN', label: 'Floor Plan', icon: 'apartment' },
    { value: 'SITE_PLAN', label: 'Site Plan', icon: 'map' },
    { value: 'BUILDING_PERMIT', label: 'Building Permit', icon: 'home_work' },
    { value: 'BUSINESS_LICENSE', label: 'Business License', icon: 'storefront' },
    { value: 'PHOTOGRAPH', label: 'Photograph', icon: 'photo_camera' },
    { value: 'NOC', label: 'No Objection Certificate', icon: 'verified' },
    { value: 'LICENSE_COPY', label: 'License Copy', icon: 'file_copy' },
    { value: 'HEALTH_CERT', label: 'Health Certificate', icon: 'health_and_safety' },
    { value: 'TAX_CLEARANCE', label: 'Tax Clearance', icon: 'receipt_long' },
    { value: 'OTHER', label: 'Other Document', icon: 'description' },
  ];

  readonly form = this.fb.nonNullable.group({
    docType: ['' as DocumentType, [Validators.required]],
    description: ['', [
      Validators.maxLength(INPUT_LIMITS.DESCRIPTION_MAX),
      noScriptValidator(),
      noNullBytesValidator(),
    ]],
  });

  canUpload(): boolean {
    return this.form.valid && this.selectedFile() !== null;
  }

  isImageFile(): boolean {
    const file = this.selectedFile();
    if (!file) return false;
    return file.type.startsWith('image/');
  }

  getFileIcon(): string {
    const file = this.selectedFile() || this.uploadedDocument();
    if (!file) return 'description';

    const filename = 'name' in file ? file.name : file.originalFilename;
    const ext = filename.split('.').pop()?.toLowerCase();

    switch (ext) {
      case 'pdf': return 'picture_as_pdf';
      case 'doc':
      case 'docx': return 'article';
      case 'xls':
      case 'xlsx': return 'table_chart';
      case 'jpg':
      case 'jpeg':
      case 'png':
      case 'gif': return 'image';
      default: return 'description';
    }
  }

  getProgressOffset(): number {
    const circumference = 283; // 2 * PI * 45 (radius)
    return circumference - (this.uploadProgress() / 100) * circumference;
  }

  formatDocType(type: string): string {
    return type.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
  }

  // Drag & Drop handlers
  onDragOver(event: DragEvent): void {
    event.preventDefault();
    this.isDragOver.set(true);
  }

  onDragLeave(event: DragEvent): void {
    event.preventDefault();
    this.isDragOver.set(false);
  }

  onDrop(event: DragEvent): void {
    event.preventDefault();
    this.isDragOver.set(false);
    const files = event.dataTransfer?.files;
    if (files && files.length > 0) {
      this.selectFile(files[0]);
    }
  }

  onFileSelected(event: Event): void {
    const input = event.target as HTMLInputElement;
    if (input.files && input.files.length > 0) {
      this.selectFile(input.files[0]);
    }
  }

  private selectFile(file: File): void {
    // Validate file size
    if (file.size > 10 * 1024 * 1024) {
      this.notification.error('File size must be less than 10MB');
      return;
    }

    // Validate file type
    const allowedTypes = ['application/pdf', 'image/jpeg', 'image/png', 'image/jpg',
      'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'];
    if (!allowedTypes.includes(file.type)) {
      this.notification.error('Invalid file type. Please upload PDF, JPG, PNG, or DOC files.');
      return;
    }

    this.selectedFile.set(file);
    this.uploadState.set('idle');
    this.errorMessage.set('');

    // Generate preview for images
    if (file.type.startsWith('image/')) {
      const reader = new FileReader();
      reader.onload = (e) => {
        this.previewUrl.set(e.target?.result as string);
      };
      reader.readAsDataURL(file);
    } else {
      this.previewUrl.set(null);
    }
  }

  clearFile(event: Event): void {
    event.stopPropagation();
    this.selectedFile.set(null);
    this.previewUrl.set(null);
    this.uploadState.set('idle');
  }

  resetUpload(): void {
    this.uploadState.set('idle');
    this.uploadProgress.set(0);
    this.errorMessage.set('');
  }

  formatFileSize(bytes: number): string {
    if (bytes < 1024) return bytes + ' B';
    if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
    return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
  }

  formatBytes(bytes: number): string {
    return this.formatFileSize(bytes);
  }

  copyHash(): void {
    const doc = this.uploadedDocument();
    if (doc?.currentHash) {
      this.clipboard.copy(doc.currentHash);
      this.hashCopied.set(true);
      this.notification.success('Hash copied to clipboard');
      setTimeout(() => this.hashCopied.set(false), 2000);
    }
  }

  onUpload(): void {
    // Debounce to prevent double-click submissions
    this.submitDebounce(() => this.performUpload());
  }

  private performUpload(): void {
    const file = this.selectedFile();
    if (!file || this.form.invalid || this.uploadState() === 'uploading') return;

    this.uploadState.set('uploading');
    this.uploadProgress.set(0);
    const rawValues = this.form.getRawValue();

    // Normalize description
    const docType = rawValues.docType;
    const description = normalizeWhitespace(rawValues.description);

    this.documentService.uploadDocumentWithProgress(this.data.requestId, file, docType, description).subscribe({
      next: (progress) => {
        if (progress.complete && progress.response) {
          this.uploadState.set('processing');
          // Simulate brief processing time for blockchain hash generation
          setTimeout(() => {
            this.uploadedDocument.set(progress.response!);
            this.uploadState.set('complete');
            this.notification.success('Document uploaded and hashed successfully');
          }, 800);
        } else {
          this.uploadProgress.set(progress.progress);
          this.uploadedBytes.set(progress.loaded);
          this.totalBytes.set(progress.total);
        }
      },
      error: (err) => {
        this.uploadState.set('error');
        this.errorMessage.set(err.message || 'Failed to upload document. Please try again.');
      },
    });
  }

  onCancel(): void {
    this.dialogRef.close();
  }

  onDone(): void {
    this.dialogRef.close(this.uploadedDocument());
  }
}
