import { eq } from 'drizzle-orm';
import { z } from 'zod';
import type { DrizzleClient } from '@/server/db/client';
import { promo } from '@/server/db/schema';
import type { FactoryOperationHandler, FactoryStore } from './core';

const inputSchema = z.object({
  key: z.uuid(),
  code: z
    .string()
    .trim()
    .min(3)
    .max(40)
    .transform((value) => value.toUpperCase()),
  dealId: z.uuid(),
  validity: z.enum(['valid', 'expired']).default('valid'),
  valueBps: z.number().int().min(1).max(9_000).default(500),
});

export function promoValidityWindow(validity: 'valid' | 'expired', now = new Date()) {
  return validity === 'valid'
    ? {
        startsAt: new Date(now.getTime() - 60_000),
        endsAt: new Date(now.getTime() + 7 * 86_400_000),
      }
    : {
        startsAt: new Date(now.getTime() - 7 * 86_400_000),
        endsAt: new Date(now.getTime() - 86_400_000),
      };
}

export function createPromotionFactoryHandlers(input: {
  db: DrizzleClient;
  store: FactoryStore;
}): Record<string, FactoryOperationHandler> {
  const { db, store } = input;
  return {
    createPromotion: {
      dependencyOrder: 35,
      reserve: (raw) => ({ kind: 'promotion', id: inputSchema.parse(raw).key }),
      async execute({ runId, input: raw }) {
        const parsed = inputSchema.parse(raw);
        if (!(await store.findOwned(runId, 'deal', parsed.dealId)))
          throw new Error('deal is not owned by factory run');
        const window = promoValidityWindow(parsed.validity);
        const rules = { scope: { kind: 'deals', dealIds: [parsed.dealId] }, eligibility: {} };
        await db.insert(promo).values({
          id: parsed.key,
          code: parsed.code,
          kind: 'percentage',
          valueBps: parsed.valueBps,
          currency: 'ILS',
          scope: rules.scope,
          eligibility: {},
          funder: 'vendor',
          perUserCap: 99,
          startsAt: window.startsAt,
          endsAt: window.endsAt,
          active: true,
          status: 'active',
          validFrom: window.startsAt,
          validUntil: window.endsAt,
          rulesJson: rules,
          description: `E2E factory ${runId}`,
        });
        return {
          entity: { kind: 'promotion', id: parsed.key },
          result: {
            promotionId: parsed.key,
            code: parsed.code,
            dealId: parsed.dealId,
            validity: parsed.validity,
          },
        };
      },
      async read({ entity }) {
        const [row] = await db
          .select({
            promotionId: promo.id,
            code: promo.code,
            status: promo.status,
            startsAt: promo.startsAt,
            endsAt: promo.endsAt,
            valueBps: promo.valueBps,
            rulesJson: promo.rulesJson,
            redemptionCount: promo.redemptionCount,
          })
          .from(promo)
          .where(eq(promo.id, entity.entityId))
          .limit(1);
        if (!row) throw new Error('Factory promotion missing');
        return {
          ...row,
          startsAt: row.startsAt?.toISOString() ?? null,
          endsAt: row.endsAt?.toISOString() ?? null,
        };
      },
      async cleanup({ entity }) {
        await db.delete(promo).where(eq(promo.id, entity.entityId));
      },
    },
  };
}
