import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, computed, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AdminProduct, AdminProductAttribute, AdminProductCategoryOption, AdminProductSpecification } from '../models/admin-product.model';
import { TranslatePipe } from '../../../../i18n/translate.pipe';
import { ButtonComponent } from '../../../../shared/ui/button/button.component';
import { InputComponent } from '../../../../shared/ui/input/input.component';
import { FormFieldComponent } from '../../../../shared/ui/form-field/form-field.component';
import { ToggleComponent } from '../../../../shared/ui/toggle/toggle.component';
import { BadgeComponent } from '../../../../shared/ui/badge/badge.component';
import { KeyValueEditorComponent } from '../../../../shared/ui/key-value-editor/key-value-editor.component';
import { ImageFieldComponent } from '../../../../shared/ui/image-field/image-field.component';
import { MediaPickerComponent } from '../../../../shared/media/media-picker/media-picker.component';
import { MediaAsset } from '../../../../core/media/models/media-asset.model';
import { MarketplaceHtmlEditorComponent } from '../../../project-editor/components/html-editor/marketplace-html-editor.component';
import { AdminProductHealth } from '../facade/admin-products.facade';
import { ProductHealthWidgetComponent, ProductHealthItem } from './product-health-widget/product-health-widget.component';
import { ProductVariantsEditorComponent } from './product-variants-editor/product-variants-editor.component';
import { IconComponent } from '../../../../shared/ui/icon/icon.component';

export type AdminProductEditorGroup = 'general' | 'media' | 'pricing' | 'inventory' | 'categories' | 'attributes' | 'seo' | 'visibility' | 'advanced';

