import { and, eq, asc, isNull } from "drizzle-orm";
import { db } from "@/db";
import { vehicles, equipment } from "@/db/schema/assets";
import { brigades } from "@/db/schema/brigades";
import { vehicleTemplates } from "@/db/schema/templates";
import { equipmentCategories } from "@/db/schema/equipment-categories";
import { merkmale, merkmalOptionen } from "@/db/schema/merkmale";
import { merkmalValues } from "@/db/schema/merkmal-values";
import type { StatusKey } from "@/components/ui/badge";
import type { EntityTyp } from "@/lib/search/types";
import type { MerkmalRow } from "./merkmale";

/**
 * Lese-Queries für die drei Detailseiten (Workstream 8). READ-ONLY und
 * wehrübergreifend (das `(app)`-Gruppen-Gate aus Phase 2 schützt; die Seiten
 * rufen zusätzlich `requireSession()`). Alle IDs sind UUIDs (`string`).
 */

/** Verlinktes Wehr-Kärtchen (Kontakt out-of-band, kein Borrow-Workflow). */
export interface BrigadeCard {
  id: string;
  name: string;
  art: string;
  strasse: string | null;
  plz: string | null;
  ort: string | null;
  wehrfuehrer: string | null;
  telefon: string | null;
  email: string | null;
}

/** Ein verlinktes Beladungs-Gerät eines Fahrzeugs. */
export interface BeladungItem {
  id: string;
  name: string;
  status: StatusKey;
  kategorie: string;
}

export interface FahrzeugDetail {
  id: string;
  name: string;
  funkrufname: string | null;
  status: StatusKey;
  notiz: string | null;
  templateName: string | null;
  merkmale: MerkmalRow[];
  beladung: BeladungItem[];
  wehr: BrigadeCard | null;
}

export interface GeraetDetail {
  id: string;
  name: string;
  status: StatusKey;
  kategorie: string;
  merkmale: MerkmalRow[];
  /** Zugeordnetes Fahrzeug oder `null` => „im Gerätehaus". */
  fahrzeug: { id: string; name: string } | null;
  wehr: BrigadeCard | null;
}

export interface WehrDetail extends BrigadeCard {
  fahrzeuge: { id: string; name: string; funkrufname: string | null; status: StatusKey }[];
  geraeteImHaus: { id: string; name: string; status: StatusKey }[];
}

/**
 * Lädt die typisierten Merkmalwerte einer Entität (joint
 * `merkmal_values` ↔ `merkmale` ↔ `merkmal_optionen` über
 * `merkmal_optionen.wert = merkmal_values.value_text`, damit enum-Werte ihr
 * Anzeige-Label erhalten). Sortiert nach `merkmale.name`.
 */
export async function loadMerkmalRows(
  entityTyp: EntityTyp,
  entityId: string,
): Promise<MerkmalRow[]> {
  const rows = await db
    .select({
      merkmalId: merkmale.id,
      name: merkmale.name,
      typ: merkmale.typ,
      einheit: merkmale.einheit,
      valueNum: merkmalValues.valueNum,
      valueText: merkmalValues.valueText,
      valueBool: merkmalValues.valueBool,
      enumLabel: merkmalOptionen.label,
    })
    .from(merkmalValues)
    .innerJoin(merkmale, eq(merkmale.id, merkmalValues.merkmalId))
    .leftJoin(
      merkmalOptionen,
      and(
        eq(merkmalOptionen.merkmalId, merkmale.id),
        eq(merkmalOptionen.wert, merkmalValues.valueText),
      ),
    )
    .where(
      and(
        eq(merkmalValues.entityTyp, entityTyp),
        eq(merkmalValues.entityId, entityId),
      ),
    )
    .orderBy(asc(merkmale.name));

  return rows.map((r, i) => ({
    merkmalId: r.merkmalId,
    name: r.name,
    typ: r.typ,
    einheit: r.einheit,
    reihenfolge: i,
    valueNum: r.valueNum,
    valueText: r.valueText,
    valueBool: r.valueBool,
    enumLabel: r.enumLabel,
  }));
}

