import axios from 'axios';
import { isDatabaseConnected } from '../config/database';
import VersionCacheModel from '../models/VersionCache';

export interface VersionFeatures {
  containers: boolean;
  loopGrid: boolean;
  nestedAccordion: boolean;
  nestedTabs: boolean;
  linkInBio: boolean;
  offCanvas: boolean;
  globalClass: boolean;
  aiFeatures: boolean;
  flexboxContainer: boolean;
  // 4.0.0+
  atomicForms: boolean;
  interactions: boolean;
  components: boolean;
}

export interface VersionDefinition {
  version: string;
  releaseDate: string;
  schemaVersion: string;
  useContainers: boolean;
  features: VersionFeatures;
  deprecated: string[];
  notes: string;
}

export interface VersionRegistry {
  versions: VersionDefinition[];
  latestVersion: string;
  lastUpdated: string;
  source: 'bundled' | 'cached' | 'live';
}

// Bundled baseline registry — updated by "Refresh" action at runtime
const BUNDLED_REGISTRY: VersionRegistry = {
  latestVersion: '4.0.3',
  lastUpdated: '2026-04-22',
  source: 'bundled',
  versions: [
    {
      version: '3.5.0',
      releaseDate: '2022-01-01',
      schemaVersion: '0.4',
      useContainers: false,
      features: {
        containers: false, loopGrid: false, nestedAccordion: false,
        nestedTabs: false, linkInBio: false, offCanvas: false,
        globalClass: false, aiFeatures: false, flexboxContainer: false,
        atomicForms: false, interactions: false, components: false,
      },
      deprecated: [],
      notes: 'Legacy section/column layout. No flexbox containers.',
    },
    {
      version: '3.6.0',
      releaseDate: '2022-06-01',
      schemaVersion: '0.4',
      useContainers: true,
      features: {
        containers: true, loopGrid: false, nestedAccordion: false,
        nestedTabs: false, linkInBio: false, offCanvas: false,
        globalClass: false, aiFeatures: false, flexboxContainer: true,
        atomicForms: false, interactions: false, components: false,
      },
      deprecated: [],
      notes: 'Flexbox Container introduced. Sections/columns still supported.',
    },
    {
      version: '3.7.0',
      releaseDate: '2022-09-01',
      schemaVersion: '0.4',
      useContainers: true,
      features: {
        containers: true, loopGrid: true, nestedAccordion: true,
        nestedTabs: false, linkInBio: false, offCanvas: false,
        globalClass: false, aiFeatures: false, flexboxContainer: true,
        atomicForms: false, interactions: false, components: false,
      },
      deprecated: [],
      notes: 'Loop Grid widget added. Nested Accordion support.',
    },
    {
      version: '3.8.0',
      releaseDate: '2022-11-01',
      schemaVersion: '0.4',
      useContainers: true,
      features: {
        containers: true, loopGrid: true, nestedAccordion: true,
        nestedTabs: true, linkInBio: true, offCanvas: false,
        globalClass: false, aiFeatures: false, flexboxContainer: true,
        atomicForms: false, interactions: false, components: false,
      },
      deprecated: [],
      notes: 'Link in Bio, Nested Tabs.',
    },
    {
      version: '3.10.0',
      releaseDate: '2023-03-01',
      schemaVersion: '0.4',
      useContainers: true,
      features: {
        containers: true, loopGrid: true, nestedAccordion: true,
        nestedTabs: true, linkInBio: true, offCanvas: true,
        globalClass: false, aiFeatures: false, flexboxContainer: true,
        atomicForms: false, interactions: false, components: false,
      },
      deprecated: [],
      notes: 'Off Canvas widget. Container improvements.',
    },
    {
      version: '3.14.0',
      releaseDate: '2023-10-01',
      schemaVersion: '0.4',
      useContainers: true,
      features: {
        containers: true, loopGrid: true, nestedAccordion: true,
        nestedTabs: true, linkInBio: true, offCanvas: true,
        globalClass: true, aiFeatures: true, flexboxContainer: true,
        atomicForms: false, interactions: false, components: false,
      },
      deprecated: [],
      notes: 'AI Copilot features, Global Class.',
    },
    {
      version: '3.16.0',
      releaseDate: '2024-01-01',
      schemaVersion: '0.4',
      useContainers: true,
      features: {
        containers: true, loopGrid: true, nestedAccordion: true,
        nestedTabs: true, linkInBio: true, offCanvas: true,
        globalClass: true, aiFeatures: true, flexboxContainer: true,
        atomicForms: false, interactions: false, components: false,
      },
      deprecated: [],
      notes: 'Performance improvements, expanded AI tools.',
    },
    {
      version: '3.21.0',
      releaseDate: '2024-05-01',
      schemaVersion: '0.4',
      useContainers: true,
      features: {
        containers: true, loopGrid: true, nestedAccordion: true,
        nestedTabs: true, linkInBio: true, offCanvas: true,
        globalClass: true, aiFeatures: true, flexboxContainer: true,
        atomicForms: false, interactions: false, components: false,
      },
      deprecated: [],
      notes: 'Full container and AI support. Display Conditions for elements.',
    },
    {
      version: '4.0.0',
      releaseDate: '2026-03-30',
      schemaVersion: '0.4',
      useContainers: true,
      features: {
        containers: true, loopGrid: true, nestedAccordion: true,
        nestedTabs: true, linkInBio: true, offCanvas: true,
        globalClass: true, aiFeatures: true, flexboxContainer: true,
        atomicForms: true, interactions: true, components: true,
      },
      deprecated: [],
      notes: 'Major release. Atomic Forms (composable fields), Interactions system (scroll triggers, custom effects), Components (reusable Pro blocks), custom fonts in typography.',
    },
    {
      version: '4.0.3',
      releaseDate: '2026-04-22',
      schemaVersion: '0.4',
      useContainers: true,
      features: {
        containers: true, loopGrid: true, nestedAccordion: true,
        nestedTabs: true, linkInBio: true, offCanvas: true,
        globalClass: true, aiFeatures: true, flexboxContainer: true,
        atomicForms: true, interactions: true, components: true,
      },
      deprecated: [],
      notes: 'Agency plan release. Fixes for Interactions, Atomic Forms field exposure, and component publishing.',
    },
  ],
};