@Component({
  selector: 'app-admin-product-form',
  standalone: true,
  imports: [
    FormsModule,
    TranslatePipe,
    ButtonComponent,
    InputComponent,
    FormFieldComponent,
    ToggleComponent,
    BadgeComponent,
    KeyValueEditorComponent,
    ImageFieldComponent,
    MediaPickerComponent,
    MarketplaceHtmlEditorComponent,
    ProductHealthWidgetComponent,
    ProductVariantsEditorComponent,
    IconComponent,
  ],
  templateUrl: './admin-product-form.component.html',
  styleUrls: ['./admin-product-form.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class AdminProductFormComponent {
  @Input({ required: true }) product!: AdminProduct;
  @Input() categories: AdminProductCategoryOption[] = [];
  @Input() allProducts: AdminProduct[] = [];
  @Input() locales: string[] = ['en'];
  @Input() mode: 'create' | 'edit' | 'duplicate' = 'create';
  @Input() health!: AdminProductHealth;

  @Output() productChange = new EventEmitter<Partial<AdminProduct>>();
  @Output() save = new EventEmitter<void>();

  protected mediaPickerOpen = false;

  readonly groups: { id: AdminProductEditorGroup; labelKey: string }[] = [
    { id: 'general', labelKey: 'adminProducts.groupGeneral' },
    { id: 'media', labelKey: 'adminProducts.groupMedia' },
    { id: 'pricing', labelKey: 'adminProducts.groupPricing' },
    { id: 'inventory', labelKey: 'adminProducts.groupInventory' },
    { id: 'categories', labelKey: 'adminProducts.groupCategories' },
    { id: 'attributes', labelKey: 'adminProducts.groupAttributes' },
    { id: 'seo', labelKey: 'adminProducts.groupSeo' },
    { id: 'visibility', labelKey: 'adminProducts.groupVisibility' },
    { id: 'advanced', labelKey: 'adminProducts.groupAdvanced' },
  ];

  readonly activeGroup = signal<AdminProductEditorGroup>('general');

  setGroup(group: AdminProductEditorGroup): void {
    this.activeGroup.set(group);
  }

  readonly healthItems = computed<ProductHealthItem[]>(() => [
    { labelKey: 'adminProducts.healthImages', done: this.health.hasImages },
    { labelKey: 'adminProducts.healthSeo', done: this.health.hasSeo },
    { labelKey: 'adminProducts.healthPrice', done: this.health.hasPrice },
    { labelKey: 'adminProducts.healthCategory', done: this.health.hasCategory },
    { labelKey: 'adminProducts.healthDescription', done: this.health.hasDescription },
    { labelKey: 'adminProducts.healthInventory', done: this.health.hasInventory },
  ]);

  updateField<K extends keyof AdminProduct>(key: K, value: AdminProduct[K]): void {
    this.productChange.emit({ [key]: value } as Partial<AdminProduct>);
  }

  /**
   * Name edits keep slug and SEO title in sync while (and only while) those
   * fields still hold their auto-derived value or are empty. The moment the
   * admin edits slug/SEO manually the derived value no longer matches, so we
   * stop regenerating - manual input is never overwritten.
   */
  updateName(value: string): void {
    const patch: Partial<AdminProduct> = { name: value };
    const previousAutoSlug = this.slugify(this.product.name);
    if (!this.product.slug || this.product.slug === previousAutoSlug) {
      patch.slug = this.slugify(value);
    }
    if (!this.product.seo.metaTitle || this.product.seo.metaTitle === this.product.name) {
      patch.seo = { ...this.product.seo, metaTitle: value };
    }
    this.productChange.emit(patch);
  }

  generateSku(): void {
    const prefix = this.slugify(this.product.name).split('-').slice(0, 2).map(part => part.slice(0, 3).toUpperCase()).join('-') || 'SKU';
    const suffix = Date.now().toString(36).slice(-4).toUpperCase();
    this.productChange.emit({ sku: `${prefix}-${suffix}` });
  }

  /** Fills empty SEO fields from name/short description; existing values stay untouched. */
  generateSeo(): void {
    this.productChange.emit({
      seo: {
        metaTitle: this.product.seo.metaTitle || this.product.name,
        metaDescription: this.product.seo.metaDescription || this.product.shortDescription || this.product.name,
        keywords: this.product.seo.keywords || this.slugify(this.product.name).split('-').filter(Boolean).join(', '),
      },
    });
  }

  private slugify(value: string): string {
    return value.toLowerCase().trim().replace(/[^a-z0-9а-яёա-ֆ]+/gi, '-').replace(/(^-|-$)/g, '');
  }

  translatedLocalesCount(): number {
    return this.locales.filter(locale => {
      const tr = this.product.translations[locale];
      return !!(tr && (tr.name || tr.shortDescription || tr.htmlDescription));
    }).length;
  }

  updateTranslation(locale: string, field: 'name' | 'shortDescription' | 'htmlDescription' | 'seoTitle' | 'seoDescription', value: string): void {
    this.productChange.emit({
      translations: {
        ...this.product.translations,
        [locale]: {
          ...(this.product.translations[locale] ?? {}),
          [field]: value,
        }
      }
    });
  }

  /** Storefront badge vocabulary from getBadgeClass (item.utils.ts) - same colors the customer sees. */
  readonly knownBadges = ['new', 'sale', 'exclusive', 'hot', 'limited', 'bestseller', 'featured'];
  private readonly badgeColors: Record<string, string> = {
    new: '#4caf50', sale: '#f44336', exclusive: '#9c27b0', hot: '#ff5722',
    limited: '#ff9800', bestseller: '#2196f3', featured: '#607d8b',
  };

  customBadge = '';

  badgeColor(badge: string): string {
    return this.badgeColors[badge.toLowerCase()] ?? '#78909c';
  }

  addBadge(badge: string): void {
    const value = badge.trim();
    if (!value || this.product.badges.includes(value)) {
      return;
    }
    this.productChange.emit({ badges: [...this.product.badges, value] });
  }

  addCustomBadge(): void {
    this.addBadge(this.customBadge);
    this.customBadge = '';
  }

  removeBadge(badge: string): void {
    this.productChange.emit({ badges: this.product.badges.filter(item => item !== badge) });
  }

  readonly createSpecRow = () => ({ key: '', value: '' });
  readonly createAttributeRow = () => ({ key: '', value: '' });

  updateSpecifications(rows: AdminProductSpecification[]): void {
    this.productChange.emit({ specifications: rows });
  }

  updateSpecificationField(index: number, field: 'key' | 'value', value: string): void {
    this.updateSpecifications(this.product.specifications.map((row, i) => i === index ? { ...row, [field]: value } : row));
  }

  updateAttributes(rows: AdminProductAttribute[]): void {
    this.productChange.emit({ attributes: rows });
  }

  updateAttributeField(index: number, field: 'key' | 'value', value: string): void {
    this.updateAttributes(this.product.attributes.map((row, i) => i === index ? { ...row, [field]: value } : row));
  }

  toggleRelated(id: string, checked: boolean): void {
    const current = this.product.relatedProductIds;
    this.productChange.emit({ relatedProductIds: checked ? [...new Set([...current, id])] : current.filter(item => item !== id) });
  }

  otherProducts(): AdminProduct[] {
    return this.allProducts.filter(item => item.id !== this.product.id);
  }

  setPrimaryImage(url: string): void {
    this.productChange.emit({ media: { ...this.product.media, images: url ? [url] : [] } });
  }

  updateVideos(value: string): void {
    this.productChange.emit({ media: { ...this.product.media, videos: value.split('\n').map(item => item.trim()).filter(Boolean) } });
  }

  openMediaPicker(): void {
    this.mediaPickerOpen = true;
  }

  addGalleryImage(asset: MediaAsset): void {
    this.productChange.emit({ media: { ...this.product.media, gallery: [...this.product.media.gallery, asset.url] } });
    this.mediaPickerOpen = false;
  }

  removeGalleryImage(index: number): void {
    this.productChange.emit({ media: { ...this.product.media, gallery: this.product.media.gallery.filter((_, i) => i !== index) } });
  }

  moveGalleryImage(index: number, direction: -1 | 1): void {
    const gallery = [...this.product.media.gallery];
    const target = index + direction;
    if (target < 0 || target >= gallery.length) return;
    [gallery[index], gallery[target]] = [gallery[target], gallery[index]];
    this.productChange.emit({ media: { ...this.product.media, gallery } });
  }

  finalPrice(): number {
    return Math.round(this.product.price * (1 - this.product.discount / 100));
  }

  stockStatusLabelKey(): string {
    switch (this.product.stockStatus) {
      case 'out_of_stock': return 'adminProducts.outOfStock';
      case 'low_stock': return 'adminProducts.lowStock';
      default: return 'adminProducts.inStock';
    }
  }
}
