import { NextResponse } from 'next/server';
import { and, desc, eq } from 'drizzle-orm';

import { withAuth, withPermission } from '@/lib/api/helpers';
import { db } from '@/lib/db';
import { interests } from '@/lib/db/schema/interests';
import { clientAddresses, clientContacts } from '@/lib/db/schema/clients';
import { errorResponse, NotFoundError } from '@/lib/errors';
import { buildEoiContext } from '@/lib/services/eoi-context';

/**
 * Returns the resolved `EoiContext` for the given interest. Drives the
 * EOI generate dialog's pre-flight preview so a sales rep can see (and
 * correct) every value before sending the document for signing.
 *
 * Augments the core context with `available.emails` / `available.phones`
 * - every non-deleted client_contacts row for the linked client. The
 * dialog renders these as combobox options so the rep can pick a
 * secondary contact for this EOI (Phase 3b).
 *
 * No mutation; pure read.
 */
export const GET = withAuth(
  withPermission('interests', 'view', async (_req, ctx, params) => {
    try {
      const context = await buildEoiContext(params.id!, ctx.portId);

      // Resolve the linked client to fetch every contact row. The core
      // context only carries the single "primary" value; the dialog needs
      // the full set to render the combobox.
      const interest = await db.query.interests.findFirst({
        where: and(eq(interests.id, params.id!), eq(interests.portId, ctx.portId)),
      });
      if (!interest) throw new NotFoundError('Interest');

      const contactRows = await db
        .select({
          id: clientContacts.id,
          channel: clientContacts.channel,
          value: clientContacts.value,
          isPrimary: clientContacts.isPrimary,
          source: clientContacts.source,
        })
        .from(clientContacts)
        .where(eq(clientContacts.clientId, interest.clientId))
        .orderBy(desc(clientContacts.isPrimary), desc(clientContacts.updatedAt));

      const addressRows = await db
        .select({
          id: clientAddresses.id,
          streetAddress: clientAddresses.streetAddress,
          city: clientAddresses.city,
          subdivisionIso: clientAddresses.subdivisionIso,
          postalCode: clientAddresses.postalCode,
          countryIso: clientAddresses.countryIso,
          isPrimary: clientAddresses.isPrimary,
          source: clientAddresses.source,
        })
        .from(clientAddresses)
        .where(eq(clientAddresses.clientId, interest.clientId))
        .orderBy(desc(clientAddresses.isPrimary), desc(clientAddresses.updatedAt));

      const available = {
        emails: contactRows
          .filter((c) => c.channel === 'email')
          .map((c) => ({ id: c.id, value: c.value, isPrimary: c.isPrimary, source: c.source })),
        phones: contactRows
          .filter((c) => c.channel === 'phone' || c.channel === 'whatsapp')
          .map((c) => ({
            id: c.id,
            value: c.value,
            isPrimary: c.isPrimary,
            channel: c.channel,
            source: c.source,
          })),
        addresses: addressRows,
      };

      return NextResponse.json({ data: { ...context, available } });
    } catch (error) {
      return errorResponse(error);
    }
  }),
);
