import { db } from '../../config/database.js';
import { kurzy, ucastnici, registracie, prilohy } from '../../db/schema.js';
import { and, desc, eq, sql } from 'drizzle-orm';
import { NotFoundError } from '../../utils/errors.js';

export const getAllRegistracie = async (kurzId = null) => {
  const conditions = kurzId ? [eq(registracie.kurzId, kurzId)] : [];

  const result = await db
    .select({
      id: registracie.id,
      kurzId: registracie.kurzId,
      ucastnikId: registracie.ucastnikId,
      formaKurzu: registracie.formaKurzu,
      fakturaCislo: registracie.fakturaCislo,
      fakturaVystavena: registracie.fakturaVystavena,
      zaplatene: registracie.zaplatene,
      stav: registracie.stav,
      poznamka: registracie.poznamka,
      createdAt: registracie.createdAt,
      kurzNazov: kurzy.nazov,
      kurzTyp: kurzy.typKurzu,
      kurzDatumOd: kurzy.datumOd,
      kurzDatumDo: kurzy.datumDo,
      ucastnikMeno: ucastnici.meno,
      ucastnikPriezvisko: ucastnici.priezvisko,
      ucastnikEmail: ucastnici.email,
      ucastnikFirma: ucastnici.firma,
    })
    .from(registracie)
    .leftJoin(kurzy, eq(registracie.kurzId, kurzy.id))
    .leftJoin(ucastnici, eq(registracie.ucastnikId, ucastnici.id))
    .where(conditions.length > 0 ? and(...conditions) : undefined)
    .orderBy(desc(kurzy.datumOd), desc(registracie.createdAt));

  return result;
};

export const getRegistraciaById = async (id) => {
  const [reg] = await db
    .select({
      id: registracie.id,
      kurzId: registracie.kurzId,
      ucastnikId: registracie.ucastnikId,
      formaKurzu: registracie.formaKurzu,
      fakturaCislo: registracie.fakturaCislo,
      fakturaVystavena: registracie.fakturaVystavena,
      zaplatene: registracie.zaplatene,
      stav: registracie.stav,
      poznamka: registracie.poznamka,
      createdAt: registracie.createdAt,
      kurzNazov: kurzy.nazov,
      kurzTyp: kurzy.typKurzu,
      ucastnikMeno: ucastnici.meno,
      ucastnikPriezvisko: ucastnici.priezvisko,
      ucastnikEmail: ucastnici.email,
    })
    .from(registracie)
    .leftJoin(kurzy, eq(registracie.kurzId, kurzy.id))
    .leftJoin(ucastnici, eq(registracie.ucastnikId, ucastnici.id))
    .where(eq(registracie.id, id))
    .limit(1);

  if (!reg) {
    throw new NotFoundError('Registrácia nenájdená');
  }

  return reg;
};

export const createRegistracia = async (data) => {
  const [newReg] = await db
    .insert(registracie)
    .values({
      kurzId: data.kurzId,
      ucastnikId: data.ucastnikId,
      formaKurzu: data.formaKurzu || 'prezencne',
      fakturaCislo: data.fakturaCislo || null,
      fakturaVystavena: data.fakturaVystavena || false,
      zaplatene: data.zaplatene || false,
      stav: data.stav || 'registrovany',
      poznamka: data.poznamka || null,
    })
    .returning();

  return newReg;
};

export const updateRegistracia = async (id, data) => {
  await getRegistraciaById(id);

  const [updated] = await db
    .update(registracie)
    .set({
      ...data,
      updatedAt: new Date(),
    })
    .where(eq(registracie.id, id))
    .returning();

  return updated;
};

export const deleteRegistracia = async (id) => {
  await getRegistraciaById(id);
  await db.delete(registracie).where(eq(registracie.id, id));
  return { success: true, message: 'Registrácia bola odstránená' };
};

