import BreadCrumbLink from "@/layouts/shared/page.breadcrumbLink";
import { listPrompts } from "@/lib/features/chatbot/prompt/query";
import PromptsClientPage from "./_client";

export const handle = {
  breadcrumb: () => (
    <BreadCrumbLink links={[{ label: "Chatbot", to: "/admin/chatbot" }, { label: "Prompts" }]} />
  ),
};

export async function loader({ request }: { request: Request }) {
  const headers = { Cookie: request.headers.get("Cookie") ?? "" };
  const res: any = await listPrompts(0, 200, headers);
  const rows: any[] = res?.data?.items ?? res?.data ?? [];

  const ttsRow              = rows.find((r: any) => r.prompt_key === "voice_tts_config");
  const charRow             = rows.find((r: any) => r.prompt_key === "voice_character_prompt");
  const recordingRow        = rows.find((r: any) => r.prompt_key === "voice_recording_config");
  const activeTextRow       = rows.find((r: any) => r.prompt_key === "voice_active_text_prompts");
  const voiceCommandsRow    = rows.find((r: any) => r.prompt_key === "voice_commands");
  const experiments         = rows.filter((r: any) => r.prompt_key?.startsWith("voice_exp_"));

  // Plain-text voice prompts managed via the Voice Prompts table (not the production keys or JSON configs)
  const PRODUCTION_VOICE_KEYS = new Set(["voice_tts_config", "voice_character_prompt", "voice_recording_config", "voice_active_text_prompts", "voice_commands"]);
  const voiceTextPrompts = rows.filter(
    (r: any) => r.prompt_key?.startsWith("voice_") &&
                !PRODUCTION_VOICE_KEYS.has(r.prompt_key) &&
                !r.prompt_key.startsWith("voice_exp_"),
  );

  let ttsConfig = { rate: 1.0, pitch: 1.0, volume: 1.0, voiceURI: "", voiceName: "", genderHint: "", ignoreBackgroundNoise: false, allowInterrupt: false };
  if (ttsRow?.prompt_value) {
    try { ttsConfig = { ...ttsConfig, ...JSON.parse(ttsRow.prompt_value) }; } catch { /* ignore */ }
  }

  let recordingConfig = {
    minRecordMs: 1200, silenceDuration: 2000, maxRecordMs: 25000, calibrationMs: 800,
    noiseMarginDefault: 12, noiseMarginHigh: 28, bargeInFrames: 3, levelFps: 15,
  };
  if (recordingRow?.prompt_value) {
    try { recordingConfig = { ...recordingConfig, ...JSON.parse(recordingRow.prompt_value) }; } catch { /* ignore */ }
  }

  let voiceCommandsData: { commands: Array<{ command: string; phrases: string[]; response: string }> } = { commands: [] };
  if (voiceCommandsRow?.prompt_value) {
    try { voiceCommandsData = JSON.parse(voiceCommandsRow.prompt_value); } catch { /* ignore */ }
  }

  // Parse active text prompt IDs + full rows from stored JSON array
  let activeTextPromptIds: string[] = [];
  let activeTextPromptRows: Array<{ id: string; prompt_key: string; prompt_name: string; prompt_value: string; created_by: string; updated_by: string }> = [];
  if (activeTextRow?.prompt_value) {
    try {
      const parsed = JSON.parse(activeTextRow.prompt_value);
      if (Array.isArray(parsed)) {
        activeTextPromptIds = parsed.map((r: any) => r.id).filter(Boolean);
        activeTextPromptRows = parsed
          .filter((r: any) => r.id)
          .map((r: any) => ({
            id:           r.id           ?? "",
            prompt_key:   r.prompt_key   ?? "",
            prompt_name:  r.prompt_name  ?? "",
            prompt_value: r.prompt_value ?? "",
            created_by:   r.created_by   ?? "",
            updated_by:   r.updated_by   ?? "",
          }));
      }
    } catch { /* ignore */ }
  }

  // Merge: if original prompt rows were deleted after being toggled active,
  // the snapshot in voice_active_text_prompts still has their data — include them
  // so the table never shows (0) while the badge says "N active in production".
  const existingIds = new Set(voiceTextPrompts.map((r: any) => r.id));
  const mergedVoiceTextPrompts = [
    ...voiceTextPrompts,
    ...activeTextPromptRows.filter((r) => !existingIds.has(r.id)),
  ];

  return {
    data: rows,
    total: res?.total ?? rows.length,
    voiceConfig: {
      ttsConfigId:              ttsRow?.id ?? null,
      charPromptId:             charRow?.id ?? null,
      recordingConfigId:        recordingRow?.id ?? null,
      activeTextPromptConfigId: activeTextRow?.id ?? null,
      voiceCommandsConfigId:    voiceCommandsRow?.id ?? null,
      voiceCommandsData,
      activeTextPromptIds,
      ttsConfig,
      recordingConfig,
      activeVoiceName:          ttsConfig.voiceName || ttsConfig.voiceURI || null,
      activeCharPrompt:         charRow?.prompt_name ?? null,
      experiments,
      voiceTextPrompts:         mergedVoiceTextPrompts,
      // Minimal info for each production record so the Voice tab can show them
      productionRecords: {
        tts:       ttsRow       ? { id: ttsRow.id,        name: ttsRow.prompt_name,        key: "voice_tts_config"          } : null,
        char:      charRow      ? { id: charRow.id,        name: charRow.prompt_name,        key: "voice_character_prompt"    } : null,
        recording: recordingRow ? { id: recordingRow.id,   name: recordingRow.prompt_name,   key: "voice_recording_config"    } : null,
        active:    activeTextRow? { id: activeTextRow.id,  name: activeTextRow.prompt_name,  key: "voice_active_text_prompts" } : null,
      },
    },
  };
}

export default function PromptsPage({
  loaderData,
}: {
  loaderData: {
    data: any[];
    total: number;
    voiceConfig: {
      ttsConfigId:              string | null;
      charPromptId:             string | null;
      recordingConfigId:        string | null;
      activeTextPromptConfigId: string | null;
      voiceCommandsConfigId:    string | null;
      voiceCommandsData:        { commands: Array<{ command: string; phrases: string[]; response: string }> };
      activeTextPromptIds:      string[];
      ttsConfig:                { rate: number; pitch: number; volume: number; voiceURI: string; voiceName: string; genderHint: string; ignoreBackgroundNoise: boolean; allowInterrupt: boolean };
      recordingConfig:          { minRecordMs: number; silenceDuration: number; maxRecordMs: number; calibrationMs: number; noiseMarginDefault: number; noiseMarginHigh: number; bargeInFrames: number; levelFps: number };
      activeVoiceName:          string | null;
      activeCharPrompt:         string | null;
      experiments:              Array<{ id: string; prompt_name: string; prompt_key: string; prompt_value: string; created_at?: string; updated_at?: string }>;
      voiceTextPrompts:         Array<{ id: string; prompt_name: string; prompt_key: string; prompt_value: string; created_by: string; updated_by: string }>;
      productionRecords: {
        tts:       { id: string; name: string; key: string } | null;
        char:      { id: string; name: string; key: string } | null;
        recording: { id: string; name: string; key: string } | null;
        active:    { id: string; name: string; key: string } | null;
      };
    };
  };
}) {
  return (
    <PromptsClientPage
      tableProps={{ data: loaderData.data, totalRows: loaderData.total }}
      voiceConfig={loaderData.voiceConfig}
    />
  );
}
