import {
  customElement,
  html,
  property,
  css,
  cssManager,
  state,
  type TemplateResult,
} from '@design.estate/dees-element';
import { DeesInputBase } from '../dees-input-base/dees-input-base.js';
import '../../dees-icon/dees-icon.js';
import '../../dees-label/dees-label.js';
import { ProfilePictureModal } from './profilepicture.modal.js';
import { demoFunc } from './dees-input-profilepicture.demo.js';
import { themeDefaultStyles } from '../../00theme.js';

declare global {
  interface HTMLElementTagNameMap {
    'dees-input-profilepicture': DeesInputProfilePicture;
  }
}

export type ProfileShape = 'square' | 'round';

@customElement('dees-input-profilepicture')
export class DeesInputProfilePicture extends DeesInputBase<DeesInputProfilePicture> {
  public static demo = demoFunc;
  public static demoGroup = 'Input';

  @property({ type: String })
  accessor value: string = ''; // Base64 encoded image or URL

  @property({ type: String })
  accessor shape: ProfileShape = 'round';

  @property({ type: Number })
  accessor size: number = 120;

  @property({ type: String })
  accessor placeholder: string = '';

  @property({ type: Boolean })
  accessor allowUpload: boolean = true;

  @property({ type: Boolean })
  accessor allowDelete: boolean = true;

  @property({ type: Number })
  accessor maxFileSize: number = 5 * 1024 * 1024; // 5MB

  @property({ type: Array })
  accessor acceptedFormats: string[] = ['image/jpeg', 'image/png', 'image/webp'];

  @property({ type: Number })
  accessor outputSize: number = 800; // Output resolution in pixels

  @property({ type: Number })
  accessor outputQuality: number = 0.95; // 0-1 quality for JPEG

  @state()
  accessor isHovered: boolean = false;

  @state()
  accessor isDragging: boolean = false;

  @state()
  accessor isLoading: boolean = false;

  private modalInstance: ProfilePictureModal | null = null;

  public static styles = [
    themeDefaultStyles,
    ...DeesInputBase.baseStyles,
    cssManager.defaultStyles,
    css`
      /* TODO: Migrate hardcoded values to --dees-* CSS variables */
      :host {
        display: block;
        position: relative;
      }

      .input-wrapper {
        display: flex;
        flex-direction: column;
        gap: 16px;
      }

      .profile-container {
        position: relative;
        display: inline-block;
        cursor: pointer;
        transition: all 0.3s ease;
      }

      .profile-container:hover {
        transform: scale(1.02);
      }

      .profile-picture {
        width: var(--size, 120px);
        height: var(--size, 120px);
        background: ${cssManager.bdTheme('#f5f5f5', '#18181b')};
        border: 3px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')};
        display: flex;
        align-items: center;
        justify-content: center;
        overflow: hidden;
        position: relative;
        transition: all 0.3s ease;
      }

      .profile-picture.round {
        border-radius: 50%;
      }

      .profile-picture.square {
        border-radius: 12px;
      }

      .profile-picture.dragging {
        border-color: ${cssManager.bdTheme('#3b82f6', '#60a5fa')};
        box-shadow: 0 0 0 4px ${cssManager.bdTheme('rgba(59, 130, 246, 0.15)', 'rgba(96, 165, 250, 0.15)')};
      }

      .profile-picture:hover {
        border-color: ${cssManager.bdTheme('#d4d4d8', '#3f3f46')};
      }

      .profile-picture:disabled {
        cursor: not-allowed;
        opacity: 0.5;
      }

      .profile-image {
        width: 100%;
        height: 100%;
        object-fit: cover;
      }

      .placeholder-icon {
        color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
      }

      .overlay {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: rgba(0, 0, 0, 0.6);
        display: flex;
        align-items: center;
        justify-content: center;
        opacity: 0;
        transition: opacity 0.3s ease;
        pointer-events: none;
      }

      .profile-container:hover .overlay {
        opacity: 1;
      }

      .overlay-content {
        display: flex;
        gap: 12px;
      }

      .overlay-button {
        width: 40px;
        height: 40px;
        border-radius: 50%;
        background: ${cssManager.bdTheme('rgba(255, 255, 255, 0.95)', 'rgba(39, 39, 42, 0.95)')};
        border: 1px solid ${cssManager.bdTheme('rgba(0, 0, 0, 0.1)', 'rgba(255, 255, 255, 0.1)')};
        color: ${cssManager.bdTheme('#09090b', '#fafafa')};
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        transition: all 0.2s ease;
        pointer-events: auto;
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
      }

      .overlay-button:hover {
        background: ${cssManager.bdTheme('#ffffff', '#3f3f46')};
        transform: scale(1.1);
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
      }

      .overlay-button.delete {
        background: ${cssManager.bdTheme('rgba(239, 68, 68, 0.9)', 'rgba(220, 38, 38, 0.9)')};
        color: white;
        border-color: transparent;
      }

      .overlay-button.delete:hover {
        background: ${cssManager.bdTheme('#ef4444', '#dc2626')};
      }

      .drop-zone-text {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        text-align: center;
        color: white;
        font-weight: 500;
        pointer-events: none;
      }

      .hidden-input {
        display: none;
      }

      /* Loading animation */
      .loading-overlay {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: ${cssManager.bdTheme('rgba(255, 255, 255, 0.8)', 'rgba(0, 0, 0, 0.8)')};
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: inherit;
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.2s ease;
      }

      .loading-overlay.show {
        opacity: 1;
        pointer-events: auto;
      }

      .loading-spinner {
        width: 40px;
        height: 40px;
        border: 3px solid ${cssManager.bdTheme('rgba(0, 0, 0, 0.1)', 'rgba(255, 255, 255, 0.1)')};
        border-top-color: ${cssManager.bdTheme('#3b82f6', '#60a5fa')};
        border-radius: 50%;
        animation: spin 0.6s linear infinite;
      }

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

      @keyframes pulse {
        0% {
          transform: scale(1);
          opacity: 1;
        }
        50% {
          transform: scale(1.05);
          opacity: 0.8;
        }
        100% {
          transform: scale(1);
          opacity: 1;
        }
      }

      .profile-picture.clicking {
        animation: pulse 0.3s ease-out;
      }
    `,
  ];

