import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, computed, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { DatePipe } from '@angular/common';
import { AdminCategory, AdminCategoryAttribute } from '../models/admin-category.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 { AdminCategoryHealth } from '../facade/admin-categories.facade';
import { CategoryHealthWidgetComponent, CategoryHealthItem } from './category-health-widget/category-health-widget.component';

export type AdminCategoryEditorGroup = 'general' | 'media' | 'seo' | 'visibility' | 'navigation' | 'attributes' | 'advanced';

@Component({
  selector: 'app-admin-category-form',
  standalone: true,
  imports: [
    FormsModule,
    DatePipe,
    TranslatePipe,
    ButtonComponent,
    InputComponent,
    FormFieldComponent,
    ToggleComponent,
    BadgeComponent,
    KeyValueEditorComponent,
    ImageFieldComponent,
    CategoryHealthWidgetComponent,
  ],
  templateUrl: './admin-category-form.component.html',
  styleUrls: ['./admin-category-form.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class AdminCategoryFormComponent {
  @Input({ required: true }) category!: AdminCategory;
  @Input() parentOptions: AdminCategory[] = [];
  @Input() breadcrumb: string[] = [];
  @Input() children: AdminCategory[] = [];
  @Input() slugTaken = false;
  @Input() slugCheckError = false;
  @Input() locales: string[] = ['en'];
  @Input() mode: 'create' | 'edit' = 'create';
  @Input() health!: AdminCategoryHealth;

  @Output() categoryChange = new EventEmitter<Partial<AdminCategory>>();
  @Output() saveDraft = new EventEmitter<void>();
  @Output() publish = new EventEmitter<void>();

  readonly groups: { id: AdminCategoryEditorGroup; labelKey: string }[] = [
    { id: 'general', labelKey: 'adminCategories.groupGeneral' },
    { id: 'media', labelKey: 'adminCategories.groupMedia' },
    { id: 'seo', labelKey: 'adminCategories.groupSeo' },
    { id: 'visibility', labelKey: 'adminCategories.groupVisibility' },
    { id: 'navigation', labelKey: 'adminCategories.groupNavigation' },
    { id: 'attributes', labelKey: 'adminCategories.groupAttributes' },
    { id: 'advanced', labelKey: 'adminCategories.groupAdvanced' },
  ];

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

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

  readonly healthItems = computed<CategoryHealthItem[]>(() => [
    { labelKey: 'adminCategories.healthImage', done: this.health.hasImage },
    { labelKey: 'adminCategories.healthSeo', done: this.health.hasSeo },
    { labelKey: 'adminCategories.healthDescription', done: this.health.hasDescription },
    { labelKey: 'adminCategories.healthParent', done: this.health.hasValidParent },
    { labelKey: 'adminCategories.healthVisibility', done: this.health.isVisible },
    { labelKey: 'adminCategories.healthProducts', done: this.health.hasProducts },
  ]);

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

  /**
   * Title edits keep the slug and SEO title in sync only while they still hold
   * their auto-derived value (or are empty). A manually edited slug/SEO title
   * no longer matches the derived value, so it is never overwritten.
   */
  updateTitle(value: string): void {
    const patch: Partial<AdminCategory> = { title: value };
    const previousAutoSlug = this.slugify(this.category.title);
    if (!this.category.slug || this.category.slug === previousAutoSlug) {
      patch.slug = this.slugify(value);
    }
    if (!this.category.seo.metaTitle || this.category.seo.metaTitle === this.category.title) {
      patch.seo = { ...this.category.seo, metaTitle: value };
    }
    this.categoryChange.emit(patch);
  }

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

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

  updateTranslation(locale: string, field: 'title' | 'description', value: string): void {
    this.categoryChange.emit({
      translations: {
        ...this.category.translations,
        [locale]: { ...(this.category.translations[locale] ?? {}), [field]: value }
      }
    });
  }

  setImage(url: string): void {
    this.updateField('imageUrl', url);
  }

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

  updateAttributes(rows: AdminCategoryAttribute[]): void {
    this.categoryChange.emit({ attributes: rows });
  }

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