import { Request, Response, Router } from 'express';
import crypto from 'crypto';

const router = Router();
const CONSENT_VERSION = 2;
const CONSENT_TTL_SECONDS = 180 * 24 * 60 * 60;

type ConsentPayload = {
    essential: boolean;
    preferences: boolean;
    analytics: boolean;
};

const getSecret = () => {
    return process.env.CONSENT_COOKIE_SECRET || process.env.AUTH_HASH_PEPPER || '';
};

const base64UrlEncode = (value: string) => {
    return Buffer.from(value, 'utf-8').toString('base64url');
};

const base64UrlDecode = (value: string) => {
    return Buffer.from(value, 'base64url').toString('utf-8');
};

const signValue = (payloadB64: string, secret: string) => {
    return crypto.createHmac('sha512', secret).update(payloadB64).digest('hex');
};

const isValidConsent = (consent: any): consent is ConsentPayload => {
    return (
        typeof consent === 'object' &&
        consent !== null &&
        typeof consent.essential === 'boolean' &&
        typeof consent.preferences === 'boolean' &&
        typeof consent.analytics === 'boolean'
    );
};

router.post('/sign-consent', (req: Request, res: Response): void => {
    const secret = getSecret();
    if (!secret || secret.length < 32) {
        res.status(500).json({ status: 'error', message: 'CONSENT_COOKIE_SECRET manquant ou trop court.' });
        return;
    }

    const consent = req.body?.consent;
    if (!isValidConsent(consent)) {
        res.status(400).json({ status: 'error', message: 'Consent payload invalide.' });
        return;
    }

    const now = Math.floor(Date.now() / 1000);
    const payload = {
        consent: {
            essential: true,
            preferences: Boolean(consent.preferences),
            analytics: Boolean(consent.analytics)
        },
        version: CONSENT_VERSION,
        iat: now,
        exp: now + CONSENT_TTL_SECONDS,
        nonce: crypto.randomBytes(16).toString('hex')
    };

    const payloadB64 = base64UrlEncode(JSON.stringify(payload));
    const signature = signValue(payloadB64, secret);
    const token = `${payloadB64}.${signature}`;

    res.json({
        status: 'success',
        token,
        maxAgeSeconds: CONSENT_TTL_SECONDS
    });
});

router.post('/verify-consent', (req: Request, res: Response): void => {
    const secret = getSecret();
    if (!secret || secret.length < 32) {
        res.status(500).json({ status: 'error', message: 'CONSENT_COOKIE_SECRET manquant ou trop court.' });
        return;
    }

    const token = String(req.body?.token || '');
    const [payloadB64, providedSignature] = token.split('.');
    if (!payloadB64 || !providedSignature) {
        res.json({ status: 'success', valid: false });
        return;
    }

    try {
        const expectedSignature = signValue(payloadB64, secret);

        if (
            expectedSignature.length !== providedSignature.length ||
            !crypto.timingSafeEqual(Buffer.from(expectedSignature), Buffer.from(providedSignature))
        ) {
            res.json({ status: 'success', valid: false });
            return;
        }

        const payload = JSON.parse(base64UrlDecode(payloadB64)) as {
            consent?: ConsentPayload;
            version?: number;
            exp?: number;
        };

        if (!payload || payload.version !== CONSENT_VERSION || !isValidConsent(payload.consent)) {
            res.json({ status: 'success', valid: false });
            return;
        }

        const now = Math.floor(Date.now() / 1000);
        if (!payload.exp || payload.exp <= now) {
            res.json({ status: 'success', valid: false });
            return;
        }

        res.json({
            status: 'success',
            valid: true,
            consent: payload.consent
        });
    } catch {
        res.json({ status: 'success', valid: false });
    }
});

export default router;
