'use server';

import { revalidatePath } from 'next/cache';
import { z } from 'zod';
import { ConflictError, forVenue, getDb, NotFoundError, venueSettingsSchema } from '@pintrush/db';
import { actionError, actionOk, CONFLICT_MESSAGE, type ActionResult } from '@/components/host/action-result';
import { isOwner, requireHost } from '@/lib/auth/session';
import { resetRoomTvLink, visiblePacks } from '../../_lib/data';

const OWNER_ONLY = 'Only the venue owner can change settings. Ask your owner to make this change.';

const SettingsFormSchema = z.object({
  enabled: z.boolean(),
  packKey: z.string().min(1).max(64),
  mergeSolos: z.boolean(),
  schedule: z.string().max(20_000),
  expectedVersion: z.coerce.number().int().min(0),
});

export async function saveVenueSettings(_prev: ActionResult, formData: FormData): Promise<ActionResult> {
  const ctx = await requireHost();
  if (!isOwner(ctx)) return actionError(OWNER_ONLY);

  const form = SettingsFormSchema.safeParse({
    enabled: formData.get('enabled') === 'on',
    packKey: formData.get('packKey') ?? '',
    mergeSolos: formData.get('mergeSolos') === 'on',
    schedule: formData.get('schedule') ?? '[]',
    expectedVersion: formData.get('expectedVersion'),
  });
  if (!form.success) return actionError('Some settings could not be read. Reload the page and try again.');

  let schedule: unknown;
  try {
    schedule = JSON.parse(form.data.schedule);
  } catch {
    return actionError('The opening hours could not be read. Reload the page and try again.');
  }
  const settings = venueSettingsSchema.safeParse({
    alwaysOn: { enabled: form.data.enabled, packKey: form.data.packKey, schedule },
    mergeSolos: form.data.mergeSolos,
  });
  if (!settings.success) {
    const issue = settings.error.issues[0];
    return actionError(issue ? `Opening hours: ${issue.message}` : 'Check the opening hours.', { schedule: issue?.message ?? 'Invalid' });
  }
  if (settings.data.alwaysOn.enabled && settings.data.alwaysOn.schedule.length === 0) {
    return actionError('Add opening hours for at least one day, or turn always-on off.', { schedule: 'Add at least one opening window.' });
  }
  const packs = await visiblePacks(ctx.venue.id);
  if (!packs.some((p) => p.key === settings.data.alwaysOn.packKey)) {
    return actionError('That question pack is not available. Pick another one.', { packKey: 'Pick an available pack.' });
  }

  try {
    await forVenue(getDb(), ctx.venue.id).venue.updateSettings(settings.data, form.data.expectedVersion);
  } catch (err) {
    if (err instanceof ConflictError) return actionError(CONFLICT_MESSAGE);
    console.error('[host] save settings failed', err);
    return actionError('Your settings could not be saved. Please try again.');
  }
  revalidatePath('/host', 'layout');
  return actionOk(
    settings.data.alwaysOn.enabled
      ? 'Saved. Always-on follows the new hours within about 15 seconds.'
      : 'Saved. Always-on is off — tonight’s game ends within about 15 seconds if it was running.',
  );
}

export async function resetTvLink(_prev: ActionResult, formData: FormData): Promise<ActionResult> {
  const ctx = await requireHost();
  if (!isOwner(ctx)) return actionError('Only the venue owner can reset TV links.');
  const roomId = String(formData.get('roomId') ?? '');
  try {
    const room = await resetRoomTvLink(ctx.venue.id, roomId);
    revalidatePath('/host', 'layout');
    return actionOk(`New TV link created for ${room.name}. TVs using the old link stop working the next time they reconnect — open the new link from the dashboard on each TV.`);
  } catch (err) {
    if (err instanceof NotFoundError) return actionError('That room no longer exists.');
    console.error('[host] reset TV link failed', err);
    return actionError('The TV link could not be reset. Please try again.');
  }
}
