import { reactive } from 'vue';
import type { ControlDef, EditorConfig } from './types';

/**
 * Theme templates (`zadex_template` posts: header, footer, single, archive ...). PHP puts `themeTemplate` on the
 * boot config for them (includes/Theme/ThemeBuilder.php); display conditions are saved separately from the
 * document through `PUT /templates/{id}/conditions` and matched by includes/Theme/Conditions.php.
 */
export type ThemeTemplateType = 'header' | 'footer' | 'single' | 'archive' | 'search' | '404' | 'loop-item' | 'popup' | 'product' | 'product_archive';

export type ConditionTarget =
  | 'entire' | 'front' | 'post_type' | 'singular' | 'specific' | 'archive' | 'taxonomy' | 'term' | 'author' | 'date' | 'search' | '404'
  // WooCommerce (includes/WooCommerce/Conditions.php), offered when the integration is active.
  | 'product' | 'product_in_cat' | 'product_in_tag' | 'product_specific' | 'shop' | 'product_archive' | 'product_cat_archive' | 'product_tag_archive';

export interface ConditionRule {
  mode: 'include' | 'exclude';
  target: ConditionTarget;
  sub: string;
  value: number | string;
}

export interface ThemeTemplateSettings {
  sticky?: boolean;
  transparent?: boolean;
  layout?: 'full_width' | 'canvas';
  preview_post?: number | string;
}

export interface ThemeTemplateConfig {
  type: ThemeTemplateType;
  label?: string;
  conditions: ConditionRule[];
  summary?: string;
  settings: ThemeTemplateSettings;
}

export interface TemplateOptionsQuery {
  target: string;
  sub?: string;
  search?: string;
}

/** Option of the conditions dialog selects (post / term / user ids are numbers). */
export interface ConditionOption {
  value: string | number;
  label: string;
}

export interface TemplateOptionsResponse {
  subs: ConditionOption[];
  values: ConditionOption[];
}

export interface SaveConditionsResponse {
  conditions: ConditionRule[];
  summary: string;
}

/** Badge text per type (source strings for t()). */
export const TYPE_BADGES: Record<ThemeTemplateType, string> = {
  header: 'Header template',
  footer: 'Footer template',
  single: 'Single template',
  archive: 'Archive template',
  search: 'Search template',
  '404': '404 template',
  'loop-item': 'Loop item template',
  popup: 'Popup template',
  product: 'Single product template',
  product_archive: 'Product archive template',
};

/** What a target needs: a `sub` select (post type / taxonomy) and/or a value select. */
export interface TargetDef {
  value: ConditionTarget;
  label: string;
  /** `sub` select: 'post_type' | 'taxonomy'; `optional` adds an "All" choice. */
  sub?: { kind: 'post_type' | 'taxonomy'; optional?: boolean };
  /** Value select (posts, terms, authors), searchable; `optional` adds an "All" choice; `label` names it. */
  pick?: { optional?: boolean; label?: string };
  /** Only offered when this integration is active (`EditorConfig.integrations`). */
  integration?: string;
}

export const TARGETS: TargetDef[] = [
  { value: 'entire', label: 'Entire site' },
  { value: 'front', label: 'Front page' },
  { value: 'singular', label: 'Singular', sub: { kind: 'post_type', optional: true } },
  { value: 'post_type', label: 'Post type', sub: { kind: 'post_type' } },
  { value: 'specific', label: 'Specific post', sub: { kind: 'post_type' }, pick: {} },
  { value: 'archive', label: 'Archive', sub: { kind: 'post_type', optional: true } },
  { value: 'taxonomy', label: 'Taxonomy archive', sub: { kind: 'taxonomy' } },
  { value: 'term', label: 'Term', sub: { kind: 'taxonomy' }, pick: {} },
  { value: 'author', label: 'Author archive', pick: { optional: true } },
  { value: 'date', label: 'Date archive' },
  { value: 'search', label: 'Search results' },
  { value: '404', label: '404 page' },
  { value: 'product', label: 'All products', integration: 'woocommerce' },
  { value: 'product_in_cat', label: 'Products in category', integration: 'woocommerce', pick: { label: 'Category' } },
  { value: 'product_in_tag', label: 'Products with tag', integration: 'woocommerce', pick: { label: 'Tag' } },
  { value: 'product_specific', label: 'Specific product', integration: 'woocommerce', pick: { label: 'Product' } },
  { value: 'shop', label: 'Shop page', integration: 'woocommerce' },
  { value: 'product_archive', label: 'All product archives', integration: 'woocommerce' },
  { value: 'product_cat_archive', label: 'Product category archive', integration: 'woocommerce', pick: { optional: true, label: 'Category' } },
  { value: 'product_tag_archive', label: 'Product tag archive', integration: 'woocommerce', pick: { optional: true, label: 'Tag' } },
];

/** Targets offered for the active integrations (WooCommerce targets need `integrations: ['woocommerce']`). */
export function availableTargets(integrations: readonly string[] = []): TargetDef[] {
  return TARGETS.filter((d) => !d.integration || integrations.includes(d.integration));
}

