import express, { Request, Response } from 'express'
import { Redis } from 'ioredis'
import dotenv from 'dotenv'
import bodyParser from 'body-parser'
import { SatelliteMapsProvider } from './interfaces/map'
const axios = require('axios');

const cors = require('cors')

const redis = new Redis({
    port: Number(process.env.REDIS_PORT) || 6379,
    host: process.env.REDIS_HOST,
    password: process.env.REDIS_PASSWORD,
})

dotenv.config()

const app = express()
const port = process.env.EMS_PORT

// Middleware to parse JSON requests
app.use(bodyParser.json())

const getTileUrl = (provider: string, x: string, y: string, z: string) => {
    if (provider === 'google') {
        return `https://khms2.google.com/kh/v=984?x=${x}&y=${y}&z=${z}`;
    } else if (provider === 'yandex') {
        return `https://core-sat.maps.yandex.net/tiles?l=sat&x=${x}&y=${y}&z=${z}&scale=1&lang=ru_RU`;
    }
    throw new Error('Invalid provider');
}

app.get('/tile/:provider/:z/:x/:y', async (req, res) => {
    const { provider, x, y, z } = req.params;
    const cacheKey = `${provider}:${z}:${x}:${y}`;

    try {
        // Check if tile is in cache
        redis.get(cacheKey, async (err, cachedTile) => {
            if (err) {
                console.error('Redis GET error:', err);
                return res.status(500).send('Server error');
            }

            if (cachedTile) {
                // If cached, return tile
                console.log('Tile served from cache');
                const imgBuffer = Buffer.from(cachedTile, 'base64');
                res.writeHead(200, {
                    'Content-Type': 'image/png',
                    'Content-Length': imgBuffer.length,
                });
                return res.end(imgBuffer);
            } else {
                // Fetch tile from provider
                const tileUrl = getTileUrl(provider, x, y, z);
                const response = await axios.get(tileUrl, {
                    responseType: 'arraybuffer',
                });

                // Cache the tile in Redis
                const base64Tile = Buffer.from(response.data).toString('base64');
                redis.setex(cacheKey, 3600 * 24 * 30, base64Tile); // Cache for 1 hour

                // Return the tile to the client
                res.writeHead(200, {
                    'Content-Type': 'image/png',
                    'Content-Length': response.data.length,
                });
                return res.end(response.data);
            }
        });
    } catch (error) {
        console.error('Error fetching tile:', error);
        res.status(500).send('Error fetching tile');
    }
})

app.get('/hello', cors(), (req: Request, res: Response) => {
    res.send('Hello, World!')
})

// Route to store GeoJSON data
app.post('/geojson', cors(), async (req: Request, res: Response) => {
    const geoJSON = req.body

    if (!geoJSON || !geoJSON.features) {
        return res.status(400).send('Invalid GeoJSON')
    }

    const id = `geojson:${Date.now()}`;
    redis.set(id, JSON.stringify(geoJSON), (err, reply) => {
        if (err) {
            return res.status(500).send('Error saving GeoJSON to Redis');
        }
        res.send({ status: 'success', id });
    })
})

// Route to fetch GeoJSON data
app.get('/geojson/:id', cors(), async (req: Request, res: Response) => {
    const id = req.params.id;

    redis.get(id, (err, data) => {
        if (err) {
            return res.status(500).send('Error fetching GeoJSON from Redis');
        }

        if (data) {
            res.send(JSON.parse(data));
        } else {
            res.status(404).send('GeoJSON not found');
        }
    })
})

app.listen(port, () => {
    console.log(`Server running on http://localhost:${port}`);
})
