/**
 * User settings REST endpoints.
 *
 * GET    /settings/kill-switch       — public kill switch check (no auth)
 * GET    /settings                   — get user settings
 * PUT    /settings                   — merge global settings
 * GET    /settings/device/:deviceId  — get resolved settings for a device
 * PUT    /settings/device/:deviceId  — set per-device overrides
 * DELETE /settings/device/:deviceId  — clear per-device overrides
 */

import type { FastifyInstance, FastifyRequest } from 'fastify';
import { getRequestProductId } from '../../lib/request-context.js';
import { BadRequestError, UnauthorizedError } from '../../lib/errors.js';
import * as repo from './repository.js';
import { UpdateSettingsSchema, SetDeviceOverridesSchema, type UserSettingsDoc } from './types.js';
import * as flagRepo from '../flags/repository.js';

function getRequestUserId(req: FastifyRequest): string {
  const userId = req.jwtPayload?.sub;
  if (!userId) throw new UnauthorizedError('Authentication required');
  return userId;
}

function buildDefaultDoc(productId: string, userId: string): UserSettingsDoc {
  const now = new Date().toISOString();
  return {
    id: repo.getSettingsId(productId, userId),
    productId,
    userId,
    settings: {},
    deviceOverrides: {},
    createdAt: now,
    updatedAt: now,
  };
}

export async function settingsRoutes(app: FastifyInstance) {
  // Public kill switch endpoint — no auth required.
  // Mobile apps call this at launch to check if the app is disabled.
  // Reads the `kill_switch` feature flag: if enabled=true → app is disabled.
  app.get('/settings/kill-switch', async req => {
    const productId =
      (req.query as { productId?: string }).productId ||
      (req.headers['x-product-id'] as string) ||
      process.env.PRODUCT_ID ||
      '';
    if (!productId) return { enabled: true, disabled: false, message: '' };

    try {
      const flag = await flagRepo.getByKey('kill_switch', productId);
      if (flag && flag.enabled) {
        return {
          enabled: false,
          disabled: true,
          message: flag.description || 'LysnrAI is temporarily unavailable for maintenance.',
        };
      }
    } catch {
      // DB error — fail open (allow app to run)
    }
    return { enabled: true, disabled: false, message: '' };
  });

  app.get('/settings', async req => {
    const productId = getRequestProductId(req);
    const userId = getRequestUserId(req);

    const existing = await repo.getByUserId(userId, productId);
    return existing ?? buildDefaultDoc(productId, userId);
  });

  app.put('/settings', async req => {
    const parsed = UpdateSettingsSchema.safeParse(req.body);
    if (!parsed.success) {
      throw new BadRequestError(parsed.error.issues.map(i => i.message).join('; '));
    }

    const productId = getRequestProductId(req);
    const userId = getRequestUserId(req);
    const existing = await repo.getByUserId(userId, productId);
    const now = new Date().toISOString();

    const doc: UserSettingsDoc = {
      ...(existing ?? buildDefaultDoc(productId, userId)),
      settings: { ...(existing?.settings ?? {}), ...parsed.data.settings },
      updatedAt: now,
    };

    return repo.upsert(doc);
  });

  app.get('/settings/device/:deviceId', async req => {
    const { deviceId } = req.params as { deviceId: string };
    const productId = getRequestProductId(req);
    const userId = getRequestUserId(req);

    const existing = await repo.getByUserId(userId, productId);
    const doc = existing ?? buildDefaultDoc(productId, userId);
    const overrides = doc.deviceOverrides[deviceId] ?? {};

    return {
      deviceId,
      settings: { ...doc.settings, ...overrides },
      hasOverrides: Object.keys(overrides).length > 0,
    };
  });

  app.put('/settings/device/:deviceId', async req => {
    const { deviceId } = req.params as { deviceId: string };
    const parsed = SetDeviceOverridesSchema.safeParse(req.body);
    if (!parsed.success) {
      throw new BadRequestError(parsed.error.issues.map(i => i.message).join('; '));
    }

    const productId = getRequestProductId(req);
    const userId = getRequestUserId(req);
    const existing = await repo.getByUserId(userId, productId);
    const now = new Date().toISOString();

    const doc: UserSettingsDoc = {
      ...(existing ?? buildDefaultDoc(productId, userId)),
      deviceOverrides: {
        ...(existing?.deviceOverrides ?? {}),
        [deviceId]: parsed.data.overrides,
      },
      updatedAt: now,
    };

    await repo.upsert(doc);
    return { deviceId, overrides: doc.deviceOverrides[deviceId] };
  });

  app.delete('/settings/device/:deviceId', async req => {
    const { deviceId } = req.params as { deviceId: string };
    const productId = getRequestProductId(req);
    const userId = getRequestUserId(req);
    const existing = await repo.getByUserId(userId, productId);

    if (!existing) return { success: true, deviceId };

    const now = new Date().toISOString();
    const nextOverrides = { ...existing.deviceOverrides };
    delete nextOverrides[deviceId];

    await repo.upsert({
      ...existing,
      deviceOverrides: nextOverrides,
      updatedAt: now,
    });

    return { success: true, deviceId };
  });
}
