// src/routes/resources/history.ts
import { FastifyInstance } from "fastify";
import { and, asc, eq, inArray } from "drizzle-orm";
import { authProfiles, historyitems } from "../../db/schema";

const columnMap: Record<string, any> = {
    customers: historyitems.customer,
    contracts: historyitems.contract,
    members: historyitems.customer,
    vendors: historyitems.vendor,
    projects: historyitems.project,
    plants: historyitems.plant,
    contacts: historyitems.contact,
    tasks: historyitems.task,
    vehicles: historyitems.vehicle,
    events: historyitems.event,
    files: historyitems.file,
    products: historyitems.product,
    inventoryitems: historyitems.inventoryitem,
    inventoryitemgroups: historyitems.inventoryitemgroup,
    checks: historyitems.check,
    costcentres: historyitems.costcentre,
    ownaccounts: historyitems.ownaccount,
    documentboxes: historyitems.documentbox,
    hourrates: historyitems.hourrate,
    services: historyitems.service,
    customerspaces: historyitems.customerspace,
    customerinventoryitems: historyitems.customerinventoryitem,
    memberrelations: historyitems.memberrelation,
    outgoingsepamandates: historyitems.outgoingsepamandate,
};

const insertFieldMap: Record<string, string> = {
    customers: "customer",
    contracts: "contract",
    members: "customer",
    vendors: "vendor",
    projects: "project",
    plants: "plant",
    contacts: "contact",
    tasks: "task",
    vehicles: "vehicle",
    events: "event",
    files: "file",
    products: "product",
    inventoryitems: "inventoryitem",
    inventoryitemgroups: "inventoryitemgroup",
    checks: "check",
    costcentres: "costcentre",
    ownaccounts: "ownaccount",
    documentboxes: "documentbox",
    hourrates: "hourrate",
    services: "service",
    customerspaces: "customerspace",
    customerinventoryitems: "customerinventoryitem",
    memberrelations: "memberrelation",
    outgoingsepamandates: "outgoingsepamandate",
}

const parseId = (value: string) => {
    if (/^\d+$/.test(value)) return Number(value)
    return value
}

export default async function resourceHistoryRoutes(server: FastifyInstance) {
    server.get("/history", {
        schema: {
            tags: ["History"],
            summary: "Get all history entries for the active tenant",
        },
    }, async (req: any) => {
        const data = await server.db
            .select()
            .from(historyitems)
            .where(eq(historyitems.tenant, req.user?.tenant_id))
            .orderBy(asc(historyitems.createdAt));

        const userIds = Array.from(
            new Set(data.map((item) => item.createdBy).filter(Boolean))
        ) as string[];

        const profiles = userIds.length > 0
            ? await server.db
                .select()
                .from(authProfiles)
                .where(and(
                    eq(authProfiles.tenant_id, req.user?.tenant_id),
                    inArray(authProfiles.user_id, userIds)
                ))
            : [];

        const profileByUserId = new Map(
            profiles.map((profile) => [profile.user_id, profile])
        );

        return data.map((historyitem) => ({
            ...historyitem,
            created_at: historyitem.createdAt,
            created_by: historyitem.createdBy,
            created_by_profile: historyitem.createdBy ? profileByUserId.get(historyitem.createdBy) || null : null,
        }));
    });

    server.get<{
        Params: { resource: string; id: string }
    }>("/resource/:resource/:id/history", {
        schema: {
            tags: ["History"],
            summary: "Get history entries for a resource",
            params: {
                type: "object",
                required: ["resource", "id"],
                properties: {
                    resource: { type: "string" },
                    id: { type: "string" },
                },
            },
        },
    }, async (req, reply) => {
        const { resource, id } = req.params;

        const column = columnMap[resource];
        if (!column) {
            return reply.code(400).send({ error: `History not supported for resource '${resource}'` });
        }

        const data = await server.db
            .select()
            .from(historyitems)
            .where(eq(column, parseId(id)))
            .orderBy(asc(historyitems.createdAt));

        const userIds = Array.from(
            new Set(data.map((item) => item.createdBy).filter(Boolean))
        ) as string[]

        const profiles = userIds.length > 0
            ? await server.db
                .select()
                .from(authProfiles)
                .where(and(
                    eq(authProfiles.tenant_id, req.user?.tenant_id),
                    inArray(authProfiles.user_id, userIds)
                ))
            : []

        const profileByUserId = new Map(
            profiles.map((profile) => [profile.user_id, profile])
        )

        const dataCombined = data.map((historyitem) => ({
            ...historyitem,
            created_at: historyitem.createdAt,
            created_by: historyitem.createdBy,
            created_by_profile: historyitem.createdBy ? profileByUserId.get(historyitem.createdBy) || null : null,
        }))



        return dataCombined;
    });

    // Neuen HistoryItem anlegen
    server.post<{
        Params: { resource: string; id: string };
        Body: {
            text: string;
            old_val?: string | null;
            new_val?: string | null;
            config?: Record<string, any>;
        };
    }>("/resource/:resource/:id/history", {
        schema: {
            tags: ["History"],
            summary: "Create new history entry",
            params: {
                type: "object",
                properties: {
                    resource: { type: "string" },
                    id: { type: "string" }
                },
                required: ["resource", "id"]
            },
            body: {
                type: "object",
                properties: {
                    text: { type: "string" },
                    old_val: { type: "string", nullable: true },
                    new_val: { type: "string", nullable: true },
                    config: { type: "object", nullable: true }
                },
                required: ["text"]
            },
            response: {
                201: {
                    type: "object",
                    properties: {
                        id: { type: "number" },
                        text: { type: "string" },
                        created_at: { type: "string" },
                        created_by: { type: "string" }
                    }
                }
            }
        }
    }, async (req, reply) => {
        const { resource, id } = req.params;
        const { text, old_val, new_val, config } = req.body;

        const userId = (req.user as any)?.user_id;


        const fkField = insertFieldMap[resource];
        if (!fkField) {
            return reply.code(400).send({ error: `Unknown resource: ${resource}` });
        }

        const inserted = await server.db
            .insert(historyitems)
            .values({
                text,
                [fkField]: parseId(id),
                oldVal: old_val || null,
                newVal: new_val || null,
                config: config || null,
                tenant: (req.user as any)?.tenant_id,
                createdBy: userId
            })
            .returning()

        const data = inserted[0]
        if (!data) {
            return reply.code(500).send({ error: "Failed to create history entry" });
        }

        return reply.code(201).send({
            ...data,
            created_at: data.createdAt,
            created_by: data.createdBy
        });
    });
}