  render(): TemplateResult {
    return html`
      <div class="input-wrapper">
        <dees-label .label=${this.label} .description=${this.description} .required=${this.required}></dees-label>
        
        <div 
          class="profile-container"
          @click=${this.handleClick}
          @dragover=${this.handleDragOver}
          @dragleave=${this.handleDragLeave}
          @drop=${this.handleDrop}
          style="--size: ${this.size}px"
        >
          <div class="profile-picture ${this.shape} ${this.isDragging ? 'dragging' : ''} ${this.isLoading && !this.value ? 'clicking' : ''}">
            ${this.value ? html`
              <img class="profile-image" src="${this.value}" alt="Profile picture" />
            ` : html`
              <dees-icon class="placeholder-icon" icon="lucide:user" iconSize="${this.size * 0.5}"></dees-icon>
            `}
            
            ${this.isDragging ? html`
              <div class="overlay" style="opacity: 1">
                <div class="drop-zone-text">
                  Drop image here
                </div>
              </div>
            ` : ''}
            
            ${this.value && !this.disabled ? html`
              <div class="overlay">
                <div class="overlay-content">
                  ${this.allowUpload ? html`
                    <button class="overlay-button" @click=${(e: Event) => { e.stopPropagation(); this.openModal(); }} title="Change picture">
                      <dees-icon icon="lucide:pencil" iconSize="20"></dees-icon>
                    </button>
                  ` : ''}
                  ${this.allowDelete ? html`
                    <button class="overlay-button delete" @click=${(e: Event) => { e.stopPropagation(); this.deletePicture(); }} title="Delete picture">
                      <dees-icon icon="lucide:trash2" iconSize="20"></dees-icon>
                    </button>
                  ` : ''}
                </div>
              </div>
            ` : ''}
            
            ${this.isLoading && !this.value ? html`
              <div class="loading-overlay show">
                <div class="loading-spinner"></div>
              </div>
            ` : ''}
          </div>
        </div>
        
        <input
          type="file"
          class="hidden-input"
          accept="${this.acceptedFormats.join(',')}"
          @change=${this.handleFileSelect}
        />
      </div>
    `;
  }

  private handleClick(): void {
    if (this.disabled || !this.allowUpload) return;
    
    if (!this.value) {
      // If no image, open file picker
      this.isLoading = true;
      const input = this.shadowRoot!.querySelector('.hidden-input') as HTMLInputElement;
      
      // Set up a focus handler to detect when the dialog is closed without selection
      const handleFocus = () => {
        setTimeout(() => {
          // Check if no file was selected
          if (!input.files || input.files.length === 0) {
            this.isLoading = false;
          }
          window.removeEventListener('focus', handleFocus);
        }, 300);
      };
      
      window.addEventListener('focus', handleFocus);
      input.click();
    }
  }

  private handleFileSelect(event: Event): void {
    const input = event.target as HTMLInputElement;
    const file = input.files?.[0];
    
    // Always reset loading state when file dialog interaction completes
    this.isLoading = false;
    
    if (file) {
      this.processFile(file);
    }
    
    // Reset input to allow selecting the same file again
    input.value = '';
  }

  private handleDragOver(event: DragEvent): void {
    event.preventDefault();
    if (!this.disabled && this.allowUpload) {
      this.isDragging = true;
    }
  }

  private handleDragLeave(): void {
    this.isDragging = false;
  }

  private handleDrop(event: DragEvent): void {
    event.preventDefault();
    this.isDragging = false;
    
    if (this.disabled || !this.allowUpload) return;
    
    const file = event.dataTransfer?.files[0];
    if (file) {
      this.processFile(file);
    }
  }

  private async processFile(file: File): Promise<void> {
    // Validate file type
    if (!this.acceptedFormats.includes(file.type)) {
      console.error('Invalid file type:', file.type);
      return;
    }
    
    // Validate file size
    if (file.size > this.maxFileSize) {
      console.error('File too large:', file.size);
      return;
    }
    
    // Read file as base64
    const reader = new FileReader();
    reader.onload = async (e) => {
      const base64 = e.target?.result as string;
      
      // Open modal for cropping
      await this.openModal(base64);
    };
    reader.readAsDataURL(file);
  }

  private async openModal(initialImage?: string): Promise<void> {
    const imageToEdit = initialImage || this.value;
    
    if (!imageToEdit) {
      // If no image provided, open file picker
      const input = this.shadowRoot!.querySelector('.hidden-input') as HTMLInputElement;
      input.click();
      return;
    }
    
    // Create and show modal
    this.modalInstance = new ProfilePictureModal();
    this.modalInstance.shape = this.shape;
    this.modalInstance.initialImage = imageToEdit;
    this.modalInstance.outputSize = this.outputSize;
    this.modalInstance.outputQuality = this.outputQuality;
    
    this.modalInstance.addEventListener('save', (event: CustomEvent) => {
      this.value = event.detail.croppedImage;
      this.changeSubject.next(this);
    });
    
    document.body.appendChild(this.modalInstance);
  }

  private deletePicture(): void {
    this.value = '';
    this.changeSubject.next(this);
  }

  public getValue(): string {
    return this.value;
  }

  public setValue(value: string): void {
    this.value = value;
  }
}