import { and, eq } from 'drizzle-orm';

import { db } from '@/lib/db';
import { berths } from '@/lib/db/schema/berths';
import { berthTenancies } from '@/lib/db/schema/tenancies';
import { clients } from '@/lib/db/schema/clients';
import { ports } from '@/lib/db/schema/ports';
import { yachts } from '@/lib/db/schema/yachts';
import { getCountryName } from '@/lib/i18n/countries';
import { NotFoundError } from '@/lib/errors';

export type ReservationAgreementContext = {
  client: {
    id: string;
    fullName: string;
    nationality: string | null;
  };
  yacht: {
    id: string;
    name: string;
    lengthFt: string | null;
    flag: string | null;
  };
  berth: {
    id: string;
    mooringNumber: string;
    area: string | null;
    lengthFt: string | null;
    priceCurrency: string;
  };
  reservation: {
    id: string;
    status: string;
    startDate: Date;
    endDate: Date | null;
    tenureType: string;
    termSummary: string;
    signedDate: string | null;
  };
  port: {
    name: string;
    defaultCurrency: string;
  };
  date: {
    today: string;
    year: string;
  };
};

/**
 * Build the merge-context shape used when generating a reservation agreement
 * document. Mirrors `buildEoiContext` for consistency: pure read-only,
 * tenant-scoped via `portId`, throws on missing rows.
 *
 * `termSummary` is a human-readable rendering of `tenureType` + dates that
 * templates can use as `{{reservation.termSummary}}` without needing date
 * formatting helpers in the template language.
 */
export async function buildReservationAgreementContext(
  tenancyId: string,
  portId: string,
): Promise<ReservationAgreementContext> {
  const reservation = await db.query.berthTenancies.findFirst({
    where: and(eq(berthTenancies.id, tenancyId), eq(berthTenancies.portId, portId)),
  });
  if (!reservation) throw new NotFoundError('Tenancy');

  const [client, yacht, berth, port] = await Promise.all([
    db.query.clients.findFirst({
      where: and(eq(clients.id, reservation.clientId), eq(clients.portId, portId)),
    }),
    db.query.yachts.findFirst({
      where: and(eq(yachts.id, reservation.yachtId), eq(yachts.portId, portId)),
    }),
    db.query.berths.findFirst({
      where: and(eq(berths.id, reservation.berthId), eq(berths.portId, portId)),
    }),
    db.query.ports.findFirst({ where: eq(ports.id, portId) }),
  ]);
  if (!client) throw new NotFoundError('Client');
  if (!yacht) throw new NotFoundError('Yacht');
  if (!berth) throw new NotFoundError('Berth');
  if (!port) throw new NotFoundError('Port');

  const start = reservation.startDate.toISOString().slice(0, 10);
  const end = reservation.endDate ? reservation.endDate.toISOString().slice(0, 10) : null;

  let termSummary: string;
  if (reservation.tenureType === 'permanent') {
    termSummary = `Permanent berth, commencing ${start}`;
  } else if (reservation.tenureType === 'fixed_term' && end) {
    termSummary = `Fixed term: ${start} to ${end}`;
  } else if (reservation.tenureType === 'seasonal' && end) {
    termSummary = `Seasonal: ${start} to ${end}`;
  } else {
    termSummary = `${reservation.tenureType} from ${start}`;
  }

  const now = new Date();
  return {
    client: {
      id: client.id,
      fullName: client.fullName,
      nationality: client.nationalityIso ? getCountryName(client.nationalityIso, 'en') : null,
    },
    yacht: {
      id: yacht.id,
      name: yacht.name,
      lengthFt: yacht.lengthFt,
      flag: yacht.flag,
    },
    berth: {
      id: berth.id,
      mooringNumber: berth.mooringNumber,
      area: berth.area,
      lengthFt: berth.lengthFt,
      priceCurrency: berth.priceCurrency,
    },
    reservation: {
      id: reservation.id,
      status: reservation.status,
      startDate: reservation.startDate,
      endDate: reservation.endDate,
      tenureType: reservation.tenureType,
      termSummary,
      signedDate: null,
    },
    port: {
      name: port.name,
      defaultCurrency: port.defaultCurrency,
    },
    date: {
      today: now.toISOString().slice(0, 10),
      year: String(now.getFullYear()),
    },
  };
}
