import {
    decorate,
    ControllerProperty,
    VaderContext,
} from '@t2ee/vader';
import Cookie from './Cookie';
import { store } from './utils';
import * as Chance from 'chance';
const chance = new Chance();

function CookieMiddleware(name: string, defaultExpire: number = 3600 * 1000) {
    return async (context: VaderContext, next) => {
        const cookieHeader = context.headers['cookie'] || '';
        let cookie: Cookie = null;
        for (const cookieString of cookieHeader.split(',').map(c => c.trim())) {
            const [key, value] = cookieString.split('=');
            if (!key || !value) continue;
            if (key === name) {
                cookie = await store().get(value);
                if (cookie && cookie.expires <= new Date()) {
                    await store().remove(cookie);
                    cookie = null;
                }
            }
        }

        if (!cookie) {
            cookie = new Cookie();
            cookie.expires = new Date(Date.now() + defaultExpire);
        }

        context['cookieman:cookie-instance'] = cookie;
        await next();
        cookie = context['cookieman:cookie-instance'];
        if (cookie && cookie.key) {
            if (cookie.expires <= new Date()) {
                await store().remove(cookie);
                return;
            }
            await store().set(cookie);
            let cookieString = `${name}=${cookie.key};Expires=${cookie.expires.toString()}`;

            if (cookie.path) {
                cookieString += `;Path=${cookie.path}`;
            }

            if (cookie.domain) {
                cookieString += `;Domain=${cookie.domain}`;
            }

            if (cookie.secure) {
                cookieString += `;Secure`;
            }

            if (cookie.httpOnly) {
                cookieString += `;HttpOnly`;
            }

            context.http.set('Set-Cookie', cookieString);
        }
    };
}

export default function InjectCookie(name: string) {
    return decorate((property: ControllerProperty) => {
        return (target, key: string) => {
            property.WARES.push(CookieMiddleware(name));
            property.PARAMS.push({
                key,
                paramType: 'cookieman:inject-cookie',
            });
        };
    });
}
