import { randomBytes } from 'crypto';
import { getRedis, REDIS_KEYS } from '../redis';
import { config } from '../config';
import type { DeliveryType } from './catalog';

export interface PickupPointDraft {
  id: string;
  name: string;
  address: string;
  city?: string;
  zip?: string;
}

export interface CourierAddressDraft {
  street: string;
  number: string;
  zip: string;
  city: string;
}

export interface InvoiceDraft {
  firstname: string;
  lastname: string;
  email: string;
  phone: string;
  invoiceIsCompany?: boolean;
  companyName?: string;
  vatin?: string;
  regon?: string;
}

export type CheckoutPaymentStatus = 'none' | 'pending' | 'paid' | 'failed';

export interface CheckoutDraft {
  id: string;
  cartSessionId: string;
  shippingMethodId?: string;
  pickupPoint?: PickupPointDraft;
  courierAddress?: CourierAddressDraft;
  paymentMethodId?: string;
  invoice?: InvoiceDraft;
  orderId?: number;
  orderReference?: string;
  paymentStatus: CheckoutPaymentStatus;
  createdAt: string;
  updatedAt: string;
}

function newId(): string {
  return randomBytes(16).toString('hex');
}

export async function createCheckoutDraft(cartSessionId: string): Promise<CheckoutDraft> {
  const now = new Date().toISOString();
  const draft: CheckoutDraft = {
    id: newId(),
    cartSessionId,
    paymentStatus: 'none',
    createdAt: now,
    updatedAt: now,
  };
  await saveCheckoutDraft(draft);
  return draft;
}

export async function getCheckoutDraft(id: string): Promise<CheckoutDraft | null> {
  const redis = getRedis();
  const raw = await redis.get(REDIS_KEYS.checkoutDraft(id));
  if (!raw) return null;
  return JSON.parse(raw) as CheckoutDraft;
}

export async function saveCheckoutDraft(draft: CheckoutDraft): Promise<void> {
  draft.updatedAt = new Date().toISOString();
  const redis = getRedis();
  await redis.setex(
    REDIS_KEYS.checkoutDraft(draft.id),
    config.checkout.draftTtlSec,
    JSON.stringify(draft),
  );
}

export function snapshotDraft(draft: CheckoutDraft) {
  const shipping = draft.shippingMethodId;
  let deliveryType: DeliveryType | undefined;
  if (shipping) {
    // resolved in service layer for snapshot
  }
  return {
    checkoutSessionId: draft.id,
    cartSessionId: draft.cartSessionId,
    shippingMethodId: draft.shippingMethodId ?? null,
    pickupPoint: draft.pickupPoint ?? null,
    courierAddress: draft.courierAddress ?? null,
    paymentMethodId: draft.paymentMethodId ?? null,
    invoice: draft.invoice ?? null,
    orderId: draft.orderId ?? null,
    orderReference: draft.orderReference ?? null,
    paymentStatus: draft.paymentStatus,
    createdAt: draft.createdAt,
    updatedAt: draft.updatedAt,
    deliveryType,
  };
}