export const getCombinedTableData = async () => {
  const result = await db
    .select({
      id: registracie.id,
      ucastnikId: ucastnici.id,
      titul: ucastnici.titul,
      meno: ucastnici.meno,
      priezvisko: ucastnici.priezvisko,
      email: ucastnici.email,
      telefon: ucastnici.telefon,
      firma: ucastnici.firma,
      firmaIco: ucastnici.firmaIco,
      firmaDic: ucastnici.firmaDic,
      firmaIcDph: ucastnici.firmaIcDph,
      firmaSidlo: ucastnici.firmaSidlo,
      mesto: ucastnici.mesto,
      ulica: ucastnici.ulica,
      psc: ucastnici.psc,
      needsFollowup: ucastnici.needsFollowup,
      kurzId: kurzy.id,
      kurzNazov: kurzy.nazov,
      kurzTyp: kurzy.typKurzu,
      kurzFarba: kurzy.farba,
      datumOd: kurzy.datumOd,
      datumDo: kurzy.datumDo,
      formaKurzu: registracie.formaKurzu,
      fakturaCislo: registracie.fakturaCislo,
      fakturaVystavena: registracie.fakturaVystavena,
      zaplatene: registracie.zaplatene,
      stav: registracie.stav,
      poznamka: registracie.poznamka,
      createdAt: registracie.createdAt,
      dokumentyCount: sql`(SELECT COUNT(*) FROM prilohy WHERE registracia_id = ${registracie.id})::int`,
      hasCertificate: sql`(SELECT COUNT(*) > 0 FROM prilohy WHERE registracia_id = ${registracie.id} AND typ_prilohy = 'certifikat')::boolean`,
    })
    .from(registracie)
    .innerJoin(ucastnici, eq(registracie.ucastnikId, ucastnici.id))
    .innerJoin(kurzy, eq(registracie.kurzId, kurzy.id))
    .orderBy(desc(kurzy.datumOd), desc(registracie.createdAt));

  return result;
};

export const updateField = async (registrationId, field, value) => {
  const ucastnikFields = ['titul', 'meno', 'priezvisko', 'email', 'telefon', 'firma', 'firmaIco', 'firmaDic', 'firmaIcDph', 'firmaSidlo', 'mesto', 'ulica', 'psc', 'needsFollowup'];
  const registraciaFields = ['formaKurzu', 'fakturaCislo', 'fakturaVystavena', 'zaplatene', 'stav', 'poznamka', 'kurzId'];

  const [reg] = await db
    .select({ ucastnikId: registracie.ucastnikId })
    .from(registracie)
    .where(eq(registracie.id, registrationId))
    .limit(1);

  if (!reg) {
    throw new NotFoundError('Registrácia nenájdená');
  }

  if (ucastnikFields.includes(field)) {
    await db
      .update(ucastnici)
      .set({ [field]: value, updatedAt: new Date() })
      .where(eq(ucastnici.id, reg.ucastnikId));
  } else if (registraciaFields.includes(field)) {
    await db
      .update(registracie)
      .set({ [field]: value, updatedAt: new Date() })
      .where(eq(registracie.id, registrationId));
  } else {
    throw new Error(`Unknown field: ${field}`);
  }

  return { success: true };
};

export const getPrilohyByRegistracia = async (registraciaId) => {
  const result = await db
    .select()
    .from(prilohy)
    .where(eq(prilohy.registraciaId, registraciaId))
    .orderBy(desc(prilohy.createdAt));

  return result;
};

export const createPriloha = async (data) => {
  const [newPriloha] = await db
    .insert(prilohy)
    .values({
      registraciaId: data.registraciaId,
      nazovSuboru: data.nazovSuboru,
      typPrilohy: data.typPrilohy || 'ine',
      cestaKSuboru: data.cestaKSuboru,
      mimeType: data.mimeType || null,
      velkostSuboru: data.velkostSuboru || null,
      popis: data.popis || null,
    })
    .returning();

  return newPriloha;
};

export const deletePriloha = async (id) => {
  const [priloha] = await db
    .select()
    .from(prilohy)
    .where(eq(prilohy.id, id))
    .limit(1);

  if (!priloha) {
    throw new NotFoundError('Príloha nenájdená');
  }

  await db.delete(prilohy).where(eq(prilohy.id, id));
  return { success: true, filePath: priloha.cestaKSuboru };
};

export const getPrilohaById = async (id) => {
  const [priloha] = await db
    .select()
    .from(prilohy)
    .where(eq(prilohy.id, id))
    .limit(1);

  return priloha || null;
};
