import { and, eq, isNull } from 'drizzle-orm';
import { NextRequest, NextResponse } from 'next/server';
import { ZodError } from 'zod';
import { memberships, organizations, users } from '@/db/schema';
import { organizerSchema } from '@/features/organizers/schemas/organizer';
import { createOrganizerRecord, listOrganizers } from '@/features/organizers/server/organizer-data';
import { getDefaultPermissionsForRole, isHRD, isSuperAdmin } from '@/lib/auth/roles';
import { db } from '@/lib/db';
import { AuthError, requireSession, requireSuperAdmin } from '@/lib/auth/session';

export async function POST(request: NextRequest) {
  try {
    const session = await requireSuperAdmin();
    const body = organizerSchema.parse(await request.json());
    const organizationId = await createOrganizerRecord({
      actorUserId: session.user.id,
      payload: body
    });

    await db.insert(memberships).values({
      id: crypto.randomUUID(),
      userId: session.user.id,
      organizationId,
      role: 'admin',
      permissions: getDefaultPermissionsForRole('admin')
    });

    await db
      .update(users)
      .set({ activeOrganizationId: organizationId })
      .where(eq(users.id, session.user.id));

    return NextResponse.json({
      success: true,
      organizationId
    });
  } catch (error) {
    if (error instanceof AuthError) {
      return NextResponse.json({ message: error.message }, { status: error.status });
    }

    if (error instanceof ZodError) {
      return NextResponse.json(
        { message: error.issues[0]?.message ?? 'Invalid organizer data' },
        { status: 400 }
      );
    }

    if (error instanceof Error && error.message === 'DUPLICATE_NAME') {
      return NextResponse.json({ message: 'Organizer name already exists' }, { status: 409 });
    }

    return NextResponse.json({ message: 'Unable to create organization' }, { status: 500 });
  }
}

export async function GET(request: NextRequest) {
  try {
    const session = await requireSession();
    const requestedStatus = request.nextUrl.searchParams.get('status');
    const canReadAllOrganizers =
      isSuperAdmin(session.user.systemRole) ||
      isHRD({
        businessRole: session.user.businessRole,
        systemRole: session.user.systemRole,
        membershipRole: session.user.membershipRole,
        role: session.user.role
      });

    const organizersList = canReadAllOrganizers
      ? await listOrganizers({
          status:
            requestedStatus === 'inactive' || requestedStatus === 'all' ? requestedStatus : 'active'
        })
      : await db
          .select({
            id: organizations.id,
            name: organizations.name,
            slug: organizations.slug,
            imageUrl: organizations.imageUrl,
            plan: organizations.plan,
            isActive: organizations.isActive,
            deletedAt: organizations.deletedAt,
            deletedBy: organizations.deletedBy,
            createdBy: organizations.createdBy,
            createdAt: organizations.createdAt,
            updatedAt: organizations.updatedAt
          })
          .from(organizations)
          .innerJoin(memberships, eq(memberships.organizationId, organizations.id))
          .where(
            and(
              eq(memberships.userId, session.user.id),
              eq(organizations.isActive, true),
              isNull(organizations.deletedAt)
            )
          )
          .then((rows) =>
            rows.map((row) => ({
              id: row.id,
              name: row.name,
              slug: row.slug,
              plan: row.plan,
              is_active: row.isActive,
              deleted_at: row.deletedAt ? row.deletedAt.toISOString() : null,
              deleted_by: row.deletedBy,
              created_by: row.createdBy,
              created_at: row.createdAt.toISOString(),
              updated_at: row.updatedAt.toISOString()
            }))
          );

    return NextResponse.json({
      success: true,
      organizers: organizersList
    });
  } catch (error) {
    if (error instanceof AuthError) {
      return NextResponse.json({ message: error.message }, { status: error.status });
    }

    return NextResponse.json({ message: 'Unable to load organizers' }, { status: 500 });
  }
}
