import { BadRequestException, Body, Controller, Delete, Get, Param, Post, Put } from '@nestjs/common';
import { PrismaService } from '../common/prisma.service';
import { getMerchant } from '../common/core';
import { MarcadeoProvisioning } from '../integrations/marcadeo-provisioning.service';

// Built-in optional signup fields (Name/Email/Password are always on).
const SIGNUP_DEFAULTS: Record<string, { enabled: boolean; required: boolean }> = {
  phone: { enabled: false, required: false },
  social: { enabled: true, required: false },
  website: { enabled: true, required: false },
  address: { enabled: false, required: false },
};

@Controller('admin')
export class SettingsController {
  constructor(
    private prisma: PrismaService,
    private marcadeo: MarcadeoProvisioning,
  ) {}

  @Get('settings')
  async getSettings() {
    const m = await getMerchant(this.prisma);
    return {
      programName: m.programName,
      autoApprove: m.autoApprove,
      cookieDays: m.cookieDays,
      attribution: m.attribution,
      commissionBase: m.commissionBase,
      defaultCommissionType: m.defaultCommissionType,
      defaultCommissionValue: Number(m.defaultCommissionValue),
      minPayout: Number(m.minPayout),
      commissionNewCustomersOnly: m.commissionNewCustomersOnly,
      excludeSelfPurchase: m.excludeSelfPurchase,
      recordNilSales: m.recordNilSales,
      verifySalesAutomatically: m.verifySalesAutomatically,
      commissionHoldDays: m.commissionHoldDays,
      postCheckoutEnabled: m.postCheckoutEnabled,
      postCheckoutHeading: m.postCheckoutHeading,
      postCheckoutText: m.postCheckoutText,
      postCheckoutButton: m.postCheckoutButton,
      customerAffiliateConnect: m.customerAffiliateConnect,
      mlmEnabled: m.mlmEnabled,
      mlmLevels: Array.isArray(m.mlmLevels) ? (m.mlmLevels as number[]).join(',') : '',
      timezone: m.timezone,
      removeTrackingAfterOrder: m.removeTrackingAfterOrder,
      recaptchaEnabled: m.recaptchaEnabled,
      recaptchaSiteKey: m.recaptchaSiteKey ?? '',
      recaptchaSecret: m.recaptchaSecret ? '••••••' : '', // never echo the real secret
      payoutScheduleEnabled: m.payoutScheduleEnabled,
      payoutScheduleDay: m.payoutScheduleDay,
    };
  }

  @Put('settings')
  async saveSettings(@Body() body: Record<string, any>) {
    const m = await getMerchant(this.prisma);
    const updated = await this.prisma.merchant.update({
      where: { id: m.id },
      data: {
        programName: body.programName ?? m.programName,
        autoApprove: !!body.autoApprove,
        cookieDays: Number(body.cookieDays ?? m.cookieDays),
        attribution: body.attribution ?? m.attribution,
        commissionBase: body.commissionBase ?? m.commissionBase,
        defaultCommissionType: body.defaultCommissionType ?? m.defaultCommissionType,
        defaultCommissionValue: Number(body.defaultCommissionValue ?? m.defaultCommissionValue),
        minPayout: Number(body.minPayout ?? m.minPayout),
        commissionNewCustomersOnly:
          body.commissionNewCustomersOnly ?? m.commissionNewCustomersOnly,
        excludeSelfPurchase: body.excludeSelfPurchase ?? m.excludeSelfPurchase,
        recordNilSales: body.recordNilSales ?? m.recordNilSales,
        verifySalesAutomatically: body.verifySalesAutomatically ?? m.verifySalesAutomatically,
        commissionHoldDays: Number(body.commissionHoldDays ?? m.commissionHoldDays),
        postCheckoutEnabled: body.postCheckoutEnabled ?? m.postCheckoutEnabled,
        postCheckoutHeading: body.postCheckoutHeading ?? m.postCheckoutHeading,
        postCheckoutText: body.postCheckoutText ?? m.postCheckoutText,
        postCheckoutButton: body.postCheckoutButton ?? m.postCheckoutButton,
        customerAffiliateConnect: body.customerAffiliateConnect ?? m.customerAffiliateConnect,
        mlmEnabled: body.mlmEnabled ?? m.mlmEnabled,
        mlmLevels:
          body.mlmLevels !== undefined
            ? String(body.mlmLevels)
                .split(',')
                .map((s: string) => Number(s.trim()))
                .filter((n: number) => !Number.isNaN(n) && n > 0)
            : (m.mlmLevels ?? undefined),
        timezone: body.timezone ?? m.timezone,
        removeTrackingAfterOrder: body.removeTrackingAfterOrder ?? m.removeTrackingAfterOrder,
        recaptchaEnabled: body.recaptchaEnabled ?? m.recaptchaEnabled,
        recaptchaSiteKey: body.recaptchaSiteKey ?? m.recaptchaSiteKey,
        // Only overwrite the secret when a new (non-masked) value is sent.
        recaptchaSecret:
          body.recaptchaSecret && body.recaptchaSecret !== '••••••'
            ? body.recaptchaSecret
            : m.recaptchaSecret,
        payoutScheduleEnabled: body.payoutScheduleEnabled ?? m.payoutScheduleEnabled,
        payoutScheduleDay: Number(body.payoutScheduleDay ?? m.payoutScheduleDay),
      },
    });
    // Keep the Marcadeo advertiser's name in sync with the program name.
    if (body.programName !== undefined && body.programName !== m.programName) {
      await this.marcadeo.syncAdvertiserProfile(updated);
    }
    return { ok: true };
  }

