import express, { Request, Response } from 'express';
import { tediousQuery } from '../../utils/tedious';
import { GeneralDB, GisDB } from '../../constants/db';
const router = express.Router()

// ✅
router.get('/regions/all', async (req: Request, res: Response) => {
    try {
        const result = await tediousQuery(
            `
            SELECT * FROM ${GeneralDB}..vRegions;
            `
        )
        res.status(200).json(result)
    } catch (err) {
        res.status(500)
    }
})

// ✅
router.get('/districts/all', async (req: Request, res: Response) => {
    try {
        const { region_id } = req.query

        const result = await tediousQuery(
            `
            SELECT c.*, d.name AS district_name
            FROM ${GeneralDB}..vCities c
            JOIN ${GeneralDB}..vDistricts d ON d.id_region = c.id_region AND d.id = c.id_district
            WHERE c.id_region = ${region_id};
            `
        )
        res.status(200).json(result)
    } catch (err) {
        res.status(500)
    }
})

// ✅
router.get('/cities/all', async (req: Request, res: Response) => {
    try {
        const { offset, limit, search, id } = req.query

        const result = await tediousQuery(
            `
            SELECT * FROM ${GeneralDB}..Cities
            ${id ? `WHERE id = '${id}'` : ''}
            ${search ? `WHERE name LIKE '%${search || ''}%'` : ''}
            ORDER BY id 
            OFFSET ${Number(offset) || 0} ROWS 
            FETCH NEXT ${Number(limit) || 10} ROWS ONLY;
            `
        )
        res.status(200).json(result)
    } catch (err) {
        res.status(500)
    }
})

// ✅
router.get('/types/all', async (req: Request, res: Response) => {
    try {
        const result = await tediousQuery(
            `
            SELECT * FROM ${GeneralDB}..tTypes
            ORDER BY id
            `
        )
        res.status(200).json(result)
    } catch (err) {
        res.status(500)
    }
})

// ✅
router.get('/objects/all', async (req: Request, res: Response) => {
    try {
        const { offset, limit, city_id } = req.query

        const result = await tediousQuery(
            `
            SELECT * FROM ${GeneralDB}..vObjects
            ${city_id ? `WHERE id_city = ${city_id}` : ''}
            ORDER BY object_id
            OFFSET ${Number(offset) || 0} ROWS
            FETCH NEXT ${Number(limit) || 10} ROWS ONLY;
            `
        )
        res.status(200).json(result)
    } catch (err) {
        res.status(500)
    }
})

// ✅
router.get('/objects/list', async (req: Request, res: Response) => {
    try {
        const { city_id, year, planning, type } = req.query

        if (type) {
            const result = await tediousQuery(
                `
                WITH cte_split(type_id, split_value, caption_params) AS
                (
                -- anchor member
                SELECT DISTINCT
                    type_id,
                    CAST(LEFT(caption_params, CHARINDEX(',', caption_params + ',') - 1) AS VARCHAR(255)),  -- Explicitly casting to VARCHAR
                    STUFF(caption_params, 1, CHARINDEX(',', caption_params + ','), '')
                FROM ${GisDB}..caption_params
                WHERE city_id = -1 AND user_id = -1
                
                UNION ALL
                
                -- recursive member
                SELECT
                    type_id,
                    CAST(LEFT(caption_params, CHARINDEX(',', caption_params + ',') - 1) AS VARCHAR(255)),  -- Explicitly casting to VARCHAR
                    STUFF(caption_params, 1, CHARINDEX(',', caption_params + ','), '')
                FROM cte_split
                WHERE caption_params > ''
                )
                SELECT
                    o.object_id,
                o.type,
                o.id_city,
                o.year,
                o.planning,
                string_agg(cast(v.value as varchar), ',') as caption
                FROM ${GeneralDB}..vObjects o
                JOIN cte_split c ON o.type = c.type_id
                JOIN ${GeneralDB}..tParameters p ON p.id = split_value
                LEFT JOIN ${GeneralDB}..tValues v
                ON 
                    v.id_param = split_value 
                    AND v.id_object = o.object_id 
                    AND (v.date_po IS NULL)
                AND (v.date_s < DATEFROMPARTS(${Number(year) + 1},01,01))

                WHERE
                    o.id_city = ${city_id}
                    AND o.year = ${year}
                    AND o.type = ${type}
                    AND
                    (
                    CASE
                        WHEN TRY_CAST(o.planning AS BIT) IS NOT NULL THEN TRY_CAST(o.planning AS BIT)
                        WHEN o.planning = 'TRUE' THEN 1
                        WHEN o.planning = 'FALSE' THEN 0
                        ELSE NULL
                    END
                    ) = ${planning}
                GROUP BY object_id, type, id_city, year, planning;
                `
            )
            res.status(200).json(result)
        } else {
            const result = await tediousQuery(
                `
                SELECT 
                    ${GeneralDB}..tTypes.id AS id,
                    ${GeneralDB}..tTypes.name AS name,
                    COUNT(vo.type) AS count,
                    tr.r,
                    tr.g,
                    tr.b
                FROM 
                    ${GeneralDB}..vObjects vo
                JOIN
                    ${GeneralDB}..tTypes ON vo.type = ${GeneralDB}..tTypes.id
                LEFT JOIN ${GisDB}..TypeRoles tr ON tr.id = ${GeneralDB}..tTypes.id
                WHERE 
                    vo.id_city = ${city_id} AND vo.year = ${year}
                    AND
                    (
                    CASE 
                        WHEN TRY_CAST(vo.planning AS BIT) IS NOT NULL THEN TRY_CAST(vo.planning AS BIT)
                        WHEN vo.planning = 'TRUE' THEN 1
                        WHEN vo.planning = 'FALSE' THEN 0
                        ELSE NULL
                    END
                    ) = ${planning}
                GROUP BY 
                    ${GeneralDB}..tTypes.id,
                    ${GeneralDB}..tTypes.name,
                    tr.r,
                    tr.g,
                    tr.b;
                `
            )
            res.status(200).json(result)
        }
    } catch (err) {
        res.status(500)
    }
})

