import fs from 'node:fs'
import os from 'node:os'
import path from 'node:path'

import { describe, expect, it } from 'vitest'

import {
  buildPublicRobotsTxt,
  buildPublicSearchAssetPlan,
  buildPublicSitemapXml,
  renderPublicSearchAssets,
} from './render-public-search-assets-lib.mjs'

function createRouteRegistry() {
  return [
    { path: '/', crawlable: true },
    { path: '/features', crawlable: true },
    { path: '/login', crawlable: false },
    { path: '/register', crawlable: false },
  ]
}

function createPolicy() {
  return {
    baseUrl: 'https://hypertwist.app/',
    explicitDisallowPaths: ['/app', '/api/', '/auth', '/health', '/app'],
  }
}

describe('buildPublicSearchAssetPlan', () => {
  it('derives crawlable routes and crawler disallow rules from shared inputs', () => {
    const plan = buildPublicSearchAssetPlan(createRouteRegistry(), createPolicy())

    expect(plan.baseUrl).toBe('https://hypertwist.app')
    expect(plan.crawlableRoutes.map((route) => route.path)).toEqual(['/', '/features'])
    expect(plan.crawlerDisallowPaths).toEqual([
      '/app',
      '/api/',
      '/auth',
      '/health',
      '/login',
      '/register',
    ])
  })
})

describe('buildPublicSitemapXml', () => {
  it('renders crawlable routes into sitemap XML', () => {
    const xml = buildPublicSitemapXml(createRouteRegistry(), createPolicy())

    expect(xml).toContain('<loc>https://hypertwist.app/</loc>')
    expect(xml).toContain('<loc>https://hypertwist.app/features</loc>')
    expect(xml).not.toContain('/login')
    expect(xml).not.toContain('/register')
  })
})

describe('buildPublicRobotsTxt', () => {
  it('renders the shared protected-route boundary into robots posture', () => {
    const robots = buildPublicRobotsTxt(createRouteRegistry(), createPolicy())

    expect(robots).toContain('User-agent: *')
    expect(robots).toContain('Allow: /')
    expect(robots).toContain('Disallow: /app')
    expect(robots).toContain('Disallow: /api/')
    expect(robots).toContain('Disallow: /auth')
    expect(robots).toContain('Disallow: /health')
    expect(robots).toContain('Disallow: /login')
    expect(robots).toContain('Disallow: /register')
    expect(robots).toContain('Sitemap: https://hypertwist.app/sitemap.xml')
  })
})

describe('renderPublicSearchAssets', () => {
  it('writes both sitemap and robots assets from the same authority inputs', async () => {
    const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'hypertwist-public-search-assets-'))
    const registryPath = path.join(tempRoot, 'public-route-registry.json')
    const policyPath = path.join(tempRoot, 'public-search-policy.json')
    const sitemapPath = path.join(tempRoot, 'sitemap.xml')
    const robotsPath = path.join(tempRoot, 'robots.txt')

    fs.writeFileSync(registryPath, JSON.stringify(createRouteRegistry(), null, 2))
    fs.writeFileSync(policyPath, JSON.stringify(createPolicy(), null, 2))

    const rendered = await renderPublicSearchAssets({
      registryPath,
      policyPath,
      sitemapPath,
      robotsPath,
    })

    expect(rendered.crawlableRoutes).toHaveLength(2)
    expect(rendered.crawlerDisallowPaths).toEqual([
      '/app',
      '/api/',
      '/auth',
      '/health',
      '/login',
      '/register',
    ])
    expect(fs.readFileSync(sitemapPath, 'utf8')).toContain('<loc>https://hypertwist.app/features</loc>')
    expect(fs.readFileSync(robotsPath, 'utf8')).toContain('Disallow: /health')
  })
})
