import Database from 'better-sqlite3';
import { existsSync, mkdirSync } from 'node:fs';
import path from 'node:path';
import fallbackCms from '../../data/cms.json';
import { derivePublishedAt } from './date';

export type PostStatus = 'approved' | 'pending';

export type Post = {
  slug: string;
  title: string;
  category: string;
  time: string;
  readTime: string;
  excerpt: string;
  body: string[];
  status: PostStatus;
  image?: string;
  thumbnail?: string;
  urgent?: boolean;
  sidebar?: boolean;
  sourceUrl?: string;
  publishedAt?: string;
};

export type LinkItem = {
  label: string;
  href: string;
};

export type StaticPage = {
  slug: string;
  title: string;
  description: string;
  navLabel?: string;
  footerLabel?: string;
  body: string[];
};

export type CmsData = {
  settings: {
    siteInfo: {
      name: string;
      tagline: string;
      description: string;
      copyright: string;
    };
    breakingNews: {
      label: string;
      href: string;
      items: string[];
      postSlugs?: string[];
    };
    hotTopics: string[];
    homeLayout: {
      featuredSlug: string;
      sideFeaturedSlugs: string[];
      latestCount: number;
      showAd: boolean;
    };
    ad: {
      enabled: boolean;
      label: string;
      href: string;
      text: string;
    };
    agents?: {
      tass?: {
        processedLinks: string[];
      };
    };
  };
  categories: string[];
  posts: Post[];
};

const dbPath = path.join(process.cwd(), 'data', 'cms.db');
const CMS_KEY = 'cms';

let dbInstance: Database.Database | null = null;

const getDb = (): Database.Database => {
  if (dbInstance) {
    return dbInstance;
  }

  const directory = path.dirname(dbPath);

  if (!existsSync(directory)) {
    mkdirSync(directory, { recursive: true });
  }

  const db = new Database(dbPath);
  db.pragma('journal_mode = WAL');
  db.exec(`
    CREATE TABLE IF NOT EXISTS cms (
      key TEXT PRIMARY KEY,
      value TEXT NOT NULL,
      updated_at INTEGER NOT NULL
    )
  `);

  dbInstance = db;
  return db;
};

// One-time import of the existing JSON document into SQLite on first run.
const seedIfEmpty = (db: Database.Database): void => {
  const existing = db.prepare('SELECT value FROM cms WHERE key = ?').get(CMS_KEY) as
    | { value: string }
    | undefined;

  if (existing) {
    return;
  }

  db.prepare('INSERT INTO cms (key, value, updated_at) VALUES (?, ?, ?)').run(
    CMS_KEY,
    JSON.stringify(fallbackCms),
    Date.now(),
  );
};

export const staticPages: StaticPage[] = [
  {
    slug: 'about',
    title: 'درباره ما',
    description: 'آشنایی با مأموریت، رویکرد خبری و تیم تحریریه روس امروز',
    body: [
      'روس امروز رسانه‌ای تخصصی برای پوشش خبرها، گزارش‌ها و تحلیل‌های مرتبط با روسیه، اوراسیا و روابط منطقه‌ای است.',
      'هدف ما ارائه روایت دقیق، سریع و قابل اتکا از روندهای سیاسی، اقتصادی، انرژی و فناوری در این حوزه جغرافیایی است.',
      'تحریریه روس امروز تلاش می‌کند با زبان روشن و تحلیل داده‌محور، تصویر کامل‌تری از تحولات منطقه ارائه دهد.',
    ],
  },
  {
    slug: 'contact',
    title: 'ارتباط با ما',
    description: 'راه‌های ارتباط با تحریریه و واحد بازرگانی روس امروز',
    body: [
      'برای ارسال خبر، پیشنهاد همکاری یا پیگیری موضوعات رسانه‌ای می‌توانید از طریق ایمیل info@ruseemrooz.ir با ما در تماس باشید.',
      'پیام‌های مرتبط با آگهی و همکاری تجاری توسط واحد بازرگانی بررسی و در کوتاه‌ترین زمان پاسخ داده می‌شود.',
    ],
  },
  {
    slug: 'editorial-team',
    title: 'تیم تحریریه',
    description: 'معرفی ساختار تحریریه و حوزه‌های تخصصی روس امروز',
    footerLabel: 'تیم تحریریه',
    body: [
      'تیم تحریریه روس امروز از نویسندگان و تحلیلگرانی تشکیل شده که حوزه‌های روسیه، قفقاز، آسیای مرکزی، انرژی و اقتصاد منطقه‌ای را دنبال می‌کنند.',
      'مطالب منتشرشده پس از بررسی محتوایی و ویرایشی در سایت قرار می‌گیرند تا دقت و خوانایی حفظ شود.',
    ],
  },
  {
    slug: 'advertise',
    title: 'آگهی در سایت',
    description: 'فرصت‌های تبلیغاتی و همکاری رسانه‌ای با روس امروز',
    body: [
      'روس امروز امکان انتشار آگهی، رپورتاژ و کمپین‌های هدفمند برای مخاطبان علاقه‌مند به روسیه و اوراسیا را فراهم می‌کند.',
      'برای دریافت تعرفه و پیشنهاد رسانه‌ای اختصاصی، با واحد بازرگانی سایت تماس بگیرید.',
    ],
  },
  {
    slug: 'privacy',
    title: 'حریم خصوصی',
    description: 'سیاست حفظ حریم خصوصی کاربران روس امروز',
    body: [
      'روس امروز اطلاعات کاربران را تنها برای بهبود تجربه کاربری، ارسال خبرنامه و تحلیل عملکرد سایت استفاده می‌کند.',
      'اطلاعات تماس کاربران بدون رضایت آن‌ها در اختیار اشخاص ثالث قرار نمی‌گیرد.',
    ],
  },
];

