import { NextRequest, NextResponse } from 'next/server';
import { certificates } from '@/db/schema';
import {
  AUDIT_ACTION,
  AUDIT_MODULE,
  getRequestMetadata,
  logAuditEvent,
  toAuditValue
} from '@/features/audit-logs/server/audit-service';
import {
  canEmployeeManageEditableRecord,
  getTrainingRecordByIdForOrganization
} from '@/features/training-records/server/training-record-data';
import { AuthError, requireOrganizationAccess } from '@/lib/auth/session';
import { db } from '@/lib/db';
import { saveCertificateFile } from '@/lib/certificate-storage';

export const runtime = 'nodejs';

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

function serializeCertificate(certificate: typeof certificates.$inferSelect) {
  return {
    id: certificate.id,
    organization_id: certificate.organizationId,
    training_record_id: certificate.trainingRecordId,
    file_name: certificate.fileName,
    file_type: certificate.fileType,
    file_size: certificate.fileSize,
    storage_key: certificate.storageKey,
    file_url: `/api/training-records/${certificate.trainingRecordId}/certificates/${certificate.id}/download`,
    uploaded_by: certificate.uploadedBy,
    uploaded_at: certificate.uploadedAt.toISOString(),
    created_at: certificate.createdAt.toISOString(),
    updated_at: certificate.updatedAt.toISOString()
  };
}

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

    const record = await getTrainingRecordByIdForOrganization({
      id: Number(id),
      organizationId: organization.id,
      userId: session.user.id,
      role: membership.role
    });

    if (!record) {
      return NextResponse.json({ message: 'ไม่พบรายการอบรม' }, { status: 404 });
    }

    const rows = await db.query.certificates.findMany({
      where: (table, { and, eq }) =>
        and(eq(table.trainingRecordId, Number(id)), eq(table.organizationId, organization.id)),
      orderBy: (table, { desc }) => [desc(table.uploadedAt)]
    });

    return NextResponse.json({
      success: true,
      time: new Date().toISOString(),
      message: 'โหลดเอกสารแนบเรียบร้อยแล้ว',
      certificates: rows.map(serializeCertificate)
    });
  } catch (error) {
    if (error instanceof AuthError) {
      return NextResponse.json({ message: error.message }, { status: error.status });
    }

    return NextResponse.json({ message: 'ไม่สามารถโหลดเอกสารแนบได้' }, { status: 500 });
  }
}

export async function POST(request: NextRequest, { params }: Params) {
  try {
    const { organization, session, membership } = await requireOrganizationAccess();
    const requestMetadata = getRequestMetadata(request);
    const { id } = await params;
    const record = await getTrainingRecordByIdForOrganization({
      id: Number(id),
      organizationId: organization.id,
      userId: session.user.id,
      role: membership.role
    });

    if (!record) {
      return NextResponse.json({ message: 'ไม่พบรายการอบรม' }, { status: 404 });
    }

    if (
      !(await canEmployeeManageEditableRecord({
        organizationId: organization.id,
        role: membership.role,
        recordUserId: record.userId,
        recordEmployeeId: record.employeeId,
        actorUserId: session.user.id,
        approvalStatus: record.approvalStatus
      }))
    ) {
      return NextResponse.json(
        { message: 'พนักงานสามารถอัปโหลดเอกสารได้เฉพาะรายการที่อยู่ในสถานะฉบับร่างหรือขอแก้ไขเท่านั้น' },
        { status: 403 }
      );
    }

    const formData = await request.formData();
    const files = formData.getAll('files').filter((entry): entry is File => entry instanceof File);

    if (!files.length) {
      return NextResponse.json({ message: 'กรุณาเลือกไฟล์อย่างน้อย 1 ไฟล์' }, { status: 400 });
    }

    const uploadedCertificates = [];

    for (const file of files) {
      const storedFile = await saveCertificateFile({
        file,
        organizationId: organization.id,
        trainingRecordId: Number(id)
      });

      const [certificate] = await db
        .insert(certificates)
        .values({
          organizationId: organization.id,
          trainingRecordId: Number(id),
          fileName: storedFile.fileName,
          fileType: storedFile.fileType,
          fileSize: storedFile.fileSize,
          storageKey: storedFile.storageKey,
          fileUrl: storedFile.fileUrl,
          uploadedBy: session.user.id
        })
        .returning();

      await logAuditEvent({
        organizationId: organization.id,
        userId: session.user.id,
        module: AUDIT_MODULE.TRAINING_RECORDS,
        action: AUDIT_ACTION.CREATE,
        entityName: certificate.fileName,
        entityId: certificate.id,
        newValue: toAuditValue(serializeCertificate(certificate)),
        ...requestMetadata
      });

      uploadedCertificates.push(serializeCertificate(certificate));
    }

    return NextResponse.json(
      {
        success: true,
        time: new Date().toISOString(),
        message: 'อัปโหลดเอกสารแนบเรียบร้อยแล้ว',
        certificates: uploadedCertificates
      },
      { status: 201 }
    );
  } catch (error) {
    if (error instanceof AuthError) {
      return NextResponse.json({ message: error.message }, { status: error.status });
    }

    return NextResponse.json(
      {
        message: error instanceof Error ? error.message : 'ไม่สามารถอัปโหลดเอกสารแนบได้'
      },
      { status: 500 }
    );
  }
}
