import { ChangeDetectionStrategy, Component, HostListener, computed, effect, inject, signal } from '@angular/core';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { toSignal } from '@angular/core/rxjs-interop';
import { map } from 'rxjs/operators';
import { ProjectEditorFacade } from '../facade/project-editor.facade';
import { ProjectEditorNavComponent } from '../components/project-editor-nav.component';
import { ProjectEditorGeneralSectionComponent } from '../sections/general-section.component';
import { ProjectEditorBrandingSectionComponent } from '../sections/branding-section.component';
import { ProjectEditorThemeSectionComponent } from '../sections/theme-section.component';
import { ProjectEditorHeaderSectionComponent } from '../sections/header-section.component';
import { ProjectEditorFooterSectionComponent } from '../sections/footer-section.component';
import { ProjectEditorHomepageSectionComponent } from '../sections/homepage-section.component';
import { ProjectEditorWidgetsSectionComponent } from '../sections/widgets-section.component';
import { ProjectEditorFeaturesSectionComponent } from '../sections/features-section.component';
import { ProjectEditorLanguagesSectionComponent } from '../sections/languages-section.component';
import { ProjectEditorNavigationSectionComponent } from '../sections/navigation-section.component';
import { ProjectEditorPreviewSectionComponent } from '../sections/preview-section.component';
import { TranslatePipe } from '../../../i18n/translate.pipe';
import { TranslateService } from '../../../i18n/translate.service';
import { LanguageService } from '../../../services/language.service';
import { ConfirmDialogComponent } from '../../../shared/ui/confirm-dialog/confirm-dialog.component';
import { IconComponent } from '../../../shared/ui/icon/icon.component';
import { ButtonComponent } from '../../../shared/ui/button/button.component';
import { StaticPagesEditorComponent } from '../../content-management/components/static-pages-editor.component';
import { ProjectEditorSaveBarComponent } from '../components/save-bar/project-editor-save-bar.component';
import { EDITOR_SECTION_BOOTSTRAP_KEYS, ProjectEditorSectionId } from '../models/project-editor.model';
import { BUILDER_GROUPS, SECTION_TO_GROUP } from '../builder/builder-groups.model';
import { BuilderLivePreviewComponent } from '../components/live-preview/builder-live-preview.component';
import { BuilderPropertySearchComponent } from '../components/property-search/builder-property-search.component';

/** Sections that currently expose highlight-mapped fields (see HighlightSourceDirective usages) - showing the panel elsewhere would just be an inert, unhighlightable diagram. */
const SECTIONS_WITH_LIVE_PREVIEW: ProjectEditorSectionId[] = ['branding', 'theme', 'homepage'];

const KNOWN_SECTIONS: ProjectEditorSectionId[] = [
  'general', 'branding', 'theme', 'header', 'footer', 'homepage', 'widgets', 'static-pages', 'features', 'languages', 'navigation', 'preview'
];

const SECTION_LABEL_KEYS: Record<ProjectEditorSectionId, string> = {
  general: 'builder.general',
  branding: 'builder.branding',
  theme: 'builder.theme',
  header: 'builder.header',
  footer: 'builder.footer',
  homepage: 'builder.homepage',
  widgets: 'builder.widgets',
  'static-pages': 'builder.staticPages',
  features: 'builder.marketplaceFeatures',
  languages: 'builder.languagesTab',
  navigation: 'builder.navigationTab',
  preview: 'builder.preview',
};

