import dbConnect from "@/database/dbConnect";
import { NextResponse } from "next/server";
import incomesModel from "@/database/models/incomeModel";
import statisticsModel from "@/database/models/statisticsModel";

// POST METHOD
export async function POST(req:Request)
{
    try{
        // connect to the db
        dbConnect();
        // get the request payload
        const { payload } = await req.json();
        // get data from formData
        const name : string | null = payload.name as string | null,
        description : string | null = payload.description as string | null,
        amount : number = payload.amount ? payload.amount : 0 as number
        // save the doc
        const doc = new incomesModel({
            name,
            description,
            amount,
            addedAt: Math.floor(new Date().getTime() / 1000),
        })
        await doc.save()
        // add the income
        await statisticsModel.findOneAndUpdate({} , {
            $inc: {
                totalIncome: amount
            }
        })
        // return the success response with the new added doc
        return NextResponse.json({
            success: true,
            message: "requestTerminatedWithSuccess",
            data: doc,
        }, {
            status: 200,
            headers: {
                "content-type": "application/json"
            }
        })
    }catch(e)
    {
        // catch any error and return an error response
        return NextResponse.json({
            success: false,
            message: "serverError",
        }, {
            status: 500,
            headers: {
                "content-type": "application/json"
            }
        })
    }
}
// set the revalidate variable
export const revalidate = 5;
// GET METHOD
export async function GET(req:Request)
{
    try{
        // connect to the db
        dbConnect();
        // get the parms
        const { searchParams } = new URL(req.url)
        const type = searchParams.get('type')
        // if get by page
        if(type == 'page')
        {
            // get the page
            const page : string | null = searchParams.get('page') ? searchParams.get('page') : '0',
            range : number[] = [(parseInt(page?page : '0') - 1) * 10, 10];
            // range : number[] = [(parseInt(page?page : '0') - 1) * 10, 10];
            // get the docs (sorted by addedAt in descending order to show newest first)
            const docs = await incomesModel.find({}).sort({ addedAt: -1 }).skip(range[0]).limit(range[1]),
            // get the size of the docs
            docs_count = await incomesModel.countDocuments({});
            // prepare the return data
            return NextResponse.json({
                success: true,
                message: "docsGetedSuccessfully",
                data: {
                    docs,
                    docs_count,
                }
            })
        }
        // if type is search
        else if(type == 'search')
        {
            // get the searchKeyword param
            let searchKeyword = searchParams.get('searchKeyword')
            // get the search results docs (sorted by addedAt in descending order)
            let results = await incomesModel.find({
                $or: [
                    // search by ( case insensitive search )
                    { name: { $regex: searchKeyword, $options: 'i' } },
                    { description: { $regex: searchKeyword, $options: 'i' } }
                ]
            }).sort({ addedAt: -1 })
            // get the docs
            let responseData = {
                docs: results,
                docs_count : results.length,
            }
            // return the response
            return NextResponse.json({
                success: true,
                message: "docsGetedSuccessfully",
                data: responseData ? responseData : [],
            } , {
                status: 200,
            })
        }
    }catch(e)
    {
        // catch any error and return an error response
        return NextResponse.json({
            success: false,
            message: "serverError",
        }, {
            status: 500,
            headers: {
                "content-type": "application/json"
            }
        })
    }
}
// DELETE METHOD
export async function DELETE(req:Request)
{
    try{
        // connect to the db
        dbConnect();
        // get the parms
        const { searchParams } = new URL(req.url)
        const page = searchParams.get('page'),        
        _id : string | null = searchParams.get('_id'),
        range : number[] = [(parseInt(page?page : '0') - 1) * 10, 10];        
        // update the outcome
        // get the old amount
        let doc = await incomesModel.findById(_id)
        // remove the outcome
        await statisticsModel.findOneAndUpdate({} , {
            $inc: {
                totalIncome: doc?.amount ? -doc?.amount : 0
            }
        })
        // delete the doc
        await incomesModel.findByIdAndRemove(_id)
        // get the docs by page (sorted by addedAt in descending order)
        const docs = await incomesModel.find({}).sort({ addedAt: -1 }).skip(range[0]).limit(range[1]),
        // get the size of the docs
        docs_count = await incomesModel.countDocuments({});
        // prepare the return data
        return NextResponse.json({
            success: true,
            message: "docsGetedSuccessfully",
            data: {
                docs,
                docs_count,
            }
        })
    }catch(e)
    {
        // catch any error and return an error response
        return NextResponse.json({
            success: false,
            message: "serverError",
        }, {
            status: 500,
            headers: {
                "content-type": "application/json"
            }
        })
    }
}
// PUT METHOD
export async function PUT(req:Request)
{
    try{
        // connect to the db
        dbConnect();
        // get the request payload
        const { payload } = await req.json();
        // get data from formData
        const name : string | null = payload.name as string | null,
        description : string | null = payload.description as string | null,
        amount : number = payload.amount ? payload.amount : 0 as number,
        _id : string | null = payload._id as string | null;
        // update the income
        // get the old amount
        let doc = await incomesModel.findById(_id)
        // re deacrease the old outcome
        await statisticsModel.findOneAndUpdate({} , {
            $inc: {
                totalIncome: doc?.amount ? -doc?.amount : 0
            }
        })
        // add the new income
        await statisticsModel.findOneAndUpdate({} , {
            $inc: {
                totalIncome: amount
            }
        })
        // update the doc
        let updated_doc = await incomesModel.findByIdAndUpdate(_id , {
            name,
            description,
            amount
        }, { new: true })
        // return the success response
        return NextResponse.json({
            success: true,
            message: "requestTerminatedWithSuccess",
            data: updated_doc,
        }, {
            status: 200,
            headers: {
                "content-type": "application/json"
            }
        })
    }catch(e)
    {
        // catch any error and return an error response
        return NextResponse.json({
            success: false,
            message: "serverError",
        }, {
            status: 500,
            headers: {
                "content-type": "application/json"
            }
        })
    }
}