export const readCms = async (): Promise<CmsData> => {
  try {
    const db = getDb();
    seedIfEmpty(db);
    const row = db.prepare('SELECT value FROM cms WHERE key = ?').get(CMS_KEY) as
      | { value: string }
      | undefined;
    const data = row ? (JSON.parse(row.value) as CmsData) : (fallbackCms as CmsData);

    return normalizeCms(data);
  } catch {
    return normalizeCms(fallbackCms as CmsData);
  }
};

export const writeCms = async (data: CmsData) => {
  const db = getDb();
  const json = JSON.stringify(normalizeCms(data));

  db.prepare(
    `INSERT INTO cms (key, value, updated_at) VALUES (?, ?, ?)
     ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at`,
  ).run(CMS_KEY, json, Date.now());
};

const normalizeCms = (data: CmsData): CmsData => ({
  ...data,
  settings: {
    ...data.settings,
    breakingNews: {
      ...data.settings.breakingNews,
      postSlugs: data.settings.breakingNews.postSlugs ?? [],
    },
    agents: {
      ...data.settings.agents,
      tass: {
        processedLinks: data.settings.agents?.tass?.processedLinks ?? [],
      },
    },
  },
  posts: data.posts.map((post) => ({
    ...post,
    status: post.status ?? 'pending',
    body: Array.isArray(post.body) ? post.body : [],
    urgent: post.urgent ?? false,
    sidebar: post.sidebar ?? false,
    publishedAt: post.publishedAt ?? derivePublishedAt(post),
  })),
});

export const getApprovedPosts = (data: CmsData) => data.posts.filter((post) => post.status === 'approved');

export const getCategoryPath = (category: string) => `/categories/${encodeURIComponent(category)}/`;

export const getStaticPageBySlug = (slug: string) => staticPages.find((page) => page.slug === slug);

export const getPrimaryNav = () => [
  { label: 'صفحه اصلی', href: '/' },
  ...staticPages
    .filter((page) => ['about', 'contact'].includes(page.slug))
    .map((page) => ({ label: page.navLabel ?? page.title, href: `/${page.slug}/` })),
];

export const getFooterPageLinks = () => staticPages.map((page) => ({
  label: page.footerLabel ?? page.navLabel ?? page.title,
  href: `/${page.slug}/`,
}));

export const getPostBySlug = (posts: Post[], slug: string) => posts.find((post) => post.slug === slug);

export const getPostsByCategory = (posts: Post[], category: string) => posts.filter((post) => post.category === category);

export const getPaginatedPosts = (page: number, perPage: number, source: Post[]) => {
  const totalPages = Math.max(1, Math.ceil(source.length / perPage));
  const currentPage = Math.min(Math.max(Math.floor(page), 1), totalPages);
  const start = (currentPage - 1) * perPage;

  return {
    currentPage,
    totalPages,
    posts: source.slice(start, start + perPage),
  };
};

export const searchPosts = (posts: Post[], query: string) => {
  const normalizedQuery = query.trim().toLocaleLowerCase('fa-IR');

  if (!normalizedQuery) {
    return [];
  }

  return posts.filter((post) => {
    const searchableText = [
      post.title,
      post.category,
      post.excerpt,
      ...post.body,
    ].join(' ').toLocaleLowerCase('fa-IR');

    return searchableText.includes(normalizedQuery);
  });
};

export const slugify = (value: string) => value
  .trim()
  .toLowerCase()
  .replace(/[^\p{L}\p{N}]+/gu, '-')
  .replace(/^-+|-+$/g, '');

export const parseImageBlock = (value: string) => {
  const match = value.match(/^\[image:(.+?)(?:\|(.*))?\]$/);

  if (!match) {
    return null;
  }

  return {
    src: match[1].trim(),
    caption: match[2]?.trim() ?? '',
  };
};
