import { Component, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Router, RouterLink } from '@angular/router';
import { ImageRecord, ImageService } from '../services/image.service';

@Component({
  selector: 'app-upload',
  standalone: true,
  imports: [CommonModule, FormsModule, RouterLink],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <div class="upload-page">
      <h1>Upload Image</h1>

      <div
        class="drop-zone"
        role="button"
        tabindex="0"
        [class.drag-over]="isDragOver"
        (dragover)="onDragOver($event)"
        (dragleave)="isDragOver = false"
        (drop)="onDrop($event)"
        (click)="fileInput.click()"
        (keydown.enter)="fileInput.click()"
        (keydown.space)="fileInput.click()"
      >
        <span class="drop-icon">📁</span>
        <p>{{ selectedFile ? selectedFile.name : 'Drag & drop or click to browse' }}</p>
        <input #fileInput type="file" accept="image/*" hidden (change)="onFileChange($event)" />
      </div>

      <div class="tag-input" *ngIf="selectedFile">
        <label for="tag-input">Tags (comma or space separated)</label>
        <input id="tag-input" [(ngModel)]="tagInput" placeholder="cat, funny, reaction" />
        <div class="chips">
          <span *ngFor="let tag of parseTagInput(tagInput)" class="chip">{{ tag }}</span>
        </div>
      </div>

      <button type="submit" [disabled]="!selectedFile || uploading" (click)="submit()">
        <span *ngIf="uploading" class="spinner"></span>
        {{ uploading ? 'Uploading…' : 'Upload' }}
      </button>

      <!-- Success banner -->
      <div class="success-banner" *ngIf="showSuccess">
        <span class="success-icon">✔</span>
        <span>{{ uploadedFilename }} uploaded.</span>
        <span class="banner-links">
          <button type="button" class="link" (click)="resetForm()">Upload another</button>
          <a routerLink="/" class="link">View in library</a>
        </span>
      </div>

      <p class="toast" *ngIf="toastMessage && !showSuccess">{{ toastMessage }}</p>
      <p class="error" *ngIf="errorMessage">{{ errorMessage }}</p>
    </div>
  `,
  styles: [`
    .upload-page { max-width: 600px; margin: 40px auto; padding: 0 16px; }
    h1 { margin-bottom: 24px; }
    .drop-zone {
      border: 2px dashed color-mix(in srgb, var(--accent) 40%, transparent);
      border-radius: var(--radius);
      padding: 48px;
      text-align: center;
      cursor: pointer;
      color: var(--text-muted);
      background: var(--surface);
      transition: border-color var(--transition), background var(--transition);
    }
    .drop-zone.drag-over { border-color: var(--accent); background: var(--surface-raised); }
    .drop-icon { font-size: 2rem; display: block; margin-bottom: 8px; }
    .tag-input { margin: 16px 0; }
    label { display: block; margin-bottom: 4px; font-size: 0.9rem; color: var(--text-muted); }
    input[type=text], input:not([type]) { width: 100%; padding: 8px; background: var(--surface); border: 1px solid var(--border); color: var(--text); border-radius: var(--radius); }
    input:focus { outline: none; border-color: var(--border-focus); }
    .chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
    .chip { background: var(--surface-raised); padding: 2px 10px; border-radius: var(--radius-chip); font-size: 0.85rem; }
    button[type="submit"] {
      display: flex; align-items: center; gap: 8px;
      padding: 10px 24px; background: var(--accent); color: var(--accent-text);
      border: none; border-radius: var(--radius); cursor: pointer; font-weight: 600;
      transition: opacity var(--transition);
    }
    button[type="submit"]:disabled { opacity: 0.5; cursor: default; color: var(--text-muted); }
    @keyframes spin { to { transform: rotate(360deg); } }
    .spinner { display: inline-block; width: 14px; height: 14px; border: 2px solid var(--accent-text); border-top-color: transparent; border-radius: 50%; animation: spin 0.7s linear infinite; }
    .success-banner {
      display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
      margin-top: 16px; padding: 12px 16px;
      background: color-mix(in srgb, #2ecc71 12%, var(--surface));
      border: 1px solid color-mix(in srgb, #2ecc71 30%, transparent);
      border-radius: var(--radius); color: var(--text);
    }
    .success-icon { color: #2ecc71; font-size: 1.1rem; }
    .banner-links { display: flex; gap: 12px; margin-left: auto; }
    .link { color: var(--accent); cursor: pointer; text-decoration: none; font-size: 0.9rem; }
    .link:hover { text-decoration: underline; }
    .toast { color: var(--accent); margin-top: 12px; }
    .error { color: var(--danger); margin-top: 12px; }
  `],
})
export class UploadComponent {
  selectedFile: File | null = null;
  tagInput = '';
  uploading = false;
  toastMessage = '';
  errorMessage = '';
  isDragOver = false;
  showSuccess = false;
  uploadedFilename = '';
  private dismissTimer: ReturnType<typeof setTimeout> | null = null;

  constructor(
    private imageService: ImageService,
    private router: Router,
    private cdr: ChangeDetectorRef,
  ) {}

  parseTagInput(input: string): string[] {
    return input
      .toLowerCase()
      .replace(/,/g, ' ')
      .split(/\s+/)
      .map((t) => t.trim())
      .filter((t) => t.length > 0);
  }

  onDragOver(event: DragEvent): void {
    event.preventDefault();
    this.isDragOver = true;
  }

  onDrop(event: DragEvent): void {
    event.preventDefault();
    this.isDragOver = false;
    const file = event.dataTransfer?.files[0];
    if (file) this.selectedFile = file;
  }

  onFileChange(event: Event): void {
    const input = event.target as HTMLInputElement;
    this.selectedFile = input.files?.[0] ?? null;
  }

  submit(): void {
    if (!this.selectedFile) return;
    this.uploading = true;
    this.errorMessage = '';
    this.toastMessage = '';
    this.showSuccess = false;

    const tags = this.parseTagInput(this.tagInput);
    this.imageService.upload(this.selectedFile, tags).subscribe({
      next: (res) => {
        this.uploading = false;
        this.handleUploadResponse(res);
        this.cdr.markForCheck();
      },
      error: (err) => {
        this.uploading = false;
        this.handleUploadError(err);
        this.cdr.markForCheck();
      },
    });
  }

  async handleUploadResponse(res: ImageRecord): Promise<void> {
    if (res.duplicate) {
      this.toastMessage = 'Already in your library';
    } else {
      this.uploadedFilename = this.selectedFile?.name ?? res.id;
      this.showSuccess = true;
      this.cdr.markForCheck();
      if (this.dismissTimer) clearTimeout(this.dismissTimer);
      this.dismissTimer = setTimeout(() => {
        this.showSuccess = false;
        this.cdr.markForCheck();
      }, 4000);
    }
    await this.router.navigate(['/i', res.short_id]);
  }

  handleUploadError(err: unknown): void {
    const httpErr = err as { status?: number; error?: { detail?: string } };
    const status = httpErr?.status;
    const detail = httpErr?.error?.detail;
    if (status === 422 && detail) {
      this.errorMessage = detail;
    } else {
      this.errorMessage = 'Upload failed. Please try again.';
    }
    this.cdr.markForCheck();
  }

  resetForm(): void {
    this.selectedFile = null;
    this.tagInput = '';
    this.toastMessage = '';
    this.errorMessage = '';
    this.showSuccess = false;
    if (this.dismissTimer) clearTimeout(this.dismissTimer);
    this.cdr.markForCheck();
  }
}