/** Wehr-Kärtchen (Stammdaten + Kontakt). `null`, wenn nicht gefunden. */
export async function getBrigadeCard(id: string): Promise<BrigadeCard | null> {
  const [b] = await db
    .select({
      id: brigades.id,
      name: brigades.name,
      art: brigades.art,
      strasse: brigades.strasse,
      plz: brigades.plz,
      ort: brigades.ort,
      wehrfuehrer: brigades.wehrfuehrer,
      telefon: brigades.telefon,
      email: brigades.email,
    })
    .from(brigades)
    .where(eq(brigades.id, id))
    .limit(1);
  return b ?? null;
}

export async function getFahrzeugDetail(id: string): Promise<FahrzeugDetail | null> {
  const [v] = await db
    .select({
      id: vehicles.id,
      brigadeId: vehicles.brigadeId,
      name: vehicles.name,
      funkrufname: vehicles.funkrufname,
      status: vehicles.status,
      notiz: vehicles.notiz,
      templateName: vehicleTemplates.name,
    })
    .from(vehicles)
    .leftJoin(vehicleTemplates, eq(vehicleTemplates.id, vehicles.templateId))
    .where(eq(vehicles.id, id))
    .limit(1);
  if (!v) return null;

  const [rows, beladung, wehr] = await Promise.all([
    loadMerkmalRows("vehicle", id),
    db
      .select({
        id: equipment.id,
        name: equipment.name,
        status: equipment.status,
        kategorie: equipmentCategories.name,
      })
      .from(equipment)
      .innerJoin(
        equipmentCategories,
        eq(equipmentCategories.id, equipment.categoryId),
      )
      .where(eq(equipment.vehicleId, id))
      .orderBy(asc(equipment.name)),
    getBrigadeCard(v.brigadeId),
  ]);

  return {
    id: v.id,
    name: v.name,
    funkrufname: v.funkrufname,
    status: v.status,
    notiz: v.notiz,
    templateName: v.templateName,
    merkmale: rows,
    beladung,
    wehr,
  };
}

export async function getGeraetDetail(id: string): Promise<GeraetDetail | null> {
  const [g] = await db
    .select({
      id: equipment.id,
      brigadeId: equipment.brigadeId,
      name: equipment.name,
      status: equipment.status,
      kategorie: equipmentCategories.name,
      vehicleId: equipment.vehicleId,
      vehicleName: vehicles.name,
    })
    .from(equipment)
    .innerJoin(equipmentCategories, eq(equipmentCategories.id, equipment.categoryId))
    .leftJoin(vehicles, eq(vehicles.id, equipment.vehicleId))
    .where(eq(equipment.id, id))
    .limit(1);
  if (!g) return null;

  const [rows, wehr] = await Promise.all([
    loadMerkmalRows("equipment", id),
    getBrigadeCard(g.brigadeId),
  ]);

  return {
    id: g.id,
    name: g.name,
    status: g.status,
    kategorie: g.kategorie,
    merkmale: rows,
    fahrzeug:
      g.vehicleId && g.vehicleName
        ? { id: g.vehicleId, name: g.vehicleName }
        : null,
    wehr,
  };
}

export async function getWehrDetail(id: string): Promise<WehrDetail | null> {
  const card = await getBrigadeCard(id);
  if (!card) return null;

  const [fahrzeuge, geraeteImHaus] = await Promise.all([
    db
      .select({
        id: vehicles.id,
        name: vehicles.name,
        funkrufname: vehicles.funkrufname,
        status: vehicles.status,
      })
      .from(vehicles)
      .where(eq(vehicles.brigadeId, id))
      .orderBy(asc(vehicles.name)),
    db
      .select({
        id: equipment.id,
        name: equipment.name,
        status: equipment.status,
      })
      .from(equipment)
      .where(and(eq(equipment.brigadeId, id), isNull(equipment.vehicleId)))
      .orderBy(asc(equipment.name)),
  ]);

  return { ...card, fahrzeuge, geraeteImHaus };
}
