import { Command } from '@cliffy/command'
import { ensureDir } from '@std/fs'
import { join } from '@std/path'
import {
  CONFIG_WORLD_JSON,
  PBF_DIR,
  PROCESS_WORLD_LUA,
  TILES_OUT_DIR,
} from '../shared/paths.ts'
import { run } from '../shared/run.ts'

const PLANET_PBF = join(PBF_DIR, 'planet-latest.osm.pbf')
const PLANET_TRIMMED_PBF = join(PBF_DIR, 'planet-trimmed.osm.pbf')

export const buildWorldCmd = new Command()
  .name('build:world')
  .description(
    'Build a world overview .pmtiles from planet-latest.osm.pbf. ' +
      'Output: www/static/tiles/world_z<maxzoom>.pmtiles',
  )
  .option('--maxzoom <zoom:number>', 'Maximum zoom level (5, 7, or 9).', {
    default: 7,
  })
  .action(async ({ maxzoom }) => {
    const hasTrimmed = !!(await Deno.stat(PLANET_TRIMMED_PBF).catch(() => null))
    const hasPlanet = !!(await Deno.stat(PLANET_PBF).catch(() => null))

    if (!hasTrimmed && !hasPlanet) {
      throw new Error(
        `Planet PBF not found: ${PLANET_PBF}\n` +
          `Run 'deno task data trim:world' first to create a trimmed copy, or place the full planet file at that path.`,
      )
    }

    const inputPbf = hasTrimmed ? PLANET_TRIMMED_PBF : PLANET_PBF
    if (hasTrimmed) {
      console.log(`Using trimmed planet file: ${PLANET_TRIMMED_PBF}`)
    } else {
      console.log(
        `No trimmed file found — using full planet: ${PLANET_PBF}\n` +
          `Tip: run 'deno task data trim:world' first to reduce memory usage.`,
      )
    }

    await ensureDir(join(TILES_OUT_DIR, 'world'))
    const outPath = join(TILES_OUT_DIR, 'world', `world_z${maxzoom}.pmtiles`)

    // Patch maxzoom/basezoom into a temp config so one config file covers all tiers.
    const base = JSON.parse(await Deno.readTextFile(CONFIG_WORLD_JSON))
    base.settings.maxzoom = maxzoom
    base.settings.basezoom = maxzoom
    base.settings.combine_below = maxzoom
    for (const layer of Object.values(base.layers) as { maxzoom?: number }[]) {
      if (layer.maxzoom !== undefined) {
        layer.maxzoom = Math.min(layer.maxzoom, maxzoom)
      }
    }
    const tmpConfig = `${CONFIG_WORLD_JSON}.tmp`
    await Deno.writeTextFile(tmpConfig, JSON.stringify(base, null, 2))

    console.log(`Building world tiles z0–${maxzoom} ...`)

    try {
      await run('tilemaker', [
        '--input',
        inputPbf,
        '--output',
        outPath,
        '--config',
        tmpConfig,
        '--process',
        PROCESS_WORLD_LUA,
      ])
    } finally {
      await Deno.remove(tmpConfig).catch(() => {})
    }

    const { size } = await Deno.stat(outPath)
    const sizeStr = size < 1024 ** 3
      ? `${Math.round(size / 1024 ** 2)} MB`
      : `${(size / 1024 ** 3).toFixed(1)} GB`
    console.log(`Saved: ${outPath} (${sizeStr})`)
  })