let runtimeRegistry: VersionRegistry = { ...BUNDLED_REGISTRY };

export function getRegistry(): VersionRegistry {
  return runtimeRegistry;
}

export function getVersionDefinition(version: string): VersionDefinition | undefined {
  return runtimeRegistry.versions.find((v) => v.version === version);
}

export function getLatestVersion(): VersionDefinition {
  const latest = runtimeRegistry.versions.find((v) => v.version === runtimeRegistry.latestVersion);
  return latest ?? runtimeRegistry.versions[runtimeRegistry.versions.length - 1];
}

export function getSupportedVersions(): string[] {
  return runtimeRegistry.versions.map((v) => v.version);
}

export function supportsContainers(version: string): boolean {
  const def = getVersionDefinition(version);
  if (!def) return true;
  return def.useContainers;
}

// Compare semver strings — returns 1 if a > b, -1 if a < b, 0 if equal
function semverCompare(a: string, b: string): number {
  const pa = a.split('.').map(Number);
  const pb = b.split('.').map(Number);
  for (let i = 0; i < 3; i++) {
    if ((pa[i] ?? 0) > (pb[i] ?? 0)) return 1;
    if ((pa[i] ?? 0) < (pb[i] ?? 0)) return -1;
  }
  return 0;
}

// Attempt to fetch the latest Elementor (free) version from WordPress.org API as a proxy signal.
// Elementor Pro versions track closely with the free plugin versions.
async function fetchLatestFromWordPressOrg(): Promise<string | null> {
  try {
    const res = await axios.get(
      'https://api.wordpress.org/plugins/info/1.2/?action=plugin_information&request[slug]=elementor&request[fields][versions]=0',
      { timeout: 8000 }
    );
    const version: string = res.data?.version;
    if (version && /^\d+\.\d+\.\d+$/.test(version)) return version;
    return null;
  } catch {
    return null;
  }
}

export async function refreshRegistry(): Promise<{ updated: boolean; changes: string[]; registry: VersionRegistry }> {
  const changes: string[] = [];

  const liveVersion = await fetchLatestFromWordPressOrg();
  let updatedRegistry = { ...runtimeRegistry };

  if (liveVersion && semverCompare(liveVersion, updatedRegistry.latestVersion) > 0) {
    // A newer version was detected — add it to the registry
    const prevLatest = getLatestVersion();
    const newDef: VersionDefinition = {
      version: liveVersion,
      releaseDate: new Date().toISOString().split('T')[0],
      schemaVersion: '0.4',
      useContainers: true,
      features: { ...prevLatest.features },
      deprecated: [],
      notes: `Auto-detected from WordPress.org. Review changelog at https://elementor.com/changelog/`,
    };

    updatedRegistry = {
      ...updatedRegistry,
      latestVersion: liveVersion,
      lastUpdated: new Date().toISOString(),
      source: 'live',
      versions: [...updatedRegistry.versions, newDef],
    };

    changes.push(`New version detected: ${liveVersion} (previously ${runtimeRegistry.latestVersion})`);
    changes.push(`Added version ${liveVersion} to registry with inherited features.`);
    changes.push(`Review Elementor changelog at https://elementor.com/changelog/ for schema changes.`);
  } else if (liveVersion) {
    changes.push(`Already up to date: ${updatedRegistry.latestVersion}`);
  } else {
    changes.push('Could not reach WordPress.org API. Registry unchanged.');
  }

  // Persist to MongoDB if available
  if (isDatabaseConnected()) {
    try {
      await VersionCacheModel.findOneAndUpdate(
        { key: 'main' },
        { key: 'main', data: updatedRegistry, updatedAt: new Date() },
        { upsert: true }
      );
      changes.push('Registry cached to MongoDB.');
    } catch {
      changes.push('Warning: could not save registry to MongoDB.');
    }
  }

  runtimeRegistry = updatedRegistry;
  return { updated: changes.some((c) => c.startsWith('New')), changes, registry: updatedRegistry };
}

// Load from MongoDB on startup if available
export async function loadCachedRegistry(): Promise<void> {
  if (!isDatabaseConnected()) return;
  try {
    const cached = await VersionCacheModel.findOne({ key: 'main' });
    if (cached?.data) {
      runtimeRegistry = { ...cached.data, source: 'cached' };
      console.log(`[Registry] Loaded cached registry (latest: ${runtimeRegistry.latestVersion})`);
    }
  } catch {
    console.warn('[Registry] Could not load cached registry from MongoDB');
  }
}
