import { externalApi } from '../_api.ts';
import { z } from 'astro:schema';
import { db } from '@db/database.ts';
import { sendWebhook, WebhookAction } from '@util/webhook.ts';
import { BASE_PATH } from 'astro:env/server';

export const GET = externalApi({
  auth: true,
  handler: async () => {
    const reports = await db.getReports({});

    return new Response(
      JSON.stringify({
        reports: reports.map((report) => ({
          reporter: report.reporter.uuid,
          reported: report.reported?.uuid ?? null,
          reason: report.reason,
          created: report.createdAt?.getTime() ?? null,
          status: report.status?.status ?? null,
          url: `${BASE_PATH}/report/${report.urlHash}`
        }))
      }),
      { status: 200 }
    );
  }
});

export const POST = externalApi({
  input: z.object({
    reporter: z.string(),
    reported: z.string().nullable(),
    reason: z.string()
  }),
  auth: true,
  handler: async ({ input }) => {
    const reporter = await db.getUserByUuid({ uuid: input.reporter });
    if (!reporter) return new Response(null, { status: 404 });

    let reported = null;
    if (input.reported) {
      reported = await db.getUserByUuid({ uuid: input.reported });
      if (!reported) return new Response(null, { status: 404 });
    }

    const report = await db.addReport({
      reporterId: reporter.id,
      reportedId: reported?.id,
      reason: input.reason,
      body: null
    });

    return new Response(JSON.stringify({ url: report.url }), { status: 200 });
  }
});

export const PUT = externalApi({
  input: z.object({
    reporter: z.string().nullable(),
    reported: z.string(),
    reason: z.string(),
    body: z.string().nullable(),
    notice: z.string().nullable(),
    statement: z.string().nullable(),
    strike_reason_id: z.number()
  }),
  auth: true,
  handler: async ({ input }) => {
    const reported = await db.getUserByUuid({ uuid: input.reported });
    if (!reported) return new Response(null, { status: 404 });

    let reporter = null;
    if (input.reporter) {
      reporter = await db.getUserByUuid({ uuid: input.reporter });
      if (!reporter) return new Response(null, { status: 404 });
    }

    await db.transaction(async (tx) => {
      const report = await tx.addReport({
        reporterId: reporter?.id,
        reportedId: reported.id,
        createdAt: new Date(),
        reason: input.reason,
        body: input.body
      });

      await tx.editReportStatus({
        reportId: report.id,
        notice: input.notice,
        statement: input.statement,
        status: 'closed'
      });

      await tx.editStrike({
        reportId: report.id,
        strikeReasonId: input.strike_reason_id
      });
    });

    // send webhook in background
    sendWebhook(WebhookAction.Strike, {
      uuid: reported.uuid!
    });

    return new Response(null, { status: 200 });
  }
});
