import { and, eq } from 'drizzle-orm';
import { NextRequest, NextResponse } from 'next/server';
import { courses } from '@/db/schema';
import {
  AUDIT_ACTION,
  AUDIT_MODULE,
  getRequestMetadata,
  logAuditEvent,
  toAuditValue
} from '@/features/audit-logs/server/audit-service';
import type { CourseMutationPayload } from '@/features/courses/api/types';
import {
  getCourseByIdForOrganization,
  normalizeCoursePayload,
  serializeCourse
} from '@/features/courses/server/course-data';
import { AuthError, requireHRD } from '@/lib/auth/session';
import { db } from '@/lib/db';

type Params = { params: Promise<{ id: string }> };

export async function GET(request: NextRequest, { params }: Params) {
  try {
    const { organization } = await requireHRD();
    const { id } = await params;

    const course = await getCourseByIdForOrganization({
      id: Number(id),
      organizationId: organization.id
    });

    if (!course) {
      return NextResponse.json(
        { success: false, message: `Course with ID ${id} not found` },
        { status: 404 }
      );
    }

    return NextResponse.json({
      success: true,
      time: new Date().toISOString(),
      message: `Course with ID ${id} found`,
      course: serializeCourse(course)
    });
  } catch (error) {
    if (error instanceof AuthError) {
      return NextResponse.json({ message: error.message }, { status: error.status });
    }

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

export async function PATCH(request: NextRequest, { params }: Params) {
  try {
    const { organization, session } = await requireHRD();
    const requestMetadata = getRequestMetadata(request);
    const { id } = await params;
    const body = normalizeCoursePayload((await request.json()) as CourseMutationPayload);

    const existingCourse = await getCourseByIdForOrganization({
      id: Number(id),
      organizationId: organization.id
    });

    if (!existingCourse) {
      return NextResponse.json(
        { success: false, message: `Course with ID ${id} not found` },
        { status: 404 }
      );
    }

    const [course] = await db
      .update(courses)
      .set({
        courseCode: body.courseCode,
        name: body.name,
        category: body.category,
        organizer: body.organizer,
        standardHours: body.standardHours,
        certificateValidityMonths: body.certificateValidityMonths,
        isRequired: body.isRequired,
        certificateRequired: existingCourse.certificateRequired,
        trainingCost: body.trainingCost,
        description: body.description,
        isActive: body.isActive,
        updatedAt: new Date()
      })
      .where(and(eq(courses.id, Number(id)), eq(courses.organizationId, organization.id)))
      .returning();

    const serializedCourse = serializeCourse(course);

    await logAuditEvent({
      organizationId: organization.id,
      userId: session.user.id,
      module: AUDIT_MODULE.COURSE_MASTER,
      action: AUDIT_ACTION.UPDATE,
      entityName: course.name,
      entityId: course.id,
      oldValue: toAuditValue(serializeCourse(existingCourse)),
      newValue: toAuditValue(serializedCourse),
      ...requestMetadata
    });

    return NextResponse.json({
      success: true,
      time: new Date().toISOString(),
      message: 'Course updated successfully',
      course: serializedCourse
    });
  } catch (error) {
    if (error instanceof AuthError) {
      return NextResponse.json({ message: error.message }, { status: error.status });
    }

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

export async function DELETE(request: NextRequest, { params }: Params) {
  try {
    const { organization } = await requireHRD();
    const { id } = await params;

    const [deletedCourse] = await db
      .delete(courses)
      .where(and(eq(courses.id, Number(id)), eq(courses.organizationId, organization.id)))
      .returning({ id: courses.id });

    if (!deletedCourse) {
      return NextResponse.json(
        { success: false, message: `Course with ID ${id} not found` },
        { status: 404 }
      );
    }

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

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