import { Body, Controller, Get, NotFoundException, Param, ParseEnumPipe, ParseIntPipe, Post, StreamableFile, UploadedFile, UseInterceptors } from '@nestjs/common';
import { TilesService } from './tiles.service';
import { join } from 'path';
import { createReadStream, existsSync, mkdirSync, writeFileSync } from 'node:fs';
import axios from 'axios';
import { dirname } from 'node:path';
import { FileInterceptor } from '@nestjs/platform-express';
import { UploadDTO } from './dto/upload';

type TileProvider = 'google' | 'yandex' | 'custom'

const tileFolder = join(__dirname, '..', '..', '..', 'storage', 'tile_data')
const uploadDir = join(__dirname, '..', '..', '..', 'storage', 'temp')

@Controller('tiles')
export class TilesController {
    constructor(private readonly tileService: TilesService) { }

    @Post('/upload')
    @UseInterceptors(FileInterceptor('file', {
        dest: '../../storage/temp'
    }))
    async uploadFile(
        @UploadedFile() file: Express.Multer.File,
        @Body() body: UploadDTO
    ) {
        //await this.tileService.processUpload(file, body)
        return { message: 'Uploaded successfully', path: file.path }
    }

    @Get('/tile/:provider/:z/:x/:y')//✅
    async getTile(@Param('provider') provider: TileProvider, @Param('z', new ParseIntPipe()) z: string, @Param('x', new ParseIntPipe()) x: string, @Param('y', new ParseIntPipe()) y: string) {
        const tilePath = provider === 'custom' ? join(tileFolder, provider, z.toString(), x.toString(), `${y}.png`) : join(tileFolder, provider, z.toString(), x.toString(), `${y}.jpg`)

        if (existsSync(tilePath)) {
            const file = createReadStream(tilePath)
            return new StreamableFile(file, {
                type: 'image/jpeg',
            })
        } else {
            if (provider !== 'custom') {
                try {
                    const tileData = await this.tileService.fetchTileFromAPI(provider, z, x, y)

                    mkdirSync(dirname(tilePath), { recursive: true })

                    writeFileSync(tilePath, tileData)

                    return new StreamableFile(tileData, {
                        type: 'image/jpeg',
                    })
                } catch (error) {
                    return error
                }
            } else {
                throw new NotFoundException(`Tile is not generated or not provided`)
            }
        }
    }

    @Get('/static/:city_id')
    async getStatic(@Param('city_id', new ParseIntPipe()) city_id: number) {
        const staticFolder = join(__dirname, '..', '..', '..', 'storage', 'static')

        const tilePath1 = join(staticFolder, `${city_id}.jpg`)
        const tilePath2 = join(staticFolder, `${city_id}.png`)

        if (existsSync(tilePath1)) {
            const file = createReadStream(tilePath1)
            return new StreamableFile(file, {
                type: 'image/jpeg',
            })
        } else if (existsSync(tilePath2)) {
            const file = createReadStream(tilePath2)
            return new StreamableFile(file, {
                type: 'image/png',
            })
        } else {
            throw new NotFoundException(`Static image for city_id = ${city_id} is not provided`)
        }
    }
}