@Component({
  selector: 'app-project-editor-page',
  standalone: true,
  imports: [
    RouterLink,
    TranslatePipe,
    ProjectEditorNavComponent,
    ProjectEditorGeneralSectionComponent,
    ProjectEditorBrandingSectionComponent,
    ProjectEditorThemeSectionComponent,
    ProjectEditorHeaderSectionComponent,
    ProjectEditorFooterSectionComponent,
    ProjectEditorHomepageSectionComponent,
    ProjectEditorWidgetsSectionComponent,
    StaticPagesEditorComponent,
    ProjectEditorFeaturesSectionComponent,
    ProjectEditorLanguagesSectionComponent,
    ProjectEditorNavigationSectionComponent,
    ProjectEditorPreviewSectionComponent,
    ProjectEditorSaveBarComponent,
    IconComponent,
    ButtonComponent,
    ConfirmDialogComponent,
    BuilderLivePreviewComponent,
    BuilderPropertySearchComponent,
  ],
  templateUrl: './project-editor-page.component.html',
  styleUrls: ['./project-editor-page.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ProjectEditorPageComponent {
  readonly facade = inject(ProjectEditorFacade);
  private readonly route = inject(ActivatedRoute);
  private readonly translate = inject(TranslateService);
  private readonly languageService = inject(LanguageService);
  readonly bootstrap = this.facade.bootstrap;
  readonly activeSection = this.facade.activeSection;
  readonly canResetActiveSection = () => !!EDITOR_SECTION_BOOTSTRAP_KEYS[this.activeSection()];

  readonly mobileDrawerOpen = signal(false);
  readonly helpOpen = signal(false);

  private readonly routeSection = toSignal(
    this.route.paramMap.pipe(map(params => params.get('section') as ProjectEditorSectionId | null)),
    { initialValue: null }
  );

  readonly activeGroup = computed(() => {
    const groupId = SECTION_TO_GROUP[this.activeSection()];
    return BUILDER_GROUPS.find(g => g.id === groupId) ?? null;
  });

  readonly sectionTitleKey = computed(() => SECTION_LABEL_KEYS[this.activeSection()]);

  readonly isModifiedActiveSection = computed(() => this.facade.modifiedSections().has(this.activeSection()));

  readonly showLivePreview = computed(() => SECTIONS_WITH_LIVE_PREVIEW.includes(this.activeSection()));

  readonly overviewRoute = computed(() => ['/', this.languageService.currentLanguage(), 'edit']);

  /** Persistent escape hatch back to the admin dashboard - section editors previously had no route to the backoffice at all. */
  readonly dashboardRoute = computed(() => ['/', this.languageService.currentLanguage(), 'backoffice', 'dashboard']);

  constructor() {
    this.facade.loadBootstrap();
    effect(() => {
      const section = this.routeSection();
      if (section && KNOWN_SECTIONS.includes(section)) {
        this.facade.setActiveSection(section);
        this.helpOpen.set(false);
        this.mobileDrawerOpen.set(false);
      }
    });
  }

  readonly resetSectionConfirmOpen = signal(false);

  resetActiveSection(): void {
    this.resetSectionConfirmOpen.set(true);
  }

  confirmResetActiveSection(): void {
    this.resetSectionConfirmOpen.set(false);
    this.facade.resetSection(this.activeSection());
  }

  toggleHelp(): void {
    this.helpOpen.update(open => !open);
  }

  toggleMobileDrawer(): void {
    this.mobileDrawerOpen.update(open => !open);
  }

  closeMobileDrawer(): void {
    this.mobileDrawerOpen.set(false);
  }

  @HostListener('window:beforeunload', ['$event'])
  warnBeforeUnload(event: BeforeUnloadEvent): void {
    if (this.facade.dirty()) {
      event.preventDefault();
      event.returnValue = '';
    }
  }

  /**
   * Ctrl/Cmd+Z undoes, Ctrl/Cmd+Shift+Z or Ctrl/Cmd+Y redoes. Skipped while a
   * text control has focus so native per-field text undo is preserved; the
   * save-bar buttons cover that case.
   */
  @HostListener('document:keydown', ['$event'])
  handleUndoRedoShortcut(event: KeyboardEvent): void {
    if (event.key === 'Escape' && this.mobileDrawerOpen()) {
      this.mobileDrawerOpen.set(false);
      return;
    }
    if (!event.ctrlKey && !event.metaKey) {
      return;
    }
    const target = event.target as HTMLElement | null;
    const tag = target?.tagName;
    if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || target?.isContentEditable) {
      return;
    }
    const key = event.key.toLowerCase();
    if (key === 'z' && !event.shiftKey) {
      event.preventDefault();
      this.facade.undo();
    } else if (key === 'y' || (key === 'z' && event.shiftKey)) {
      event.preventDefault();
      this.facade.redo();
    }
  }
}
