import { NextResponse } from 'next/server';
import { z } from 'zod';
import { withErrorHandler } from '@server/middleware/withErrorHandler';
import { withAuth, AuthedRequest } from '@server/middleware/withAuth';
import { ForbiddenError, ValidationError, AuthError } from '@server/errors';
import { initDatabase } from '@server/db/init';
import {
  getRestaurantSmtpView,
  setRestaurantSmtp,
  clearRestaurantSmtp,
  getRestaurantSmtp,
} from '@server/services/email/restaurant-settings';
import { sendRaw } from '@server/services/email/transport';
import { renderTemplate } from '@server/services/email/render';

function requireRestaurantManager(req: AuthedRequest): string {
  const { restaurantId, role } = req.session;
  if (!restaurantId) throw new AuthError();
  if (role !== 'owner' && role !== 'manager') {
    throw new ForbiddenError('Only restaurant owners and managers can change SMTP settings');
  }
  return restaurantId;
}

export const GET = withErrorHandler(
  withAuth(async (req: AuthedRequest) => {
    const restaurantId = requireRestaurantManager(req);
    await initDatabase();
    const view = await getRestaurantSmtpView(restaurantId);
    return NextResponse.json({ smtp: view });
  })
);

const saveSchema = z.object({
  enabled: z.boolean(),
  host: z.string().trim().max(255).default(''),
  port: z.coerce.number().int().min(1).max(65535).default(587),
  user: z.string().trim().max(255).default(''),
  pass: z.string().optional().default(''),
  from: z.string().trim().max(255).default(''),
  secure: z.boolean().optional().default(false),
});

export const POST = withErrorHandler(
  withAuth(async (req: AuthedRequest) => {
    const restaurantId = requireRestaurantManager(req);
    await initDatabase();
    const body = await req.json().catch(() => ({}));
    const parsed = saveSchema.safeParse(body);
    if (!parsed.success) throw new ValidationError(parsed.error.issues[0]?.message || 'Invalid input');
    const data = parsed.data;

    if (data.enabled) {
      if (!data.host) throw new ValidationError('SMTP host is required when enabling tenant SMTP');
      if (!data.user) throw new ValidationError('SMTP username is required when enabling tenant SMTP');
      if (!data.from) throw new ValidationError('From address is required when enabling tenant SMTP');
      const existing = await getRestaurantSmtpView(restaurantId);
      if (!existing.passSet && !data.pass) {
        throw new ValidationError('SMTP password is required when enabling tenant SMTP');
      }
    }

    await setRestaurantSmtp(restaurantId, data);
    return NextResponse.json({ ok: true, smtp: await getRestaurantSmtpView(restaurantId) });
  })
);

export const DELETE = withErrorHandler(
  withAuth(async (req: AuthedRequest) => {
    const restaurantId = requireRestaurantManager(req);
    await initDatabase();
    await clearRestaurantSmtp(restaurantId);
    return NextResponse.json({ ok: true });
  })
);

const testSchema = z.object({ to: z.string().email() });

export const PUT = withErrorHandler(
  withAuth(async (req: AuthedRequest) => {
    const restaurantId = requireRestaurantManager(req);
    await initDatabase();
    const body = await req.json().catch(() => ({}));
    const parsed = testSchema.safeParse(body);
    if (!parsed.success) throw new ValidationError('Invalid recipient email');

    const cfg = await getRestaurantSmtp(restaurantId);
    if (!cfg) throw new ValidationError('Tenant SMTP not configured or not enabled yet');

    const rendered = await renderTemplate('signup_otp', { name: 'Test', code: '000000' });
    const result = await sendRaw(parsed.data.to, `[Test] ${rendered.subject}`, rendered.html, null, restaurantId);
    if (!result) throw new ValidationError('Send failed — check SMTP host/credentials');
    return NextResponse.json({ ok: true });
  })
);
