import { FastifyInstance } from "fastify";
import { eq, and } from "drizzle-orm";

import {
    authProfiles,
} from "../../db/schema";
import {
    loadProfileWithBranches,
    resolveTenantBranchIds,
    syncProfileBranches,
} from "../utils/profileBranches";
import {
    enrichProfilesWithTeams,
    resolveTenantTeamIds,
    syncProfileTeams,
} from "../utils/profileTeams";
import {
    enrichProfileWithCalendarSubscription,
    generateProfileCalendarSubscriptionToken,
} from "../utils/calendarSubscription";

export default async function authProfilesRoutes(server: FastifyInstance) {

    // -------------------------------------------------------------
    // GET SINGLE PROFILE
    // -------------------------------------------------------------
    server.get("/profiles/:id", async (req, reply) => {
        try {
            const { id } = req.params as { id: string };
            const tenantId = (req.user as any)?.tenant_id;

            if (!tenantId) {
                return reply.code(400).send({ error: "No tenant selected" });
            }

            const profileWithBranches = await loadProfileWithBranches(server, id, tenantId)
            const [profile] = profileWithBranches
                ? await enrichProfilesWithTeams(server, [profileWithBranches])
                : [null]

            if (!profile) {
                return reply.code(404).send({ error: "User not found or not in tenant" });
            }

            return enrichProfileWithCalendarSubscription(profile);

        } catch (error) {
            console.error("GET /profiles/:id ERROR:", error);
            return reply.code(500).send({ error: "Internal Server Error" });
        }
    });

    function sanitizeProfileUpdate(body: any) {
        const cleaned: any = { ...body }

        // ❌ Systemfelder entfernen
            const forbidden = [
                "id", "user_id", "tenant_id", "created_at", "updated_at",
                "updatedAt", "updatedBy", "old_profile_id", "full_name",
                "branch", "calendar_subscription_token",
                "calendar_subscription_path", "calendar_subscription_url"
        ]
        forbidden.forEach(f => delete cleaned[f])

        // ❌ Falls NULL Strings vorkommen → in null umwandeln
        for (const key of Object.keys(cleaned)) {
            if (cleaned[key] === "") cleaned[key] = null
        }

        // ✅ Date-Felder sauber konvertieren, falls vorhanden
        const dateFields = ["birthday", "entry_date"]

        for (const field of dateFields) {
            if (cleaned[field]) {
                const d = new Date(cleaned[field])
                if (!isNaN(d.getTime())) cleaned[field] = d
                else delete cleaned[field] // invalid → entfernen
            }
        }

        return cleaned
    }

    // -------------------------------------------------------------
    // UPDATE PROFILE
    // -------------------------------------------------------------
    server.put("/profiles/:id", async (req, reply) => {
        try {
            const tenantId = req.user?.tenant_id
            const userId = req.user?.user_id

            if (!tenantId) {
                return reply.code(400).send({ error: "No tenant selected" })
            }

            const { id } = req.params as { id: string }
            let body = req.body as any

            // Clean + Normalize
            body = sanitizeProfileUpdate(body)

            const { primaryBranchId, branchIds } = await resolveTenantBranchIds(
                server,
                tenantId,
                [
                    ...(Array.isArray(body.branch_ids) ? body.branch_ids : []),
                    ...(Array.isArray(body.branches) ? body.branches : []),
                ],
                body.branch_id ?? body.branch?.id ?? null
            )
            const teamIds = await resolveTenantTeamIds(
                server,
                tenantId,
                [
                    ...(Array.isArray(body.team_ids) ? body.team_ids : []),
                    ...(Array.isArray(body.teams) ? body.teams : []),
                ],
            )

            delete body.branch_ids
            delete body.branches
            delete body.team_ids
            delete body.teams

            const updateData = {
                ...body,
                branch_id: primaryBranchId,
                updatedAt: new Date(),
                updatedBy: userId
            }

            const updated = await server.db
                .update(authProfiles)
                .set(updateData)
                .where(
                    and(
                        eq(authProfiles.id, id),
                        eq(authProfiles.tenant_id, tenantId)
                    )
                )
                .returning()

            if (!updated.length) {
                return reply.code(404).send({ error: "User not found or not in tenant" })
            }

            await syncProfileBranches(server, id, branchIds, userId)
            await syncProfileTeams(server, id, teamIds, userId)

            const profileWithBranches = await loadProfileWithBranches(server, id, tenantId)
            const [profile] = profileWithBranches
                ? await enrichProfilesWithTeams(server, [profileWithBranches])
                : [null]
            return enrichProfileWithCalendarSubscription(profile || updated[0])

        } catch (err) {
            console.error("PUT /profiles/:id ERROR:", err)
            if (err instanceof Error && ["INVALID_BRANCH_SELECTION", "INVALID_PRIMARY_BRANCH"].includes(err.message)) {
                return reply.code(400).send({ error: "Ungültige Niederlassungsauswahl" })
            }
            if (err instanceof Error && err.message === "INVALID_TEAM_SELECTION") {
                return reply.code(400).send({ error: "Ungültige Teamauswahl" })
            }
            return reply.code(500).send({ error: "Internal Server Error" })
        }
    })

    server.post("/profiles/:id/calendar-subscription-token", async (req, reply) => {
        try {
            const tenantId = req.user?.tenant_id

            if (!tenantId) {
                return reply.code(400).send({ error: "No tenant selected" })
            }

            const { id } = req.params as { id: string }
            const updatedProfile = await generateProfileCalendarSubscriptionToken(server, id, tenantId)

            if (!updatedProfile) {
                return reply.code(404).send({ error: "User not found or not in tenant" })
            }

            const profileWithBranches = await loadProfileWithBranches(server, id, tenantId)
            const [profile] = profileWithBranches
                ? await enrichProfilesWithTeams(server, [profileWithBranches])
                : [updatedProfile]

            return enrichProfileWithCalendarSubscription(profile)
        } catch (err) {
            console.error("POST /profiles/:id/calendar-subscription-token ERROR:", err)
            return reply.code(500).send({ error: "Internal Server Error" })
        }
    })
}