  // --- S2S (server-to-server) postback + IP whitelist ---
  @Get('s2s')
  async getS2s() {
    const m = await getMerchant(this.prisma);
    return this.marcadeo.s2sInfo(m);
  }

  @Post('s2s/ip')
  async addS2sIp(@Body() body: { ip?: string; type?: 'SINGLE' | 'CIDR' }) {
    const ip = (body.ip || '').trim();
    if (!ip) throw new BadRequestException('Enter an IP address or CIDR range');
    const m = await getMerchant(this.prisma);
    const ok = await this.marcadeo.s2sAddIp(m, ip, body.type);
    if (!ok) throw new BadRequestException('Could not add IP (is the store connected to Marcadeo?)');
    return { ok: true };
  }

  @Delete('s2s/ip/:id')
  async removeS2sIp(@Param('id') id: string) {
    const m = await getMerchant(this.prisma);
    await this.marcadeo.s2sRemoveIp(m, id);
    return { ok: true };
  }

  // --- Branding (PRD 4.10) ---
  @Get('branding')
  async getBranding() {
    const m = await getMerchant(this.prisma);
    return {
      logoUrl: m.logoUrl,
      brandColor: m.brandColor,
      brandSecondaryColor: m.brandSecondaryColor,
      portalSubdomain: m.portalSubdomain,
      termsText: m.termsText,
    };
  }

  @Put('branding')
  async saveBranding(@Body() body: Record<string, any>) {
    const m = await getMerchant(this.prisma);
    await this.prisma.merchant.update({
      where: { id: m.id },
      data: {
        logoUrl: body.logoUrl ?? m.logoUrl,
        brandColor: body.brandColor ?? m.brandColor,
        brandSecondaryColor: body.brandSecondaryColor ?? m.brandSecondaryColor,
        portalSubdomain: body.portalSubdomain ?? m.portalSubdomain,
        termsText: body.termsText ?? m.termsText,
      },
    });
    return { ok: true };
  }

  // --- Notifications config (PRD 4.9) ---
  @Get('notifications')
  async getNotifications() {
    const m = await getMerchant(this.prisma);
    const def = { welcome: true, sale_notification: true, payout: true, admin_new_affiliate: true, admin_payout_request: true };
    return { ...def, ...((m.notifications as any) || {}) };
  }

  @Put('notifications')
  async saveNotifications(@Body() body: Record<string, boolean>) {
    const m = await getMerchant(this.prisma);
    await this.prisma.merchant.update({ where: { id: m.id }, data: { notifications: body as any } });
    return { ok: true };
  }

  // --- Custom signup fields (PRD 4.1) ---
  @Get('signup-fields')
  async signupFields() {
    const m = await getMerchant(this.prisma);
    const list = await this.prisma.signupFieldDef.findMany({ where: { merchantId: m.id }, orderBy: { sortOrder: 'asc' } });
    return list.map((f) => ({ id: f.id, label: f.label, type: f.type, required: f.required, sortOrder: f.sortOrder }));
  }

  @Post('signup-fields')
  async createSignupField(@Body() body: Record<string, any>) {
    const m = await getMerchant(this.prisma);
    if (!body.label?.trim()) throw new BadRequestException('Label is required');
    const count = await this.prisma.signupFieldDef.count({ where: { merchantId: m.id } });
    const f = await this.prisma.signupFieldDef.create({
      data: { merchantId: m.id, label: body.label, type: body.type || 'text', required: !!body.required, sortOrder: count },
    });
    return { ok: true, id: f.id };
  }

  @Delete('signup-fields/:id')
  async deleteSignupField(@Param('id') id: string) {
    await this.prisma.signupFieldDef.delete({ where: { id } });
    return { ok: true };
  }

  // --- Default (built-in) signup fields with enable/required toggles (PRD 4.1) ---
  @Get('signup-defaults')
  async signupDefaults() {
    const m = await getMerchant(this.prisma);
    return { ...SIGNUP_DEFAULTS, ...((m.signupDefaults as Record<string, any>) ?? {}) };
  }

  @Put('signup-defaults')
  async saveSignupDefaults(@Body() body: Record<string, any>) {
    const m = await getMerchant(this.prisma);
    const clean: Record<string, { enabled: boolean; required: boolean }> = {};
    for (const key of Object.keys(SIGNUP_DEFAULTS)) {
      const v = body[key] ?? {};
      clean[key] = { enabled: !!v.enabled, required: !!v.enabled && !!v.required };
    }
    await this.prisma.merchant.update({ where: { id: m.id }, data: { signupDefaults: clean } });
    return { ok: true };
  }
}
