import { Injectable } from '@angular/core';
import { map, Observable } from 'rxjs';
import { ConfigService } from './config.service';
import {
  BootstrapConfig,
  FooterColumnConfig,
  FooterConfig,
  FooterNavigationGroupConfig,
  FooterNavigationItemConfig,
  NavigationConfig,
  NavigationItemConfig
} from '../../shared/models/config';
import { StaticPageResolverService } from './static-page-resolver.service';
import { LanguageService } from '../../services/language.service';

export interface FooterResolvedItem {
  id: string;
  label: string;
  route: string;
  external?: boolean;
}

export interface FooterResolvedGroup {
  id: string;
  title: string;
  items: FooterResolvedItem[];
}

export interface FooterPaymentIcon {
  src: string;
  alt: string;
  width: number;
  height: number;
}

export interface FooterResolvedModel {
  groups: FooterResolvedGroup[];
  paymentIcons: FooterPaymentIcon[];
  copyrightText: string;
  logoUrl?: string;
}

@Injectable({ providedIn: 'root' })
export class FooterResolverService {
  constructor(
    private readonly configService: ConfigService,
    private readonly staticPageResolver: StaticPageResolverService,
    private readonly languageService: LanguageService
  ) {}

  resolveFooterModel(): Observable<FooterResolvedModel> {
    return this.configService.loadBootstrap().pipe(
      map((bootstrap) => this.resolveFooterModelFromBootstrap(bootstrap))
    );
  }

  resolveFooterModelFromBootstrap(bootstrap: BootstrapConfig): FooterResolvedModel {
    return {
      groups: this.resolveFooterGroups(bootstrap),
      paymentIcons: this.resolvePaymentIcons(bootstrap.footer),
      copyrightText: this.resolveCopyrightText(bootstrap),
      logoUrl: bootstrap.footer?.logoUrl
    };
  }

  private resolveFooterGroups(bootstrap: BootstrapConfig): FooterResolvedGroup[] {
    const footer = bootstrap.navigation?.footer ?? [];
    const lang = this.languageService.currentLanguage();

    // Footer Builder columns (admin/edit/footer) take priority over both the
    // legacy grouped-navigation config and the auto-grouped-by-static-page
    // fallback below - once a merchant builds columns, that's their footer.
    if (bootstrap.footer?.columns?.length) {
      const groups = this.resolveGroupsFromColumns(bootstrap.footer.columns, bootstrap, lang)
        .filter(group => group.items.length > 0);
      const social = this.resolveSocialGroup(bootstrap.footer);
      if (social) {
        groups.push(social);
      }
      return groups;
    }

    const contentPages = this.resolveBootstrapStaticPages(bootstrap, lang);

    if (this.isGroupedFooter(footer)) {
      const groups = footer
        .map((group, index) => this.resolveGroupFromConfig(group, bootstrap, lang, index))
        .filter((group): group is FooterResolvedGroup => group != null && group.items.length > 0);

      for (const group of contentPages) {
        if (!groups.some(existing => existing.id === group.id)) {
          groups.push(group);
        }
      }

      return groups;
    }

    const items = (footer as NavigationItemConfig[])
      .map(item => this.resolveLegacyItem(item, bootstrap, lang))
      .filter((item): item is FooterResolvedItem => item != null);

    if (!items.length) {
      return contentPages;
    }

    const groups: FooterResolvedGroup[] = [{
      id: 'footer-group-default',
      title: '',
      items
    }];

    groups.push(...contentPages);

    return groups;
  }

  private resolveBootstrapStaticPages(bootstrap: BootstrapConfig, lang: string): FooterResolvedGroup[] {
    const rawPages = Object.values(bootstrap.staticPages ?? {}) as any[];
    const pages = rawPages
      .filter(page => page.showInFooter !== false)
      .map(page => ({ raw: page, resolved: this.staticPageResolver.resolveByKeyFromBootstrap(bootstrap, page.id ?? '', lang) }))
      .filter(entry => entry.resolved !== null);

    const groups = new Map<string, FooterResolvedGroup>();

    for (const page of pages) {
      const raw = page.raw;
      const resolved = page.resolved!;
      const groupTitle = raw?.footerGroup || 'Legal';
      const groupId = `footer-group-${String(groupTitle).toLowerCase().replace(/\s+/g, '-')}`;
      if (!groups.has(groupId)) {
        groups.set(groupId, { id: groupId, title: groupTitle, items: [] });
      }
      groups.get(groupId)!.items.push({ id: resolved.id, label: resolved.title, route: resolved.route });
    }

    const social = this.resolveSocialGroup(bootstrap.footer);
    if (social) {
      groups.set(social.id, social);
    }

    return [...groups.values()].map(group => ({
      ...group,
      items: group.items.sort((left, right) => left.label.localeCompare(right.label))
    }));
  }

