const test = require('node:test')
const assert = require('node:assert/strict')
const {
  parseBlogCsv,
  parseTagsField,
  csvRowToContentBody,
  csvRowToPageBody,
  htmlCodeFromCsvRow,
  omitUndefined,
  validateBlogCsvColumns,
  resolveImagePathRelativeToCsv,
  normalizeContentSlug,
  isValidContentSlug,
  BLOG_CSV_COLUMNS,
  parsePublishedAtMs,
  mergePageScheduleWithPublishedAt,
} = require('../src/lib/blog-csv')

test('parseTagsField: comma-separated', () => {
  assert.deepEqual(parseTagsField('a, b, c'), ['a', 'b', 'c'])
})

test('parseTagsField: JSON array', () => {
  assert.deepEqual(parseTagsField('["x","y"]'), ['x', 'y'])
})

test('parseTagsField: empty', () => {
  assert.deepEqual(parseTagsField(''), [])
  assert.deepEqual(parseTagsField(null), [])
})

test('validateBlogCsvColumns', () => {
  const row = {}
  for (const c of BLOG_CSV_COLUMNS) row[c] = ''
  assert.equal(validateBlogCsvColumns(row).ok, true)
  assert.equal(validateBlogCsvColumns({ slug: 'x' }).ok, false)
})

test('parseBlogCsv: quoted multiline content', () => {
  const csv =
    'slug,title,published_at,excerpt,content,category,tags,author,image,meta_title,meta_description\n' +
    'a,A,,,"line1\nline2",cat,"tag1,tag2",me,,mTitle,mDesc\n'
  const rows = parseBlogCsv(csv)
  assert.equal(rows.length, 1)
  assert.equal(rows[0].slug, 'a')
  assert.match(rows[0].content, /line1\nline2/)
  assert.deepEqual(parseTagsField(rows[0].tags), ['tag1', 'tag2'])
})

test('parseBlogCsv: HTML with commas inside quoted field', () => {
  const csv =
    'slug,title,published_at,excerpt,content,category,tags,author,image,meta_title,meta_description\n' +
    'p,T,,,"<p>a,b</p><div>x</div>",,,,,,\n'
  const rows = parseBlogCsv(csv)
  assert.equal(rows.length, 1)
  assert.equal(rows[0].content, '<p>a,b</p><div>x</div>')
})

test('normalizeContentSlug and validation', () => {
  assert.equal(normalizeContentSlug('Foo_Bar! '), 'foo-bar')
  assert.equal(isValidContentSlug('my-post'), true)
  assert.equal(isValidContentSlug('-bad'), false)
})

test('htmlCodeFromCsvRow preserves markup', () => {
  assert.equal(htmlCodeFromCsvRow({ content: '<article>\n<p>Hi</p>\n</article>' }), '<article>\n<p>Hi</p>\n</article>')
})

test('csvRowToContentBody: code is raw HTML not JSON', () => {
  const row = {
    slug: 'my-post',
    title: 'T',
    published_at: '2025-01-02',
    excerpt: 'ex',
    content: '<main><h1>Hi</h1></main>',
    category: 'cat',
    tags: 'a,b',
    author: 'me',
    image: '',
    meta_title: 'mt',
    meta_description: 'md',
  }
  const p = csvRowToContentBody(row, { devices: ['web'], forceDraft: false })
  assert.equal(p.name, 'T')
  assert.equal(p.slug, 'my-post')
  assert.deepEqual(p.devices, ['web'])
  assert.equal(p.code, '<main><h1>Hi</h1></main>')
  assert.equal(p.category, undefined)
  assert.equal(p.status, 'published')
  assert.ok(p.schedule && typeof p.schedule.startDate === 'number')
  assert.throws(() => JSON.parse(String(p.code)), /Unexpected token/)
})

test('csvRowToContentBody draft', () => {
  const row = {
    slug: 'x',
    title: 'Y',
    published_at: '',
    excerpt: '',
    content: '',
    category: '',
    tags: '',
    author: '',
    image: '',
    meta_title: '',
    meta_description: '',
  }
  const p = csvRowToContentBody(row, { devices: ['web'], forceDraft: true })
  assert.equal(p.status, 'draft')
  assert.equal(p.code, '')
})

test('csvRowToPageBody links contentId and metaTags', () => {
  const row = {
    slug: 'content-slug',
    page_slug: 'url-path',
    title: 'Page title',
    published_at: '2025-06-01',
    excerpt: 'Short',
    content: '<p>x</p>',
    category: '',
    tags: 'kw1, kw2',
    author: '',
    image: 'https://cdn.example.com/o.jpg',
    meta_title: 'SEO title',
    meta_description: 'SEO desc',
  }
  const p = csvRowToPageBody(row, { contentId: 'cid-1', forceDraft: false })
  assert.equal(p.slug, 'url-path')
  assert.equal(p.name, 'Page title')
  assert.equal(p.contentId, 'cid-1')
  assert.equal(p.published, true)
  assert.ok(p.schedule)
  assert.equal(p.previewDescription, 'Short')
  assert.ok(p.metaTags)
  assert.equal(p.metaTags.title, 'SEO title')
  assert.equal(p.metaTags.keywords, 'kw1, kw2')
  assert.equal(p.metaTags.ogImage, 'https://cdn.example.com/o.jpg')
})

test('csvRowToPageBody defaults page slug to content slug', () => {
  const row = {
    slug: 'same-slug',
    title: 'T',
    published_at: '',
    excerpt: '',
    content: '',
    category: '',
    tags: '',
    author: '',
    image: '',
    meta_title: '',
    meta_description: '',
  }
  const p = csvRowToPageBody(row, { contentId: 'c', forceDraft: true })
  assert.equal(p.slug, 'same-slug')
  assert.equal(p.published, false)
})

test('omitUndefined', () => {
  assert.deepEqual(omitUndefined({ a: 1, b: undefined }), { a: 1 })
})

test('parsePublishedAtMs', () => {
  assert.equal(parsePublishedAtMs('2025-06-01'), Date.parse('2025-06-01'))
  assert.throws(() => parsePublishedAtMs(''), /empty/)
  assert.throws(() => parsePublishedAtMs('not-a-date'), /Invalid/)
})

test('mergePageScheduleWithPublishedAt keeps extra keys', () => {
  const prev = { persistent: false, custom: 1 }
  const m = mergePageScheduleWithPublishedAt(prev, '2024-12-15T12:00:00Z')
  assert.equal(m.custom, 1)
  assert.equal(m.persistent, true)
  assert.equal(typeof m.startDate, 'number')
  assert.equal(m.startDate, Date.parse('2024-12-15T12:00:00Z'))
})

test('resolveImagePathRelativeToCsv', () => {
  const csvPath = '/project/data/posts.csv'
  assert.equal(resolveImagePathRelativeToCsv(csvPath, 'https://x/y.jpg'), 'https://x/y.jpg')
  assert.ok(resolveImagePathRelativeToCsv(csvPath, './img/a.jpg').endsWith(`${require('path').join('data', 'img', 'a.jpg')}`))
})