router.get('/objects/:id([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})', async (req: Request, res: Response) => {
    try {
        const { id } = req.params;

        const result = await tediousQuery(
            `
            SELECT * FROM ${GeneralDB}..vObjects
            ${id ? `WHERE object_id = '${id}'` : ''}
            `
        )
        if (Array.isArray(result) && result.length > 0) {
            res.status(200).json(result[0])
        }
    } catch (err) {
        res.status(500)
    }
})

// ✅
router.get('/values/all', async (req: Request, res: Response) => {
    try {
        const { object_id } = req.query

        if (!object_id) {
            res.status(500)
        }

        const result = await tediousQuery(
            `
            SELECT
                id_object,
                id_param,
                CAST(v.value AS varchar(max)) AS value,
                date_s,
                date_po,
                id_user
            FROM 
                ${GeneralDB}..tValues v
            JOIN
                ${GeneralDB}..tParameters p ON v.id_param = p.id
            WHERE id_object = '${object_id}'
            `
        )

        res.status(200).json(result)
    } catch (err) {
        res.status(500)
    }
})

// ✅
router.get('/params/all', async (req: Request, res: Response) => {
    try {
        const { param_id } = req.query

        if (!param_id) {
            res.status(500)
        }

        const result = await tediousQuery(
            `
            SELECT * FROM ${GeneralDB}..tParameters
            WHERE id = '${param_id}'
            `
        )

        res.status(200).json(result)
    } catch (err) {
        res.status(500)
    }
})

const tcbParamQuery = (vtable: string, id_city: string) => {
    switch (vtable) {
        case 'vStreets':
            return `SELECT * FROM ${GeneralDB}..${vtable} WHERE id_city = ${id_city};`
        case 'vBoilers':
            return `SELECT * FROM ${GeneralDB}..${vtable} WHERE id_city = ${id_city};`
        default:
            return `SELECT * FROM ${GeneralDB}..${vtable};`
    }
}

// ✅
// Get value from TCB parameter
router.get('/params/tcb', async (req: Request, res: Response) => {
    try {
        const { vtable, id, offset, limit, id_city } = req.query

        if (!vtable) {
            res.status(500)
        }

        if (id) {
            const result = await tediousQuery(
                `
                SELECT * FROM ${GeneralDB}..${vtable}
                WHERE id = '${id}'
                `
            )
            res.status(200).json(result)
        } else {
            const result = await tediousQuery(
                // `
                // SELECT * FROM nGeneral..${vtable}
                // ORDER BY id
                // OFFSET ${Number(offset) || 0} ROWS
                // FETCH NEXT ${Number(limit) || 10} ROWS ONLY;
                // `
                tcbParamQuery(vtable as string, id_city as string)
            )
            res.status(200).json(result)
        }
    } catch (err) {
        res.status(500)
    }
})

// ✅
router.get('/search/objects', async (req: Request, res: Response) => {
    try {
        const { q, id_city, year } = req.query

        if (q && id_city && year) {
            const result = await tediousQuery(
                `
                WITH RankedValues AS (
                    SELECT
                        id_object,
                        date_s,
                        CAST(value AS varchar(max)) AS value,
                        ROW_NUMBER() OVER (PARTITION BY id_object ORDER BY date_s DESC) AS rn,
                        o.id_city AS id_city,
                        o.year AS year
                    FROM ${GeneralDB}..tValues
                    JOIN ${GeneralDB}..tObjects o ON o.id = id_object
                    WHERE CAST(value AS varchar(max)) LIKE '%${q}%'
                    )
                SELECT
                    id_object,
                    date_s,
                    value,
                    id_city,
                    year
                FROM RankedValues
                WHERE rn = 1 AND id_city = ${id_city} AND year = ${year};
                `
            )

            res.status(200).json(result)
        } else {
            res.status(400).json("Bad request")
        }

    } catch (err) {
        res.status(500).json({
            message: "Error",
            error: err
        })
    }
})

export default router