// ── Opslag van voorstellen (modelonderdelen én modeldocumenten) ──────────────
// Bewaart de voorstellen die externe AI-agenten via de MCP-server/REST-API
// indienen, zodat ze in de browser (tabblad "Te valideren") opgehaald en
// gevalideerd kunnen worden. Twee implementaties:
//
//  - SupabaseOpslag  → persistente opslag in een Supabase-project (PostgreSQL).
//                     Actief zodra SUPABASE_URL en SUPABASE_SERVICE_ROLE_KEY
//                     bestaan als omgevingsvariabelen. Betrouwbaar over koude
//                     starts en instanties heen.
//  - GeheugenOpslag  → best-effort fallback in het geheugen van de huidige
//                     serverinstantie (niet persistent), gebruikt wanneer geen
//                     Supabase-project is geconfigureerd.
//
// Beide bevatten enkel generieke modeltekst met {{parameters}} — nooit
// persoonsgegevens (Notary.AI is niet GDPR-conform; zie de richtlijnen).

import { maakServiceClient, heeftPersistenteOpslag, type AnyClient } from "@/lib/supabase/server";
import type { Wijzigingsvoorstel, ModeldocumentVoorstel } from "@/data/modeldocumenten";

export { heeftPersistenteOpslag };

export interface VoorstellenOpslag {
  // Modelonderdeel-voorstellen (clausules).
  voegToe(voorstel: Wijzigingsvoorstel): Promise<void>;
  lijst(): Promise<Wijzigingsvoorstel[]>;
  verwijder(id: string): Promise<void>;
  // Modeldocument-voorstellen (volledige modellen).
  voegModelToe(voorstel: ModeldocumentVoorstel): Promise<void>;
  lijstModellen(): Promise<ModeldocumentVoorstel[]>;
  verwijderModel(id: string): Promise<void>;
}

// ── In-geheugen fallback ─────────────────────────────────────────────────────

class GeheugenOpslag implements VoorstellenOpslag {
  private onderdelen: Wijzigingsvoorstel[] = [];
  private modellen: ModeldocumentVoorstel[] = [];

  async voegToe(voorstel: Wijzigingsvoorstel): Promise<void> {
    this.onderdelen.push(voorstel);
  }
  async lijst(): Promise<Wijzigingsvoorstel[]> {
    return [...this.onderdelen];
  }
  async verwijder(id: string): Promise<void> {
    this.onderdelen = this.onderdelen.filter((v) => v.id !== id);
  }
  async voegModelToe(voorstel: ModeldocumentVoorstel): Promise<void> {
    this.modellen.push(voorstel);
  }
  async lijstModellen(): Promise<ModeldocumentVoorstel[]> {
    return [...this.modellen];
  }
  async verwijderModel(id: string): Promise<void> {
    this.modellen = this.modellen.filter((v) => v.id !== id);
  }
}

// ── Persistente opslag via Supabase (PostgreSQL) ─────────────────────────────
// Vereiste tabellen (SQL, één keer uitvoeren in de Supabase SQL Editor):
//
//   create table voorstellen_onderdelen (
//     id        text primary key,
//     data      jsonb not null,
//     aangemaakt timestamptz default now()
//   );
//   create table voorstellen_modellen (
//     id        text primary key,
//     data      jsonb not null,
//     aangemaakt timestamptz default now()
//   );
//
// Met service_role key is geen RLS nodig; voeg optioneel toe:
//   alter table voorstellen_onderdelen enable row level security;
//   alter table voorstellen_modellen    enable row level security;

class SupabaseOpslag implements VoorstellenOpslag {
  private readonly sb: AnyClient;

  constructor(sb: AnyClient) {
    this.sb = sb;
  }

  async voegToe(voorstel: Wijzigingsvoorstel): Promise<void> {
    const { error } = await this.sb
      .from("voorstellen_onderdelen")
      .upsert({ id: voorstel.id, data: voorstel });
    if (error) throw new Error(`Supabase voegToe: ${error.message}`);
  }

  async lijst(): Promise<Wijzigingsvoorstel[]> {
    const { data, error } = await this.sb
      .from("voorstellen_onderdelen")
      .select("data")
      .order("aangemaakt");
    if (error) throw new Error(`Supabase lijst: ${error.message}`);
    return (data ?? []).map((r: { data: unknown }) => r.data as Wijzigingsvoorstel);
  }

  async verwijder(id: string): Promise<void> {
    const { error } = await this.sb
      .from("voorstellen_onderdelen")
      .delete()
      .eq("id", id);
    if (error) throw new Error(`Supabase verwijder: ${error.message}`);
  }

  async voegModelToe(voorstel: ModeldocumentVoorstel): Promise<void> {
    const { error } = await this.sb
      .from("voorstellen_modellen")
      .upsert({ id: voorstel.id, data: voorstel });
    if (error) throw new Error(`Supabase voegModelToe: ${error.message}`);
  }

  async lijstModellen(): Promise<ModeldocumentVoorstel[]> {
    const { data, error } = await this.sb
      .from("voorstellen_modellen")
      .select("data")
      .order("aangemaakt");
    if (error) throw new Error(`Supabase lijstModellen: ${error.message}`);
    return (data ?? []).map((r: { data: unknown }) => r.data as ModeldocumentVoorstel);
  }

  async verwijderModel(id: string): Promise<void> {
    const { error } = await this.sb
      .from("voorstellen_modellen")
      .delete()
      .eq("id", id);
    if (error) throw new Error(`Supabase verwijderModel: ${error.message}`);
  }
}

// ── Selectie van de actieve implementatie ────────────────────────────────────

function maakStandaardOpslag(): VoorstellenOpslag {
  const sb = maakServiceClient();
  return sb ? new SupabaseOpslag(sb) : new GeheugenOpslag();
}

let opslag: VoorstellenOpslag | null = null;

/**
 * Huidige opslagimplementatie. Standaard: persistente Supabase-store als die
 * is geconfigureerd (SUPABASE_URL/SUPABASE_SERVICE_ROLE_KEY), anders in-geheugen.
 */
export function voorstellenOpslag(): VoorstellenOpslag {
  if (!opslag) opslag = maakStandaardOpslag();
  return opslag;
}