/** First target of a new rule for a template type (product templates start with "All products" ...). */
export function defaultTarget(type: ThemeTemplateType | undefined, first: boolean): ConditionTarget {
  if (type === 'product') return 'product';
  if (type === 'product_archive') return 'product_archive';
  return first ? 'entire' : 'singular';
}

export function targetDef(target: string): TargetDef | undefined {
  return TARGETS.find((d) => d.value === target);
}

/** A new rule for a target, with the first sub preselected when the target requires one. */
export function newRule(target: ConditionTarget = 'entire', mode: ConditionRule['mode'] = 'include'): ConditionRule {
  return { mode, target, sub: '', value: '' };
}

/** Normalises rules coming from the config / REST (unknown targets dropped). */
export function normalizeRules(input: unknown): ConditionRule[] {
  if (!Array.isArray(input)) return [];
  const out: ConditionRule[] = [];
  for (const raw of input) {
    if (!raw || typeof raw !== 'object') continue;
    const r = raw as Record<string, unknown>;
    if (!targetDef(String(r.target))) continue;
    const value = typeof r.value === 'number' || typeof r.value === 'string' ? r.value : '';
    out.push({ mode: r.mode === 'exclude' ? 'exclude' : 'include', target: r.target as ConditionTarget, sub: typeof r.sub === 'string' ? r.sub : '', value });
  }
  return out;
}

/** A rule is complete when every required select has a value. */
export function isRuleComplete(rule: ConditionRule): boolean {
  const def = targetDef(rule.target);
  if (!def) return false;
  if (def.sub && !def.sub.optional && !rule.sub) return false;
  if (def.pick && !def.pick.optional && (rule.value === '' || rule.value === 0)) return false;
  return true;
}

/**
 * One-line summary ("Entire site", "Singular: post, not Specific post: page #12"). `translate` is t();
 * `labels` optionally maps sub/value keys to display names.
 */
export function summarize(rules: ConditionRule[], translate: (s: string) => string = (s) => s, labels: Record<string, string> = {}): string {
  if (!rules.length) return translate('No conditions');
  return rules
    .map((r) => {
      let text = translate(targetDef(r.target)?.label ?? r.target);
      const details = [r.sub ? labels[`sub:${r.sub}`] ?? r.sub : '', r.value !== '' && r.value !== 0 ? labels[`value:${r.value}`] ?? `#${r.value}` : ''].filter(Boolean);
      if (details.length) text += `: ${details.join(' ')}`;
      return r.mode === 'exclude' ? `${translate('not')} ${text}` : text;
    })
    .join(', ');
}

/** Template settings controls shown in the Page panel (values live in page settings `tpl_*`). */
export function templateControls(type: ThemeTemplateType): ControlDef[] {
  const out: ControlDef[] = [];
  if (type === 'header') {
    out.push(
      { id: 'tpl_sticky', type: 'switch', label: 'Sticky header', tab: 'content', section: 'p_template', default: false, description: 'Stays at the top of the window while scrolling.' },
      { id: 'tpl_transparent', type: 'switch', label: 'Transparent header', tab: 'content', section: 'p_template', default: false, description: 'Lies over the content below it (hero sections).' },
    );
  }
  if (type === 'single' || type === 'archive' || type === 'search' || type === '404' || type === 'product' || type === 'product_archive') {
    out.push({
      id: 'tpl_layout',
      type: 'select',
      label: 'Layout',
      tab: 'content',
      section: 'p_template',
      default: 'full_width',
      options: [
        { value: 'full_width', label: 'Full width (theme header and footer)' },
        { value: 'canvas', label: 'Canvas (blank page)' },
      ],
      labelBlock: true,
    });
  }
  out.push({
    id: 'tpl_preview_post',
    type: 'select',
    label: 'Preview with',
    tab: 'content',
    section: 'p_template',
    default: '0',
    optionsFrom: 'previewPosts',
    options: [{ value: '0', label: 'Latest post' }],
    labelBlock: true,
    description: 'The post shown as the current post in the editor. Applies after saving and reloading.',
  });
  return out;
}

/** Shared editor state for the theme template (conditions dialog + saved conditions). */
export const themeState = reactive({
  conditions: [] as ConditionRule[],
  summary: '',
  dialogOpen: false,
  /** Set once the dialog auto-opened after the first publish (never twice per session). */
  autoOpened: false,
});

export function themeTemplateOf(config: Pick<EditorConfig, 'themeTemplate'> | null | undefined): ThemeTemplateConfig | null {
  const tpl = config?.themeTemplate;
  return tpl && typeof tpl === 'object' && typeof tpl.type === 'string' ? tpl : null;
}

/** Loads the config's conditions into the shared state (boot). */
export function initThemeState(config: Pick<EditorConfig, 'themeTemplate'> | null | undefined): void {
  const tpl = themeTemplateOf(config);
  themeState.conditions = tpl ? normalizeRules(tpl.conditions) : [];
  themeState.summary = tpl?.summary ?? '';
  themeState.dialogOpen = false;
  themeState.autoOpened = false;
}

/** The first publish of a template without conditions opens the conditions dialog. */
export function shouldAutoOpen(prevStatus: string, status: string, conditions: ConditionRule[], alreadyOpened: boolean): boolean {
  return !alreadyOpened && prevStatus !== 'publish' && status === 'publish' && conditions.length === 0;
}
