import { NextResponse } from 'next/server';

import { withAuth, withPermission } from '@/lib/api/helpers';
import { errorResponse, ValidationError } from '@/lib/errors';
import {
  clearPortLogo,
  getPortLogoFile,
  processLogoUpload,
  setPortLogo,
  type LogoCrop,
} from '@/lib/services/logo.service';

const MAX_RAW_BYTES = 5 * 1024 * 1024;

function parseCrop(value: FormDataEntryValue | null): LogoCrop | undefined {
  if (typeof value !== 'string' || value.length === 0) return undefined;
  let parsed: unknown;
  try {
    parsed = JSON.parse(value);
  } catch {
    throw new ValidationError('Invalid crop JSON');
  }
  if (!parsed || typeof parsed !== 'object') {
    throw new ValidationError('Invalid crop payload');
  }
  const c = parsed as Record<string, unknown>;
  for (const key of ['x', 'y', 'width', 'height']) {
    if (typeof c[key] !== 'number' || !Number.isFinite(c[key])) {
      throw new ValidationError(`Crop ${key} must be a finite number`);
    }
  }
  return {
    x: c.x as number,
    y: c.y as number,
    width: c.width as number,
    height: c.height as number,
  };
}

/**
 * GET /api/v1/admin/branding/logo
 * Returns metadata for the current port logo (or null).
 */
export const GET = withAuth(
  withPermission('admin', 'manage_settings', async (_req, ctx) => {
    try {
      if (!ctx.portId) throw new ValidationError('No active port');
      const file = await getPortLogoFile(ctx.portId);
      if (!file) {
        return NextResponse.json({ data: null });
      }
      // Path-only - the admin UI renders this as `<img src>` and the
      // browser resolves against the current origin. Stays valid whether
      // the admin opens the page from localhost or a LAN IP.
      return NextResponse.json({
        data: {
          fileId: file.id,
          previewUrl: `/api/public/files/${file.id}`,
          sizeBytes: file.sizeBytes,
          mimeType: file.mimeType,
        },
      });
    } catch (error) {
      return errorResponse(error);
    }
  }),
);

/**
 * POST /api/v1/admin/branding/logo
 *
 * Multipart: `file` (required) + `crop` (optional JSON string `{x, y, width, height}`).
 * Runs the sharp normalization pipeline; if accepted, atomically updates the
 * `port_logo_file_id` system setting and soft-archives the previous logo.
 */
export const POST = withAuth(
  withPermission('admin', 'manage_settings', async (req, ctx) => {
    try {
      if (!ctx.portId) throw new ValidationError('No active port');
      const formData = await req.formData();
      const fileEntry = formData.get('file');
      if (!(fileEntry instanceof File)) throw new ValidationError('Missing `file` part');
      if (fileEntry.size === 0) throw new ValidationError('Empty file');
      if (fileEntry.size > MAX_RAW_BYTES) {
        throw new ValidationError(`File exceeds ${MAX_RAW_BYTES / 1024 / 1024} MB`);
      }
      const crop = parseCrop(formData.get('crop'));
      const buffer = Buffer.from(await fileEntry.arrayBuffer());
      const processed = await processLogoUpload(buffer, crop);
      const result = await setPortLogo(ctx.portId, processed, {
        userId: ctx.userId,
        portId: ctx.portId,
        ipAddress: ctx.ipAddress,
        userAgent: ctx.userAgent,
      });
      return NextResponse.json({
        data: {
          fileId: result.fileId,
          previewUrl: `/api/public/files/${result.fileId}`,
          warnings: result.warnings,
          finalDimensions: processed.finalDimensions,
          finalBytes: processed.finalBytes,
          originalDimensions: processed.originalDimensions,
          originalFormat: processed.originalFormat,
        },
      });
    } catch (error) {
      return errorResponse(error);
    }
  }),
);

/**
 * DELETE /api/v1/admin/branding/logo
 * Clear the port logo. Subsequent PDF renders fall back to the port-name text header.
 */
export const DELETE = withAuth(
  withPermission('admin', 'manage_settings', async (_req, ctx) => {
    try {
      if (!ctx.portId) throw new ValidationError('No active port');
      await clearPortLogo(ctx.portId, {
        userId: ctx.userId,
        portId: ctx.portId,
        ipAddress: ctx.ipAddress,
        userAgent: ctx.userAgent,
      });
      return new NextResponse(null, { status: 204 });
    } catch (error) {
      return errorResponse(error);
    }
  }),
);