  private resolveSocialGroup(footerConfig: FooterConfig | undefined): FooterResolvedGroup | null {
    const socialLinks = footerConfig?.socialLinks ?? [];
    if (socialLinks.length === 0) {
      return null;
    }
    return {
      id: 'footer-group-social',
      title: 'Social',
      items: socialLinks.map(link => ({ id: link.id, label: link.label, route: link.url, external: true }))
    };
  }

  /** Footer Builder columns -> resolved groups. Page-linked entries resolve through StaticPageResolverService (so a page's route stays correct even if it changes); custom URLs pass through as external links. */
  private resolveGroupsFromColumns(columns: FooterColumnConfig[], bootstrap: BootstrapConfig, lang: string): FooterResolvedGroup[] {
    return columns.map((column, index) => ({
      id: column.id || `footer-group-${index}`,
      title: column.title,
      items: column.links
        .map((link): FooterResolvedItem | null => {
          if (link.pageKey) {
            const staticPage = this.staticPageResolver.resolveByKeyFromBootstrap(bootstrap, link.pageKey, lang);
            if (!staticPage) {
              return null;
            }
            return { id: link.id, label: link.label || staticPage.title, route: staticPage.route };
          }
          if (!link.url) {
            return null;
          }
          return { id: link.id, label: link.label || link.url, route: link.url, external: true };
        })
        .filter((item): item is FooterResolvedItem => item !== null),
    }));
  }

  private resolveGroupFromConfig(
    group: FooterNavigationGroupConfig,
    bootstrap: BootstrapConfig,
    lang: string,
    index: number
  ): FooterResolvedGroup | null {
    const items = (group.items ?? [])
      .map(item => this.resolveGroupItem(item, bootstrap, lang))
      .filter((item): item is FooterResolvedItem => item != null);

    if (!items.length) {
      return null;
    }

    return {
      id: `footer-group-${index}`,
      title: this.staticPageResolver.resolveFooterTitle(group.groupTitle, lang),
      items
    };
  }

  private resolveGroupItem(
    item: FooterNavigationItemConfig,
    bootstrap: BootstrapConfig,
    lang: string
  ): FooterResolvedItem | null {
    if (item.visible === false) {
      return null;
    }

    if (item.type === 'staticPage' && item.key) {
      const staticPage = this.staticPageResolver.resolveByKeyFromBootstrap(bootstrap, item.key, lang);
      if (!staticPage) {
        return null;
      }

      return {
        id: `static-${item.key}`,
        label: staticPage.title,
        route: staticPage.route
      };
    }

    const label = typeof item.label === 'string'
      ? item.label
      : this.staticPageResolver.resolveFooterTitle(item.label, lang);

    if (!item.route || !label) {
      return null;
    }

    return {
      id: `${item.type}-${label}`,
      label,
      route: item.route
    };
  }

  private resolveLegacyItem(item: NavigationItemConfig, bootstrap: BootstrapConfig, lang: string): FooterResolvedItem | null {
    if (item.visible === false) {
      return null;
    }

    if (item.type === 'staticPage' && item.key) {
      const staticPage = this.staticPageResolver.resolveByKeyFromBootstrap(bootstrap, item.key, lang);
      if (!staticPage) {
        return null;
      }

      return {
        id: item.id,
        label: staticPage.title,
        route: staticPage.route
      };
    }

    if (!item.route) {
      return null;
    }

    return {
      id: item.id,
      label: item.labelKey ?? item.id,
      route: item.route
    };
  }

  private isGroupedFooter(footer: NavigationConfig['footer']): footer is FooterNavigationGroupConfig[] {
    return Array.isArray(footer) && footer.length > 0 && 'items' in footer[0];
  }

  private resolvePaymentIcons(footerConfig: FooterConfig | undefined): FooterPaymentIcon[] {
    if (!footerConfig?.paymentIcons?.length) {
      return [];
    }

    return footerConfig.paymentIcons
      .filter(icon => !!icon?.src)
      .map(icon => ({
        src: icon.src,
        alt: icon.alt || 'Payment icon',
        width: icon.width ?? 40,
        height: icon.height ?? 28
      }));
  }

  private resolveCopyrightText(bootstrap: BootstrapConfig): string {
    const configured = bootstrap.footer?.copyrightText;
    const lang = this.languageService.currentLanguage();

    if (typeof configured === 'string' && configured.trim()) {
      return configured;
    }

    if (configured && typeof configured === 'object') {
      return this.staticPageResolver.resolveFooterTitle(configured, lang);
    }

    return '';
  }
}