import Sphericalmercator from '@mapbox/sphericalmercator';

import { config, logger, pgClients } from '@opengis/fastify-table/utils.js';

import mapnik from '../../../plugins/mapnik/funcs/mapnik.js';

const { RenderTile } = mapnik();

const mercator = new Sphericalmercator({ size: 256 });

/**
 * Формування растрового tile cartoCss
 *
 * @method GET
 * @alias rtile
 * @param {String} bbox - bbox
 * @param {Number} height - висота по координатам
 * @param {Number} width - ширина по координатам
 * @param {String} data - стилізація
 * @param {String} lang - мова
 * @param {String} z - координата z
 * @param {String} x - координата y
 * @param {String} y - координата x
 */

export default async function rtile({
    pg = pgClients.client, params, query,
}, reply) {
    if (!RenderTile) {
        return reply.status(400).send({ error: 'mapnik server address needed', code: 400 });
    }

    const { id, z, y } = params;

    const x = params.x.split('.')[0] - 0;

    if (!id) {
        return reply.status(400).send({ error: 'not enough params: id', code: 400 });
    }

    if (!x || !y || !z) {
        return reply.status(400).send({ error: 'not enough params: xyz', code: 400 });
    }

    const raster = pg.pk?.['gis.rasters']
        ? await pg.query('select raster_id, source_path from gis.rasters where raster_id=$1::text', [id])
            .then(el => el.rows?.[0] || {})
        : {};

    // const relpath = raster ? `/map/raster/${raster.source_path}` : null;

    const cartoExists = pg.pk?.['gis.cartocss']
        ? await pg.query('select cartocss_id from gis.cartocss where cartocss_id=$1::text', [id])
            .then(el => el.rows?.[0]?.cartocss_id)
        : null;

    if (!raster.raster_id && !cartoExists) {
        const decodedPath = Buffer.from(id, 'base64url').toString('utf-8');
        Object.assign(raster, { source_path: decodedPath });
    }

    if (!raster.source_path && !cartoExists) {
        return reply.status(404).send({ error: 'raster / cartocss not found', code: 404 });
    }

    const bbox = mercator.bbox(y, x, z, false, '900913');

    try {
        const data = await RenderTile({
            path: cartoExists ? null : raster.source_path, // for rasters only
            name: id, // required for cartocss
            width: 256,
            height: 256,
            bbox,
            ttl: query.nocache ? '0' : '1h',
            debug: query.debug,
        });

        if (query.debug) {
            return { ...data, base64_path: Buffer.from(raster.source_path).toString('base64url') };
        }

        if (data.err) {
            logger.file('rtile/error', { error: data.err });
            return reply.status(500).send({ error: config.local ? data.err : 'render error', code: 500 });
        }

        const buffer = Buffer.from(data.base64, 'base64');

        return reply.headers({ 'Content-Type': 'image/png', 'Cache-Control': query.nocache ? 'no-cache' : '30d' }).send(buffer);
    }
    catch (err) {
        logger.file('rtile/error', { error: err.toString(), stack: err.stack });
        return reply.status(500).send({ error: config.local ? err.toString() : 'rtile error', code: 500 });
    }
}
